com.alicizax.unity.framework/Runtime/UI/Manager/UIService.Open.cs

264 lines
8.5 KiB
C#
Raw Normal View History

2025-09-05 19:46:30 +08:00
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
2025-09-05 19:46:30 +08:00
using AlicizaX;
using Cysharp.Threading.Tasks;
namespace AlicizaX.UI.Runtime
{
readonly struct LayerData
{
public readonly List<UIMetadata> OrderList; // 维护插入顺序
public readonly HashSet<RuntimeTypeHandle> HandleSet; // O(1)存在性检查
2025-12-24 20:44:36 +08:00
public readonly Dictionary<RuntimeTypeHandle, int> IndexMap; // O(1)索引查找
2025-09-05 19:46:30 +08:00
public LayerData(int initialCapacity)
{
OrderList = new List<UIMetadata>(initialCapacity);
HandleSet = new HashSet<RuntimeTypeHandle>();
2025-12-24 20:44:36 +08:00
IndexMap = new Dictionary<RuntimeTypeHandle, int>(initialCapacity);
2025-09-05 19:46:30 +08:00
}
}
internal sealed partial class UIService
2025-09-05 19:46:30 +08:00
{
private readonly LayerData[] _openUI = new LayerData[(int)UILayer.All];
2025-11-13 17:46:20 +08:00
private async UniTask<UIBase> ShowUIImplAsync(UIMetadata metaInfo, params object[] userDatas)
2025-09-05 19:46:30 +08:00
{
2025-11-13 17:46:20 +08:00
CreateMetaUI(metaInfo);
await UIHolderFactory.CreateUIResourceAsync(metaInfo, UICacheLayer);
2026-03-17 17:15:31 +08:00
if (metaInfo.View == null || metaInfo.State == UIState.Uninitialized || metaInfo.State == UIState.Destroyed)
{
return null;
}
2025-11-13 17:46:20 +08:00
FinalizeShow(metaInfo, userDatas);
await UpdateVisualState(metaInfo, metaInfo.CancellationToken);
2025-11-13 17:46:20 +08:00
return metaInfo.View;
}
private UIBase ShowUIImplSync(UIMetadata metaInfo, params object[] userDatas)
{
CreateMetaUI(metaInfo);
UIHolderFactory.CreateUIResourceSync(metaInfo, UICacheLayer);
2026-03-17 17:15:31 +08:00
if (metaInfo.View == null || metaInfo.State == UIState.Uninitialized || metaInfo.State == UIState.Destroyed)
{
return null;
}
2025-11-13 17:46:20 +08:00
FinalizeShow(metaInfo, userDatas);
UpdateVisualState(metaInfo).Forget();
return metaInfo.View;
2025-09-05 19:46:30 +08:00
}
private async UniTask CloseUIImpl(UIMetadata meta, bool force)
{
2026-03-17 17:15:31 +08:00
if (meta.State == UIState.Uninitialized)
{
return;
}
if (meta.State == UIState.CreatedUI)
{
meta.CancelAsyncOperations();
meta.Dispose();
return;
}
if (meta.State == UIState.Loaded || meta.State == UIState.Initialized)
2025-09-05 19:46:30 +08:00
{
2026-03-17 17:15:31 +08:00
meta.CancelAsyncOperations();
Pop(meta);
SortWindowVisible(meta.MetaInfo.UILayer);
SortWindowDepth(meta.MetaInfo.UILayer);
meta.View.Visible = false;
CacheWindow(meta, force);
2025-09-05 19:46:30 +08:00
return;
}
2025-11-13 17:46:20 +08:00
meta.CancelAsyncOperations();
2025-09-05 19:46:30 +08:00
await meta.View.InternalClose();
2026-03-17 17:15:31 +08:00
if (meta.State != UIState.Closed)
{
return;
}
2025-09-05 19:46:30 +08:00
Pop(meta);
SortWindowVisible(meta.MetaInfo.UILayer);
SortWindowDepth(meta.MetaInfo.UILayer);
CacheWindow(meta, force);
}
private UIBase GetUIImpl(UIMetadata meta)
{
return meta.View;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2025-11-13 17:46:20 +08:00
private void CreateMetaUI(UIMetadata meta)
2025-09-05 19:46:30 +08:00
{
if (meta.State == UIState.Uninitialized) meta.CreateUI();
}
2025-11-13 17:46:20 +08:00
private void FinalizeShow(UIMetadata meta, object[] userDatas)
2025-09-05 19:46:30 +08:00
{
if (meta.InCache)
{
RemoveFromCache(meta.MetaInfo.RuntimeTypeHandle);
Push(meta);
}
else
{
switch (meta.State)
{
case UIState.Loaded:
Push(meta);
break;
2026-03-17 17:15:31 +08:00
case UIState.Opening:
case UIState.Closing:
2025-09-05 19:46:30 +08:00
case UIState.Opened:
MoveToTop(meta);
break;
}
}
meta.View.RefreshParams(userDatas);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Push(UIMetadata meta)
{
ref var layer = ref _openUI[meta.MetaInfo.UILayer];
if (layer.HandleSet.Add(meta.MetaInfo.RuntimeTypeHandle))
{
2025-12-24 20:44:36 +08:00
int index = layer.OrderList.Count;
2025-09-05 19:46:30 +08:00
layer.OrderList.Add(meta);
2025-12-24 20:44:36 +08:00
layer.IndexMap[meta.MetaInfo.RuntimeTypeHandle] = index;
2025-09-05 19:46:30 +08:00
UpdateLayerParent(meta);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Pop(UIMetadata meta)
{
ref var layer = ref _openUI[meta.MetaInfo.UILayer];
if (layer.HandleSet.Remove(meta.MetaInfo.RuntimeTypeHandle))
{
2025-12-24 20:44:36 +08:00
if (layer.IndexMap.TryGetValue(meta.MetaInfo.RuntimeTypeHandle, out int index))
{
layer.OrderList.RemoveAt(index);
layer.IndexMap.Remove(meta.MetaInfo.RuntimeTypeHandle);
// Update indices for all elements after the removed one
for (int i = index; i < layer.OrderList.Count; i++)
{
var m = layer.OrderList[i];
layer.IndexMap[m.MetaInfo.RuntimeTypeHandle] = i;
}
}
2025-09-05 19:46:30 +08:00
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void UpdateLayerParent(UIMetadata meta)
{
2025-12-24 20:44:36 +08:00
if (meta.View?.Holder != null && meta.View.Holder.IsValid())
2025-09-05 19:46:30 +08:00
{
var layerRect = GetLayerRect(meta.MetaInfo.UILayer);
meta.View.Holder.transform.SetParent(layerRect);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void MoveToTop(UIMetadata meta)
{
ref var layer = ref _openUI[meta.MetaInfo.UILayer];
int lastIdx = layer.OrderList.Count - 1;
2025-12-24 20:44:36 +08:00
if (!layer.IndexMap.TryGetValue(meta.MetaInfo.RuntimeTypeHandle, out int currentIdx))
return;
2025-09-05 19:46:30 +08:00
if (currentIdx != lastIdx && currentIdx >= 0)
{
layer.OrderList.RemoveAt(currentIdx);
layer.OrderList.Add(meta);
2025-12-24 20:44:36 +08:00
for (int i = currentIdx; i < lastIdx; i++)
{
var m = layer.OrderList[i];
layer.IndexMap[m.MetaInfo.RuntimeTypeHandle] = i;
}
layer.IndexMap[meta.MetaInfo.RuntimeTypeHandle] = lastIdx;
SortWindowDepth(meta.MetaInfo.UILayer, currentIdx);
2025-09-05 19:46:30 +08:00
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private async UniTask UpdateVisualState(UIMetadata meta, CancellationToken cancellationToken = default)
2025-09-05 19:46:30 +08:00
{
SortWindowVisible(meta.MetaInfo.UILayer);
SortWindowDepth(meta.MetaInfo.UILayer);
if (meta.State == UIState.Loaded)
{
await meta.View.InternalInitlized(cancellationToken);
2025-09-05 19:46:30 +08:00
}
await meta.View.InternalOpen(cancellationToken);
2025-09-05 19:46:30 +08:00
}
private void SortWindowVisible(int layer)
{
var list = _openUI[layer].OrderList;
2025-12-24 20:44:36 +08:00
int count = list.Count;
2025-09-05 19:46:30 +08:00
2025-12-24 20:44:36 +08:00
int fullscreenIdx = -1;
for (int i = count - 1; i >= 0; i--)
2025-09-05 19:46:30 +08:00
{
var meta = list[i];
2026-03-17 17:15:31 +08:00
if (meta.MetaInfo.FullScreen && UIStateMachine.IsDisplayActive(meta.State))
2025-12-24 20:44:36 +08:00
{
fullscreenIdx = i;
2026-03-16 20:52:55 +08:00
break;
2025-12-24 20:44:36 +08:00
}
}
if (fullscreenIdx == -1)
{
for (int i = 0; i < count; i++)
{
list[i].View.Visible = true;
}
}
else
{
for (int i = 0; i < count; i++)
{
list[i].View.Visible = (i >= fullscreenIdx);
}
2025-09-05 19:46:30 +08:00
}
}
2025-12-24 20:44:36 +08:00
private void SortWindowDepth(int layer, int startIndex = 0)
2025-09-05 19:46:30 +08:00
{
var list = _openUI[layer].OrderList;
int baseDepth = layer * LAYER_DEEP;
2025-12-24 20:44:36 +08:00
for (int i = startIndex; i < list.Count; i++)
2025-09-05 19:46:30 +08:00
{
2025-12-24 20:44:36 +08:00
int newDepth = baseDepth + i * WINDOW_DEEP;
if (list[i].View.Depth != newDepth)
{
list[i].View.Depth = newDepth;
}
2025-09-05 19:46:30 +08:00
}
}
}
}