com.alicizax.unity.framework/Runtime/UI/Manager/UIService.Open.cs
陈思海 6397cc03b2 框架大更新
1.进步优化UI系统 加载问题 性能问题 Canvas重绘问题 边界处理问题
2.优化对象池和游戏对象池的性能 游戏对象池根据窗口 策略定期清理
3.优化整个AppService 和ServiceWorld结构 固定三大类 具体参考代码
2026-03-31 17:25:20 +08:00

354 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using AlicizaX;
using Cysharp.Threading.Tasks;
namespace AlicizaX.UI.Runtime
{
sealed class LayerData
{
public readonly List<UIMetadata> OrderList;
public readonly Dictionary<RuntimeTypeHandle, int> IndexMap;
public int LastFullscreenIndex;
public LayerData(int initialCapacity)
{
OrderList = new List<UIMetadata>(initialCapacity);
IndexMap = new Dictionary<RuntimeTypeHandle, int>(initialCapacity);
LastFullscreenIndex = -1;
}
}
internal sealed partial class UIService
{
private readonly LayerData[] _openUI = new LayerData[(int)UILayer.All];
private async UniTask<UIBase> ShowUIImplAsync(UIMetadata metaInfo, params object[] userDatas)
{
CreateMetaUI(metaInfo);
await UIHolderFactory.CreateUIResourceAsync(metaInfo, UICacheLayer);
if (metaInfo.View == null || metaInfo.State == UIState.Uninitialized || metaInfo.State == UIState.Destroyed)
{
return null;
}
FinalizeShow(metaInfo, userDatas);
await UpdateVisualState(metaInfo, metaInfo.CancellationToken);
return metaInfo.View;
}
private UIBase ShowUIImplSync(UIMetadata metaInfo, params object[] userDatas)
{
CreateMetaUI(metaInfo);
UIHolderFactory.CreateUIResourceSync(metaInfo, UICacheLayer);
if (metaInfo.View == null || metaInfo.State == UIState.Uninitialized || metaInfo.State == UIState.Destroyed)
{
return null;
}
FinalizeShow(metaInfo, userDatas);
UpdateVisualState(metaInfo).Forget();
return metaInfo.View;
}
private async UniTask CloseUIImpl(UIMetadata meta, bool force)
{
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)
{
meta.CancelAsyncOperations();
var popResult = Pop(meta);
SortWindowVisible(meta.MetaInfo.UILayer, popResult.previousFullscreenIndex);
SortWindowDepth(meta.MetaInfo.UILayer, popResult.removedIndex >= 0 ? popResult.removedIndex : 0);
meta.View.Visible = false;
CacheWindow(meta, force);
return;
}
meta.CancelAsyncOperations();
await meta.View.InternalClose();
if (meta.State != UIState.Closed)
{
return;
}
var closedPopResult = Pop(meta);
SortWindowVisible(meta.MetaInfo.UILayer, closedPopResult.previousFullscreenIndex);
SortWindowDepth(meta.MetaInfo.UILayer, closedPopResult.removedIndex >= 0 ? closedPopResult.removedIndex : 0);
CacheWindow(meta, force);
}
private UIBase GetUIImpl(UIMetadata meta)
{
return meta.View;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void CreateMetaUI(UIMetadata meta)
{
if (meta.State == UIState.Uninitialized) meta.CreateUI();
}
private void FinalizeShow(UIMetadata meta, object[] userDatas)
{
if (meta.InCache)
{
RemoveFromCache(meta.MetaInfo.RuntimeTypeHandle);
Push(meta);
}
else
{
switch (meta.State)
{
case UIState.Loaded:
Push(meta);
break;
case UIState.Opening:
case UIState.Closing:
case UIState.Opened:
MoveToTop(meta);
break;
}
}
meta.View.RefreshParams(userDatas);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Push(UIMetadata meta)
{
var layer = _openUI[meta.MetaInfo.UILayer];
if (!layer.IndexMap.ContainsKey(meta.MetaInfo.RuntimeTypeHandle))
{
int index = layer.OrderList.Count;
layer.OrderList.Add(meta);
layer.IndexMap[meta.MetaInfo.RuntimeTypeHandle] = index;
if (meta.MetaInfo.FullScreen)
{
layer.LastFullscreenIndex = index;
}
UpdateLayerParent(meta);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private (int removedIndex, int previousFullscreenIndex) Pop(UIMetadata meta)
{
var layer = _openUI[meta.MetaInfo.UILayer];
int previousFullscreenIndex = layer.LastFullscreenIndex;
if (layer.IndexMap.TryGetValue(meta.MetaInfo.RuntimeTypeHandle, out int index))
{
layer.OrderList.RemoveAt(index);
layer.IndexMap.Remove(meta.MetaInfo.RuntimeTypeHandle);
for (int i = index; i < layer.OrderList.Count; i++)
{
var item = layer.OrderList[i];
layer.IndexMap[item.MetaInfo.RuntimeTypeHandle] = i;
}
UpdateFullscreenIndexAfterRemove(layer, meta, index);
return (index, previousFullscreenIndex);
}
return (-1, previousFullscreenIndex);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void UpdateLayerParent(UIMetadata meta)
{
if (meta.View?.Holder != null && meta.View.Holder.IsValid())
{
var layerRect = GetLayerRect(meta.MetaInfo.UILayer);
meta.View.Holder.transform.SetParent(layerRect);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void MoveToTop(UIMetadata meta)
{
var layer = _openUI[meta.MetaInfo.UILayer];
int lastIdx = layer.OrderList.Count - 1;
if (!layer.IndexMap.TryGetValue(meta.MetaInfo.RuntimeTypeHandle, out int currentIdx))
return;
if (currentIdx != lastIdx && currentIdx >= 0)
{
layer.OrderList.RemoveAt(currentIdx);
layer.OrderList.Add(meta);
for (int i = currentIdx; i < lastIdx; i++)
{
var item = layer.OrderList[i];
layer.IndexMap[item.MetaInfo.RuntimeTypeHandle] = i;
}
layer.IndexMap[meta.MetaInfo.RuntimeTypeHandle] = lastIdx;
UpdateFullscreenIndexAfterMove(layer, meta, currentIdx, lastIdx);
SortWindowDepth(meta.MetaInfo.UILayer, currentIdx);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private async UniTask UpdateVisualState(UIMetadata meta, CancellationToken cancellationToken = default)
{
SortWindowVisible(meta.MetaInfo.UILayer);
SortWindowDepth(meta.MetaInfo.UILayer);
if (meta.State == UIState.Loaded)
{
await meta.View.InternalInitlized(cancellationToken);
}
await meta.View.InternalOpen(cancellationToken);
}
private void SortWindowVisible(int layer, int previousFullscreenIndex = int.MinValue)
{
var layerData = _openUI[layer];
var list = layerData.OrderList;
int count = list.Count;
int fullscreenIdx = layerData.LastFullscreenIndex;
if (fullscreenIdx >= count || (fullscreenIdx >= 0 && !IsDisplayFullscreen(list[fullscreenIdx])))
{
fullscreenIdx = FindLastFullscreenIndex(list, count - 1);
layerData.LastFullscreenIndex = fullscreenIdx;
}
int oldFullscreenIndex = previousFullscreenIndex == int.MinValue ? fullscreenIdx : previousFullscreenIndex;
if (oldFullscreenIndex == fullscreenIdx)
{
ApplyVisibilityRange(list, fullscreenIdx >= 0 ? fullscreenIdx : 0, count, fullscreenIdx);
return;
}
if (oldFullscreenIndex == -1 && fullscreenIdx == -1)
{
ApplyVisibilityRange(list, 0, count, -1);
return;
}
int start = oldFullscreenIndex < 0 || fullscreenIdx < 0
? 0
: Math.Min(oldFullscreenIndex, fullscreenIdx);
int endExclusive = oldFullscreenIndex < 0 || fullscreenIdx < 0
? count
: Math.Max(oldFullscreenIndex, fullscreenIdx) + 1;
ApplyVisibilityRange(list, start, endExclusive, fullscreenIdx);
}
private void SortWindowDepth(int layer, int startIndex = 0)
{
var list = _openUI[layer].OrderList;
int baseDepth = layer * LAYER_DEEP;
for (int i = startIndex; i < list.Count; i++)
{
int newDepth = baseDepth + i * WINDOW_DEEP;
if (list[i].View.Depth != newDepth)
{
list[i].View.Depth = newDepth;
}
}
}
private static bool IsDisplayFullscreen(UIMetadata meta)
{
return meta.MetaInfo.FullScreen && UIStateMachine.IsDisplayActive(meta.State);
}
private static int FindLastFullscreenIndex(List<UIMetadata> list, int startIndex)
{
for (int i = Math.Min(startIndex, list.Count - 1); i >= 0; i--)
{
if (IsDisplayFullscreen(list[i]))
{
return i;
}
}
return -1;
}
private static void ApplyVisibilityRange(List<UIMetadata> list, int startInclusive, int endExclusive, int fullscreenIdx)
{
if (startInclusive < 0)
{
startInclusive = 0;
}
if (endExclusive > list.Count)
{
endExclusive = list.Count;
}
bool showAll = fullscreenIdx < 0;
for (int i = startInclusive; i < endExclusive; i++)
{
list[i].View.Visible = showAll || i >= fullscreenIdx;
}
}
private static void UpdateFullscreenIndexAfterRemove(LayerData layer, UIMetadata removedMeta, int removedIndex)
{
if (layer.OrderList.Count == 0)
{
layer.LastFullscreenIndex = -1;
return;
}
if (removedMeta.MetaInfo.FullScreen && layer.LastFullscreenIndex == removedIndex)
{
layer.LastFullscreenIndex = FindLastFullscreenIndex(layer.OrderList, removedIndex - 1);
return;
}
if (removedIndex < layer.LastFullscreenIndex)
{
layer.LastFullscreenIndex--;
}
}
private static void UpdateFullscreenIndexAfterMove(LayerData layer, UIMetadata meta, int fromIndex, int toIndex)
{
if (layer.LastFullscreenIndex == fromIndex)
{
layer.LastFullscreenIndex = toIndex;
return;
}
if (!meta.MetaInfo.FullScreen)
{
return;
}
if (fromIndex < layer.LastFullscreenIndex)
{
layer.LastFullscreenIndex--;
}
layer.LastFullscreenIndex = Math.Max(layer.LastFullscreenIndex, toIndex);
}
}
}