优化UIService模块
优化UI模块更多细节容错处理 优化UI模块内存泄露问题 优化性能
This commit is contained in:
parent
ac15608019
commit
cd5de2c374
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using AlicizaX.Resource.Runtime;
|
||||
using AlicizaX;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
@ -1,11 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.PlayerLoop;
|
||||
|
||||
namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
@ -37,38 +33,36 @@ namespace AlicizaX.UI.Runtime
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Register(Type uiType, Type holderType, UILayer layer = UILayer.UI, bool fullScreen = false, int cacheTime = 0, bool needUpdate = false)
|
||||
{
|
||||
var holderHandle = holderType.TypeHandle;
|
||||
var uiHandle = uiType.TypeHandle;
|
||||
RuntimeTypeHandle holderHandle = holderType.TypeHandle;
|
||||
RuntimeTypeHandle uiHandle = uiType.TypeHandle;
|
||||
_typeHandleMap[uiHandle] = new UIMetaInfo(uiHandle, holderHandle, layer, fullScreen, cacheTime, needUpdate);
|
||||
_stringHandleMap[uiType.Name] = uiHandle;
|
||||
}
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool TryGet(RuntimeTypeHandle handle, out UIMetaInfo info)
|
||||
{
|
||||
if (_typeHandleMap.TryGetValue(handle, out info))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var t = Type.GetTypeFromHandle(handle);
|
||||
|
||||
if (TryReflectAndRegister(t, out info))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return TryReflectAndRegister(Type.GetTypeFromHandle(handle), out info);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool TryGet(string typeName, out UIMetaInfo info)
|
||||
{
|
||||
if (_stringHandleMap.TryGetValue(typeName, out var handle))
|
||||
if (_stringHandleMap.TryGetValue(typeName, out RuntimeTypeHandle handle))
|
||||
{
|
||||
return TryGet(handle, out info);
|
||||
}
|
||||
|
||||
|
||||
var type = AlicizaX.Utility.Assembly.GetType(typeName);
|
||||
|
||||
Type type = AlicizaX.Utility.Assembly.GetType(typeName);
|
||||
if (type != null && TryReflectAndRegister(type, out info))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
info = default;
|
||||
return false;
|
||||
@ -77,7 +71,13 @@ namespace AlicizaX.UI.Runtime
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static bool TryReflectAndRegister(Type uiType, out UIMetaInfo info)
|
||||
{
|
||||
Log.Warning($"[UI] UI未注册[{uiType.FullName}] 反射进行缓存");
|
||||
if (uiType == null)
|
||||
{
|
||||
info = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.Warning($"[UI] UI not pre-registered: {uiType.FullName}, using reflection fallback.");
|
||||
return TryReflectAndRegisterInternal(uiType, out info);
|
||||
}
|
||||
|
||||
@ -86,14 +86,11 @@ namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
try
|
||||
{
|
||||
Type baseType = uiType;
|
||||
#pragma warning disable CS8632
|
||||
Type? holderType = null;
|
||||
|
||||
var genericArgs = baseType.GetGenericArguments();
|
||||
if (genericArgs.Length > 0)
|
||||
Type holderType = ResolveHolderType(uiType);
|
||||
if (holderType == null)
|
||||
{
|
||||
holderType = genericArgs[0];
|
||||
info = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
UILayer layer = UILayer.UI;
|
||||
@ -101,27 +98,38 @@ namespace AlicizaX.UI.Runtime
|
||||
int cacheTime = 0;
|
||||
bool needUpdate = false;
|
||||
|
||||
var windowAttribute = CustomAttributeData.GetCustomAttributes(uiType)
|
||||
.FirstOrDefault(a => a.AttributeType.Name == nameof(WindowAttribute));
|
||||
var uiUpdateAttribute = CustomAttributeData.GetCustomAttributes(uiType)
|
||||
.FirstOrDefault(a => a.AttributeType.Name == nameof(UIUpdateAttribute));
|
||||
|
||||
if (windowAttribute != null)
|
||||
IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(uiType);
|
||||
for (int i = 0; i < attributes.Count; i++)
|
||||
{
|
||||
var args = windowAttribute.ConstructorArguments;
|
||||
if (args.Count > 0) layer = (UILayer)(args[0].Value ?? UILayer.UI);
|
||||
if (args.Count > 1) fullScreen = (bool)(args[1].Value ?? false);
|
||||
if (args.Count > 2) cacheTime = (int)(args[2].Value ?? 0);
|
||||
CustomAttributeData attribute = attributes[i];
|
||||
string attributeName = attribute.AttributeType.Name;
|
||||
if (attributeName == nameof(WindowAttribute))
|
||||
{
|
||||
IList<CustomAttributeTypedArgument> args = attribute.ConstructorArguments;
|
||||
if (args.Count > 0)
|
||||
{
|
||||
layer = (UILayer)(args[0].Value ?? UILayer.UI);
|
||||
}
|
||||
|
||||
if (args.Count > 1)
|
||||
{
|
||||
fullScreen = (bool)(args[1].Value ?? false);
|
||||
}
|
||||
|
||||
if (args.Count > 2)
|
||||
{
|
||||
cacheTime = (int)(args[2].Value ?? 0);
|
||||
}
|
||||
}
|
||||
else if (attributeName == nameof(UIUpdateAttribute))
|
||||
{
|
||||
needUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
needUpdate = uiUpdateAttribute != null;
|
||||
|
||||
if (holderType != null)
|
||||
{
|
||||
Register(uiType, holderType, layer, fullScreen, cacheTime, needUpdate);
|
||||
info = _typeHandleMap[uiType.TypeHandle];
|
||||
return true;
|
||||
}
|
||||
Register(uiType, holderType, layer, fullScreen, cacheTime, needUpdate);
|
||||
info = _typeHandleMap[uiType.TypeHandle];
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -131,5 +139,25 @@ namespace AlicizaX.UI.Runtime
|
||||
info = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Type ResolveHolderType(Type uiType)
|
||||
{
|
||||
Type current = uiType;
|
||||
while (current != null && current != typeof(object))
|
||||
{
|
||||
if (current.IsGenericType)
|
||||
{
|
||||
Type[] genericArgs = current.GetGenericArguments();
|
||||
if (genericArgs.Length == 1 && typeof(UIHolderObjectBase).IsAssignableFrom(genericArgs[0]))
|
||||
{
|
||||
return genericArgs[0];
|
||||
}
|
||||
}
|
||||
|
||||
current = current.BaseType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,15 @@ namespace AlicizaX.UI.Runtime
|
||||
return;
|
||||
|
||||
View = (UIBase)InstanceFactory.CreateInstanceOptimized(UILogicType);
|
||||
EnsureCancellationToken();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void EnsureCancellationToken()
|
||||
{
|
||||
if (_cancellationTokenSource == null)
|
||||
{
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
}
|
||||
}
|
||||
@ -51,7 +60,7 @@ namespace AlicizaX.UI.Runtime
|
||||
DisposeAsync().Forget();
|
||||
}
|
||||
|
||||
private async UniTask DisposeAsync()
|
||||
internal async UniTask DisposeAsync()
|
||||
{
|
||||
CancelAsyncOperations();
|
||||
|
||||
@ -64,11 +73,22 @@ namespace AlicizaX.UI.Runtime
|
||||
|
||||
public UIMetadata(Type uiType)
|
||||
{
|
||||
if (uiType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uiType));
|
||||
}
|
||||
|
||||
UILogicType = uiType;
|
||||
|
||||
UIMetaRegistry.TryGet(UILogicType.TypeHandle, out MetaInfo);
|
||||
if (!UIMetaRegistry.TryGet(UILogicType.TypeHandle, out MetaInfo))
|
||||
{
|
||||
throw new InvalidOperationException($"[UI] Metadata not registered for {UILogicType.FullName}");
|
||||
}
|
||||
|
||||
UIResRegistry.TryGet(MetaInfo.HolderRuntimeTypeHandle, out ResInfo);
|
||||
if (!UIResRegistry.TryGet(MetaInfo.HolderRuntimeTypeHandle, out ResInfo))
|
||||
{
|
||||
throw new InvalidOperationException($"[UI] Resource metadata not registered for holder of {UILogicType.FullName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,5 +27,16 @@ namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
protected internal override void OnUnspawn()
|
||||
{
|
||||
base.OnUnspawn();
|
||||
|
||||
UIMetadata metadata = (UIMetadata)Target;
|
||||
if (metadata != null)
|
||||
{
|
||||
metadata.CancelAsyncOperations();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,19 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
public static class UIResRegistry
|
||||
{
|
||||
private static readonly Dictionary<RuntimeTypeHandle, UIResInfo> _typeHandleMap = new();
|
||||
|
||||
|
||||
public readonly struct UIResInfo
|
||||
{
|
||||
public readonly string Location;
|
||||
@ -26,29 +19,35 @@ namespace AlicizaX.UI.Runtime
|
||||
LoadType = loadType;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<RuntimeTypeHandle, UIResInfo> _typeHandleMap = new();
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Register(Type holderType, string location, EUIResLoadType loadType)
|
||||
{
|
||||
var handle = holderType.TypeHandle;
|
||||
RuntimeTypeHandle handle = holderType.TypeHandle;
|
||||
_typeHandleMap[handle] = new UIResInfo(location, loadType);
|
||||
}
|
||||
|
||||
public static bool TryGet(RuntimeTypeHandle handle, out UIResInfo info)
|
||||
{
|
||||
if (_typeHandleMap.TryGetValue(handle, out info))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var t = Type.GetTypeFromHandle(handle);
|
||||
|
||||
if (TryReflectAndRegister(t, out info))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return TryReflectAndRegister(Type.GetTypeFromHandle(handle), out info);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static bool TryReflectAndRegister(Type holderType, out UIResInfo info)
|
||||
{
|
||||
if (holderType == null)
|
||||
{
|
||||
info = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TryReflectAndRegisterInternal(holderType, out info);
|
||||
}
|
||||
|
||||
@ -57,17 +56,21 @@ namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
try
|
||||
{
|
||||
var cad = CustomAttributeData.GetCustomAttributes(holderType)
|
||||
.FirstOrDefault(a => a.AttributeType.Name == nameof(UIResAttribute));
|
||||
|
||||
string resLocation = string.Empty;
|
||||
EUIResLoadType resLoadType = EUIResLoadType.AssetBundle;
|
||||
|
||||
if (cad != null)
|
||||
IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(holderType);
|
||||
for (int i = 0; i < attributes.Count; i++)
|
||||
{
|
||||
var args = cad.ConstructorArguments;
|
||||
if (args.Count > 0) resLocation = (string)(args[0].Value ?? string.Empty);
|
||||
if (args.Count > 1) resLoadType = (EUIResLoadType)(args[1].Value ?? EUIResLoadType.AssetBundle);
|
||||
CustomAttributeData attribute = attributes[i];
|
||||
if (attribute.AttributeType.Name != nameof(UIResAttribute))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IList<CustomAttributeTypedArgument> args = attribute.ConstructorArguments;
|
||||
string resLocation = args.Count > 0 ? (string)(args[0].Value ?? string.Empty) : string.Empty;
|
||||
EUIResLoadType resLoadType = args.Count > 1
|
||||
? (EUIResLoadType)(args[1].Value ?? EUIResLoadType.AssetBundle)
|
||||
: EUIResLoadType.AssetBundle;
|
||||
|
||||
Register(holderType, resLocation, resLoadType);
|
||||
info = _typeHandleMap[holderType.TypeHandle];
|
||||
return true;
|
||||
|
||||
@ -37,7 +37,10 @@ namespace AlicizaX
|
||||
public void Clear()
|
||||
{
|
||||
for (int i = _eventHandles.Count - 1; i >= 0; i--)
|
||||
{
|
||||
_eventHandles[i].Dispose();
|
||||
}
|
||||
|
||||
_eventHandles.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,13 +27,14 @@ namespace AlicizaX.UI.Runtime
|
||||
/// <param name="timeDuration">倒计时/s</param>
|
||||
public void SetUIBlock(float timeDuration)
|
||||
{
|
||||
ITimerService timerService = GetTimerService();
|
||||
if (m_LastCountDownGuid != 0)
|
||||
{
|
||||
_timerService.RemoveTimer(m_LastCountDownGuid);
|
||||
timerService.RemoveTimer(m_LastCountDownGuid);
|
||||
}
|
||||
|
||||
SetLayerBlockOption(true);
|
||||
m_LastCountDownGuid = _timerService.AddTimer(OnBlockCountDown, timeDuration);
|
||||
m_LastCountDownGuid = timerService.AddTimer(OnBlockCountDown, timeDuration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -41,9 +42,10 @@ namespace AlicizaX.UI.Runtime
|
||||
/// </summary>
|
||||
public void ForceExitBlock()
|
||||
{
|
||||
ITimerService timerService = GetTimerService();
|
||||
if (m_LastCountDownGuid != 0)
|
||||
{
|
||||
_timerService.RemoveTimer(m_LastCountDownGuid);
|
||||
timerService.RemoveTimer(m_LastCountDownGuid);
|
||||
}
|
||||
|
||||
RecoverLayerOptionAll();
|
||||
|
||||
@ -40,7 +40,8 @@ namespace AlicizaX.UI.Runtime
|
||||
uiMetadata.View.Holder.transform.SetParent(UICacheLayer);
|
||||
if (uiMetadata.MetaInfo.CacheTime > 0)
|
||||
{
|
||||
timerId = _timerService.AddTimer(
|
||||
ITimerService timerService = GetTimerService();
|
||||
timerId = timerService.AddTimer(
|
||||
OnTimerDisposeWindow,
|
||||
uiMetadata,
|
||||
uiMetadata.MetaInfo.CacheTime,
|
||||
@ -62,8 +63,8 @@ namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
if (meta != null)
|
||||
{
|
||||
meta.Dispose();
|
||||
RemoveFromCache(meta.MetaInfo.RuntimeTypeHandle);
|
||||
meta.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,11 +74,22 @@ namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
m_CacheWindow.Remove(typeHandle);
|
||||
entry.Metadata.InCache = false;
|
||||
if (entry.TimerId > 0)
|
||||
if (entry.TimerId > 0 && _timerService != null)
|
||||
{
|
||||
_timerService.RemoveTimer(entry.TimerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ITimerService GetTimerService()
|
||||
{
|
||||
if (_timerService != null)
|
||||
{
|
||||
return _timerService;
|
||||
}
|
||||
|
||||
_timerService = AppServices.Require<ITimerService>();
|
||||
return _timerService;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ namespace AlicizaX.UI.Runtime
|
||||
private async UniTask<UIBase> ShowUIImplAsync(UIMetadata metaInfo, params object[] userDatas)
|
||||
{
|
||||
CreateMetaUI(metaInfo);
|
||||
EnsureMetaCanOpen(metaInfo);
|
||||
await UIHolderFactory.CreateUIResourceAsync(metaInfo, UICacheLayer);
|
||||
if (metaInfo.View == null || metaInfo.State == UIState.Uninitialized || metaInfo.State == UIState.Destroyed)
|
||||
{
|
||||
@ -42,6 +43,7 @@ namespace AlicizaX.UI.Runtime
|
||||
private UIBase ShowUIImplSync(UIMetadata metaInfo, params object[] userDatas)
|
||||
{
|
||||
CreateMetaUI(metaInfo);
|
||||
EnsureMetaCanOpen(metaInfo);
|
||||
UIHolderFactory.CreateUIResourceSync(metaInfo, UICacheLayer);
|
||||
if (metaInfo.View == null || metaInfo.State == UIState.Uninitialized || metaInfo.State == UIState.Destroyed)
|
||||
{
|
||||
@ -63,7 +65,7 @@ namespace AlicizaX.UI.Runtime
|
||||
if (meta.State == UIState.CreatedUI)
|
||||
{
|
||||
meta.CancelAsyncOperations();
|
||||
meta.Dispose();
|
||||
await meta.DisposeAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -79,6 +81,7 @@ namespace AlicizaX.UI.Runtime
|
||||
}
|
||||
|
||||
meta.CancelAsyncOperations();
|
||||
meta.EnsureCancellationToken();
|
||||
await meta.View.InternalClose();
|
||||
if (meta.State != UIState.Closed)
|
||||
{
|
||||
@ -103,6 +106,15 @@ namespace AlicizaX.UI.Runtime
|
||||
if (meta.State == UIState.Uninitialized) meta.CreateUI();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void EnsureMetaCanOpen(UIMetadata meta)
|
||||
{
|
||||
if (meta.State == UIState.Closed)
|
||||
{
|
||||
meta.EnsureCancellationToken();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void FinalizeShow(UIMetadata meta, object[] userDatas)
|
||||
{
|
||||
|
||||
@ -17,6 +17,7 @@ namespace AlicizaX.UI.Runtime
|
||||
|
||||
protected override void OnDestroyService()
|
||||
{
|
||||
DestroyAllManagedUI().Forget();
|
||||
}
|
||||
|
||||
void IServiceTickable.Tick(float deltaTime)
|
||||
@ -99,5 +100,81 @@ namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
_timerService = timerService;
|
||||
}
|
||||
|
||||
private async UniTask DestroyAllManagedUI()
|
||||
{
|
||||
for (int layerIndex = 0; layerIndex < _openUI.Length; layerIndex++)
|
||||
{
|
||||
LayerData layer = _openUI[layerIndex];
|
||||
if (layer == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int count = layer.OrderList.Count;
|
||||
for (int i = count - 1; i >= 0; i--)
|
||||
{
|
||||
UIMetadata meta = layer.OrderList[i];
|
||||
if (meta == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
meta.CancelAsyncOperations();
|
||||
await meta.DisposeAsync();
|
||||
}
|
||||
|
||||
layer.OrderList.Clear();
|
||||
layer.IndexMap.Clear();
|
||||
layer.LastFullscreenIndex = -1;
|
||||
}
|
||||
|
||||
if (m_CacheWindow.Count > 0)
|
||||
{
|
||||
RuntimeTypeHandle[] handles = new RuntimeTypeHandle[m_CacheWindow.Count];
|
||||
int writeIndex = 0;
|
||||
foreach (var pair in m_CacheWindow)
|
||||
{
|
||||
handles[writeIndex++] = pair.Key;
|
||||
}
|
||||
|
||||
for (int i = 0; i < writeIndex; i++)
|
||||
{
|
||||
if (!m_CacheWindow.TryGetValue(handles[i], out CacheEntry entry))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.TimerId > 0 && _timerService != null)
|
||||
{
|
||||
_timerService.RemoveTimer(entry.TimerId);
|
||||
}
|
||||
|
||||
entry.Metadata.InCache = false;
|
||||
entry.Metadata.CancelAsyncOperations();
|
||||
await entry.Metadata.DisposeAsync();
|
||||
}
|
||||
|
||||
m_CacheWindow.Clear();
|
||||
}
|
||||
|
||||
if (m_LastCountDownGuid != 0 && _timerService != null)
|
||||
{
|
||||
_timerService.RemoveTimer(m_LastCountDownGuid);
|
||||
m_LastCountDownGuid = 0;
|
||||
}
|
||||
|
||||
if (m_LayerBlock != null)
|
||||
{
|
||||
UnityEngine.Object.Destroy(m_LayerBlock);
|
||||
m_LayerBlock = null;
|
||||
}
|
||||
|
||||
UICacheLayer = null;
|
||||
UICanvasRoot = null;
|
||||
UICanvas = null;
|
||||
UICamera = null;
|
||||
UIRoot = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,6 @@ namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
public interface IUITransitionPlayer
|
||||
{
|
||||
int Priority { get; }
|
||||
|
||||
UniTask PlayOpenAsync(CancellationToken cancellationToken = default);
|
||||
|
||||
UniTask PlayCloseAsync(CancellationToken cancellationToken = default);
|
||||
|
||||
@ -8,7 +8,6 @@ namespace AlicizaX.UI.Runtime
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class UIAnimationFlowTransition : AnimationFlow.Runtime.AnimationFlow, IUITransitionPlayer
|
||||
{
|
||||
public int Priority => 0;
|
||||
|
||||
[SerializeField] private string openClip = "Open";
|
||||
[SerializeField] private string closeClip = "Close";
|
||||
|
||||
@ -38,8 +38,6 @@ namespace AlicizaX.UI.Runtime
|
||||
public float Alpha;
|
||||
}
|
||||
|
||||
public int Priority => 100;
|
||||
|
||||
[SerializeField] private UITransitionPreset openPreset = UITransitionPreset.FadeScale;
|
||||
[SerializeField] private UITransitionPreset closePreset = UITransitionPreset.FadeScale;
|
||||
[SerializeField] private UITransitionEase openEase = UITransitionEase.OutCubic;
|
||||
|
||||
@ -5,7 +5,6 @@ using System.Threading;
|
||||
using AlicizaX;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
|
||||
namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
@ -39,8 +38,17 @@ namespace AlicizaX.UI.Runtime
|
||||
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
if (temp[j].View.Visible) await temp[j].View.InternalClose();
|
||||
temp[j].Dispose();
|
||||
UIMetadata metadata = temp[j];
|
||||
if (metadata.View.Visible)
|
||||
{
|
||||
metadata.CancelAsyncOperations();
|
||||
metadata.EnsureCancellationToken();
|
||||
await metadata.View.InternalClose(metadata.CancellationToken);
|
||||
}
|
||||
|
||||
await metadata.DisposeAsync();
|
||||
UIMetadataFactory.ReturnToPool(metadata);
|
||||
temp[j] = null;
|
||||
}
|
||||
}
|
||||
finally
|
||||
@ -54,9 +62,9 @@ namespace AlicizaX.UI.Runtime
|
||||
|
||||
private void ChildVisible(bool value)
|
||||
{
|
||||
foreach (var kvp in _children)
|
||||
foreach (KeyValuePair<UIBase, UIMetadata> kvp in _children)
|
||||
{
|
||||
var view = kvp.Value.View;
|
||||
UIBase view = kvp.Value.View;
|
||||
if (view.State == UIState.Opened)
|
||||
{
|
||||
view.Visible = value;
|
||||
@ -142,7 +150,13 @@ namespace AlicizaX.UI.Runtime
|
||||
|
||||
private async UniTask ProcessWidget(UIMetadata meta, bool visible, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!AddWidget(meta)) return;
|
||||
if (!AddWidget(meta))
|
||||
{
|
||||
await meta.DisposeAsync();
|
||||
UIMetadataFactory.ReturnToPool(meta);
|
||||
return;
|
||||
}
|
||||
|
||||
await meta.View.InternalInitlized(cancellationToken);
|
||||
meta.View.Visible = visible;
|
||||
if (meta.View.Visible)
|
||||
@ -156,8 +170,6 @@ namespace AlicizaX.UI.Runtime
|
||||
if (!_children.TryAdd(meta.View, meta))
|
||||
{
|
||||
Log.Warning("Already has widget:{0}", meta.View);
|
||||
meta.Dispose();
|
||||
UIMetadataFactory.ReturnToPool(meta);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -174,16 +186,33 @@ namespace AlicizaX.UI.Runtime
|
||||
if (_children.Remove(widget, out var meta))
|
||||
{
|
||||
meta.CancelAsyncOperations();
|
||||
await widget.InternalClose();
|
||||
meta.EnsureCancellationToken();
|
||||
await widget.InternalClose(meta.CancellationToken);
|
||||
|
||||
if (meta.MetaInfo.NeedUpdate)
|
||||
{
|
||||
_updateableChildren.Remove(meta);
|
||||
RemoveUpdateableChild(meta);
|
||||
}
|
||||
|
||||
meta.Dispose();
|
||||
await meta.DisposeAsync();
|
||||
UIMetadataFactory.ReturnToPool(meta);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveUpdateableChild(UIMetadata meta)
|
||||
{
|
||||
for (int i = 0; i < _updateableChildren.Count; i++)
|
||||
{
|
||||
if (_updateableChildren[i] != meta)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int lastIndex = _updateableChildren.Count - 1;
|
||||
_updateableChildren[i] = _updateableChildren[lastIndex];
|
||||
_updateableChildren.RemoveAt(lastIndex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@ namespace AlicizaX.UI.Runtime
|
||||
_state = UIState.CreatedUI;
|
||||
}
|
||||
|
||||
~UIBase() => Dispose(false);
|
||||
private bool _disposed;
|
||||
|
||||
internal Canvas _canvas;
|
||||
@ -105,7 +104,6 @@ namespace AlicizaX.UI.Runtime
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
@ -190,7 +188,7 @@ namespace AlicizaX.UI.Runtime
|
||||
|
||||
private void ReleaseEventListenerProxy()
|
||||
{
|
||||
if (!_eventListenerProxy.IsNull())
|
||||
if (_eventListenerProxy != null)
|
||||
{
|
||||
MemoryPool.Release(_eventListenerProxy);
|
||||
_eventListenerProxy = null;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
@ -6,7 +7,7 @@ using UnityEngine;
|
||||
namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public abstract class UIHolderObjectBase : UnityEngine.MonoBehaviour
|
||||
public abstract class UIHolderObjectBase : MonoBehaviour
|
||||
{
|
||||
public Action OnWindowInitEvent;
|
||||
public Action OnWindowBeforeShowEvent;
|
||||
@ -17,30 +18,17 @@ namespace AlicizaX.UI.Runtime
|
||||
|
||||
private GameObject _target;
|
||||
private IUITransitionPlayer _transitionPlayer;
|
||||
|
||||
/// <summary>
|
||||
/// UI实例资源对象。
|
||||
/// </summary>
|
||||
public GameObject Target => _target ??= gameObject;
|
||||
|
||||
private RectTransform _rectTransform;
|
||||
public RectTransform RectTransform => _rectTransform ??= Target.transform as RectTransform;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口矩阵位置组件。
|
||||
/// </summary>
|
||||
public RectTransform RectTransform => _rectTransform ??= _target.transform as RectTransform;
|
||||
|
||||
/// <summary>
|
||||
/// 可见性
|
||||
/// </summary>
|
||||
public bool Visible
|
||||
{
|
||||
get => Target.activeSelf;
|
||||
|
||||
internal set { _target.SetActive(value); }
|
||||
internal set => Target.SetActive(value);
|
||||
}
|
||||
|
||||
|
||||
public virtual void Awake()
|
||||
{
|
||||
_target = gameObject;
|
||||
@ -55,21 +43,21 @@ namespace AlicizaX.UI.Runtime
|
||||
|
||||
internal UniTask PlayOpenTransitionAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return TryGetTransitionPlayer(out var transitionPlayer)
|
||||
return TryGetTransitionPlayer(out IUITransitionPlayer transitionPlayer)
|
||||
? transitionPlayer.PlayOpenAsync(cancellationToken)
|
||||
: UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
internal UniTask PlayCloseTransitionAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return TryGetTransitionPlayer(out var transitionPlayer)
|
||||
return TryGetTransitionPlayer(out IUITransitionPlayer transitionPlayer)
|
||||
? transitionPlayer.PlayCloseAsync(cancellationToken)
|
||||
: UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
internal void StopTransition()
|
||||
{
|
||||
if (TryGetTransitionPlayer(out var transitionPlayer))
|
||||
if (TryGetTransitionPlayer(out IUITransitionPlayer transitionPlayer))
|
||||
{
|
||||
transitionPlayer.Stop();
|
||||
}
|
||||
@ -83,24 +71,7 @@ namespace AlicizaX.UI.Runtime
|
||||
return true;
|
||||
}
|
||||
|
||||
_transitionPlayer = null;
|
||||
int bestPriority = int.MinValue;
|
||||
MonoBehaviour[] behaviours = GetComponents<MonoBehaviour>();
|
||||
for (int i = 0; i < behaviours.Length; i++)
|
||||
{
|
||||
MonoBehaviour behaviour = behaviours[i];
|
||||
if (behaviours.IsNull() || !behaviour.isActiveAndEnabled || behaviour is not IUITransitionPlayer player)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player.Priority > bestPriority)
|
||||
{
|
||||
_transitionPlayer = player;
|
||||
bestPriority = player.Priority;
|
||||
}
|
||||
}
|
||||
|
||||
_transitionPlayer = GetComponent<IUITransitionPlayer>();
|
||||
transitionPlayer = _transitionPlayer;
|
||||
return transitionPlayer != null;
|
||||
}
|
||||
|
||||
@ -58,8 +58,7 @@ namespace AlicizaX.UI.Runtime
|
||||
// 初始化方法(泛型版本)
|
||||
protected void InitTabVirtuallyView<TTab>(Transform parent = null) where TTab : UIWidget
|
||||
{
|
||||
var metadata = UIMetadataFactory.GetWindowMetadata<TTab>();
|
||||
CacheTabMetadata(metadata, parent);
|
||||
CacheTabMetadata(typeof(TTab).TypeHandle, parent);
|
||||
}
|
||||
|
||||
// 初始化方法(类型名版本)
|
||||
@ -67,15 +66,12 @@ namespace AlicizaX.UI.Runtime
|
||||
{
|
||||
if (UIMetaRegistry.TryGet(typeName, out var metaRegistry))
|
||||
{
|
||||
var metadata = UIMetadataFactory.GetWindowMetadata(metaRegistry.RuntimeTypeHandle);
|
||||
CacheTabMetadata(metadata, parent);
|
||||
CacheTabMetadata(metaRegistry.RuntimeTypeHandle, parent);
|
||||
}
|
||||
}
|
||||
|
||||
private void CacheTabMetadata(UIMetadata metadata, Transform parent)
|
||||
private void CacheTabMetadata(RuntimeTypeHandle typeHandle, Transform parent)
|
||||
{
|
||||
var typeHandle = metadata.MetaInfo.RuntimeTypeHandle;
|
||||
|
||||
if (!_tabCache.ContainsKey(typeHandle))
|
||||
{
|
||||
_typeOrder.Add(typeHandle);
|
||||
@ -105,10 +101,10 @@ namespace AlicizaX.UI.Runtime
|
||||
|
||||
try
|
||||
{
|
||||
var metadata = UIMetadataFactory.GetWindowMetadata(typeHandle);
|
||||
var parent = _tabCache[typeHandle];
|
||||
UIMetadata metadata = UIMetadataFactory.GetWidgetMetadata(typeHandle);
|
||||
Transform parent = _tabCache[typeHandle];
|
||||
|
||||
var widget = await CreateWidgetUIAsync(metadata, parent, false);
|
||||
UIBase widget = await CreateWidgetUIAsync(metadata, parent, false);
|
||||
if (widget is not UIWidget tabWidget) return;
|
||||
|
||||
_loadedTabs[typeHandle] = tabWidget;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user