1.进步优化UI系统 加载问题 性能问题 Canvas重绘问题 边界处理问题 2.优化对象池和游戏对象池的性能 游戏对象池根据窗口 策略定期清理 3.优化整个AppService 和ServiceWorld结构 固定三大类 具体参考代码
354 lines
12 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|