com.alicizax.unity.framework/Runtime/UI/UIBase/UIBase.cs

333 lines
9.2 KiB
C#
Raw Normal View History

2025-09-05 19:46:30 +08:00
using System;
using System.Collections.Generic;
using System.Threading;
2025-09-05 19:46:30 +08:00
using AlicizaX;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace AlicizaX.UI.Runtime
{
public abstract partial class UIBase : IDisposable
{
protected UIBase()
{
_state = UIState.CreatedUI;
}
~UIBase() => Dispose(false);
private bool _disposed;
internal Canvas _canvas;
internal GraphicRaycaster _raycaster;
2026-03-17 17:15:31 +08:00
private int _lifecycleVersion;
2025-09-05 19:46:30 +08:00
internal UIState _state = UIState.Uninitialized;
internal UIState State => _state;
private System.Object[] _userDatas;
protected System.Object UserData => _userDatas != null && _userDatas.Length >= 1 ? _userDatas[0] : null;
protected System.Object[] UserDatas => _userDatas;
private RuntimeTypeHandle _runtimeTypeHandle;
internal RuntimeTypeHandle RuntimeTypeHandler
{
get
{
if (_runtimeTypeHandle.Value == IntPtr.Zero)
{
_runtimeTypeHandle = GetType().TypeHandle;
}
return _runtimeTypeHandle;
}
}
protected virtual void OnInitialize()
{
}
protected virtual void OnDestroy()
{
}
protected virtual void OnOpen()
{
}
protected virtual void OnClose()
{
}
protected virtual void OnUpdate()
{
}
/// <summary>
/// 如果重写当前方法 则同步OnInitialize不会调用
/// </summary>
2026-03-19 16:07:51 +08:00
protected virtual UniTask OnInitializeAsync()
2025-09-05 19:46:30 +08:00
{
OnInitialize();
2025-12-24 20:44:36 +08:00
return UniTask.CompletedTask;
2025-09-05 19:46:30 +08:00
}
/// <summary>
/// 如果重写当前方法 则同步OnOpen不会调用
/// </summary>
2026-03-19 16:07:51 +08:00
protected virtual UniTask OnOpenAsync()
2025-09-05 19:46:30 +08:00
{
OnOpen();
2025-12-24 20:44:36 +08:00
return UniTask.CompletedTask;
2025-09-05 19:46:30 +08:00
}
/// <summary>
/// 如果重写当前方法 则同步OnClose不会调用
/// </summary>
2026-03-19 16:07:51 +08:00
protected virtual UniTask OnCloseAsync()
2025-09-05 19:46:30 +08:00
{
OnClose();
2025-12-24 20:44:36 +08:00
return UniTask.CompletedTask;
2025-09-05 19:46:30 +08:00
}
/// <summary>
/// 事件在窗口销毁后会自动移除
/// </summary>
/// <param name="proxy"></param>
protected virtual void OnRegisterEvent(EventListenerProxy proxy)
{
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
// 托管资源释放
_canvas = null;
_raycaster = null;
}
_userDatas = null;
// 非托管资源释放
if (Holder != null)
{
if (Application.isPlaying)
Object.Destroy(Holder.gameObject);
else
Object.DestroyImmediate(Holder.gameObject);
}
_disposed = true;
}
internal bool Visible
{
get => _canvas != null && _canvas.gameObject.layer == UIComponent.UIShowLayer;
set
{
if (_canvas != null)
{
int setLayer = value ? UIComponent.UIShowLayer : UIComponent.UIHideLayer;
if (_canvas.gameObject.layer == setLayer)
return;
_canvas.gameObject.layer = setLayer;
ChildVisible(value);
Interactable = value;
}
}
}
private bool Interactable
{
2026-03-16 18:33:06 +08:00
get => _raycaster != null && _raycaster.enabled;
2025-09-05 19:46:30 +08:00
set
{
if (_raycaster != null && _raycaster.enabled != value)
{
_raycaster.enabled = value;
}
}
}
/// <summary>
/// 窗口深度值。
/// </summary>
internal int Depth
{
get => _canvas != null ? _canvas.sortingOrder : 0;
set
{
if (_canvas != null && _canvas.sortingOrder != value)
{
// 设置父类
_canvas.sortingOrder = value;
}
}
}
#region Event
private EventListenerProxy _eventListenerProxy;
private EventListenerProxy EventListenerProxy => _eventListenerProxy ??= MemoryPool.Acquire<EventListenerProxy>();
private void ReleaseEventListenerProxy()
{
if (!_eventListenerProxy.IsNull())
{
MemoryPool.Release(_eventListenerProxy);
2026-04-21 15:45:27 +08:00
_eventListenerProxy = null;
2025-09-05 19:46:30 +08:00
}
}
#endregion
#region
internal UIHolderObjectBase Holder;
internal abstract Type UIHolderType { get; }
internal abstract void BindUIHolder(UIHolderObjectBase holder, UIBase owner);
internal async UniTask InternalInitlized(CancellationToken cancellationToken = default)
2025-09-05 19:46:30 +08:00
{
2025-12-24 20:44:36 +08:00
if (!UIStateMachine.ValidateTransition(GetType().Name, _state, UIState.Initialized))
return;
2025-09-05 19:46:30 +08:00
_state = UIState.Initialized;
2025-09-25 11:11:19 +08:00
Holder.OnWindowInitEvent?.Invoke();
2026-03-19 16:07:51 +08:00
await OnInitializeAsync();
2025-09-05 19:46:30 +08:00
OnRegisterEvent(EventListenerProxy);
}
internal async UniTask InternalOpen(CancellationToken cancellationToken = default)
2025-09-05 19:46:30 +08:00
{
2026-03-17 17:15:31 +08:00
if (_state == UIState.Opened || _state == UIState.Opening)
return;
2025-12-24 20:44:36 +08:00
2026-03-17 17:15:31 +08:00
if (!UIStateMachine.ValidateTransition(GetType().Name, _state, UIState.Opening))
2025-12-24 20:44:36 +08:00
return;
2026-03-17 17:15:31 +08:00
int lifecycleVersion = BeginLifecycleTransition();
_state = UIState.Opening;
2025-12-24 20:44:36 +08:00
Visible = true;
Holder.OnWindowBeforeShowEvent?.Invoke();
2026-03-17 17:15:31 +08:00
try
{
2026-03-19 16:07:51 +08:00
await OnOpenAsync();
2026-03-17 17:15:31 +08:00
if (!IsCurrentLifecycleTransition(lifecycleVersion, UIState.Opening))
return;
cancellationToken.ThrowIfCancellationRequested();
await Holder.PlayOpenTransitionAsync(cancellationToken);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
return;
}
if (!IsCurrentLifecycleTransition(lifecycleVersion, UIState.Opening))
return;
_state = UIState.Opened;
2025-12-24 20:44:36 +08:00
Holder.OnWindowAfterShowEvent?.Invoke();
2025-09-05 19:46:30 +08:00
}
internal async UniTask InternalClose(CancellationToken cancellationToken = default)
2025-09-05 19:46:30 +08:00
{
2026-03-17 17:15:31 +08:00
if (_state == UIState.Closed || _state == UIState.Closing)
2026-03-16 20:52:55 +08:00
return;
2025-12-24 20:44:36 +08:00
2026-03-17 17:15:31 +08:00
if (!UIStateMachine.ValidateTransition(GetType().Name, _state, UIState.Closing))
2025-12-24 20:44:36 +08:00
return;
2026-03-17 17:15:31 +08:00
int lifecycleVersion = BeginLifecycleTransition();
_state = UIState.Closing;
2025-12-24 20:44:36 +08:00
Holder.OnWindowBeforeClosedEvent?.Invoke();
2026-03-17 17:15:31 +08:00
try
{
2026-03-19 16:07:51 +08:00
await OnCloseAsync();
2026-03-17 17:15:31 +08:00
if (!IsCurrentLifecycleTransition(lifecycleVersion, UIState.Closing))
return;
cancellationToken.ThrowIfCancellationRequested();
await Holder.PlayCloseTransitionAsync(cancellationToken);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
return;
}
if (!IsCurrentLifecycleTransition(lifecycleVersion, UIState.Closing))
return;
2025-12-24 20:44:36 +08:00
Visible = false;
2026-03-17 17:15:31 +08:00
_state = UIState.Closed;
2025-12-24 20:44:36 +08:00
Holder.OnWindowAfterClosedEvent?.Invoke();
2025-09-05 19:46:30 +08:00
}
internal void InternalUpdate()
{
if (_state != UIState.Opened) return;
OnUpdate();
UpdateChildren();
}
internal async UniTask InternalDestroy()
2026-03-09 20:39:10 +08:00
{
2025-12-24 20:44:36 +08:00
if (!UIStateMachine.ValidateTransition(GetType().Name, _state, UIState.Destroying))
return;
2026-03-17 17:15:31 +08:00
InterruptLifecycleTransition();
2025-09-05 19:46:30 +08:00
_state = UIState.Destroying;
2026-03-17 17:15:31 +08:00
Holder?.OnWindowDestroyEvent?.Invoke();
2025-09-05 19:46:30 +08:00
await DestroyAllChildren();
OnDestroy();
ReleaseEventListenerProxy();
Dispose();
_state = UIState.Destroyed;
}
internal void RefreshParams(params System.Object[] userDatas)
{
this._userDatas = userDatas;
}
2026-03-17 17:15:31 +08:00
private int BeginLifecycleTransition()
{
InterruptLifecycleTransition();
return _lifecycleVersion;
}
private void InterruptLifecycleTransition()
{
_lifecycleVersion++;
Holder?.StopTransition();
}
private bool IsCurrentLifecycleTransition(int lifecycleVersion, UIState state)
{
return lifecycleVersion == _lifecycleVersion && _state == state;
}
2025-09-05 19:46:30 +08:00
#endregion
}
}