Net.Like.Xue.Tokyo/Assets/BITKit/Unity/Scripts/UX/Waiting/UXWaiting.cs

148 lines
4.6 KiB
C#
Raw Normal View History

2024-11-03 16:42:23 +08:00
using System;
using System.Collections.Concurrent;
using System.Threading;
using BITKit.Mod;
using BITKit.UX;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
namespace BITKit
{
[Serializable]
public sealed class UXWaitingSingleton : IUXWaiting
{
private IUXWaiting Implementation => UXWaiting.Singleton;
public IUXWaitingHandle Get()
{
return Implementation.Get();
}
public void Release(IUXWaitingHandle handle)
{
Implementation.Release(handle);
}
}
public sealed class WaitingHandle : IUXWaitingHandle
{
public string Message
{
get => Label.text;
set => SetMessage(value);
}
public object Container => VisualElement;
internal VisualElement VisualElement;
internal Label Label;
internal Action OnDispose;
internal Action<string> OnSetMessage;
public void SetMessage(string message) => OnSetMessage?.Invoke(message);
public void Dispose() => OnDispose?.Invoke();
}
[CustomType(typeof(IUXWaiting))]
public sealed class UXWaiting : UIToolkitOverlay,IUXWaiting
{
private const string HandleTemplate = "ux_waiting_handle";
public static UXWaiting Singleton { get; private set; }
private readonly ITicker _ticker;
public UXWaiting(IUXService uxService, ITicker ticker, CancellationTokenSource cancellationToken) : base(uxService, cancellationToken)
{
_ticker = ticker;
Singleton = this;
_visibleHandle.AddListener(Dispose);
}
protected override string DocumentPath => "ux_global_waiting";
private VisualTreeAsset _handleTemplate;
[UXBindPath("waiting-container")]
private VisualElement _container;
private readonly ConcurrentQueue<(WaitingHandle handle,string text)> _messageQueue = new();
private readonly ConcurrentQueue<WaitingHandle> _initializedHandles = new();
private readonly ConcurrentQueue<WaitingHandle> _disposeQueue = new();
private readonly ValidHandle _visibleHandle = new();
private InitializationState _initializationState;
public IUXWaitingHandle Get()
{
var handle = new WaitingHandle();
_initializedHandles.Enqueue(handle);
handle.OnSetMessage = (text) =>
{
_messageQueue.Enqueue((handle,text));
};
handle.OnDispose = () =>
{
_disposeQueue.Enqueue(handle);
_ticker.Add(OnTick);
};
_ticker.Add(OnTick);
return handle;
}
public void Release(IUXWaitingHandle handle)
{
handle.Dispose();
}
2024-12-28 23:19:55 +08:00
private void OnTick(float deltaTime)
2024-11-03 16:42:23 +08:00
{
2024-12-28 23:19:55 +08:00
if(_initializationState is not InitializationState.Initialized)return;
2024-11-03 16:42:23 +08:00
while (_initializedHandles.TryDequeue(out var handle))
{
var container = _container.Create(_handleTemplate);
_visibleHandle.AddElement(handle);
handle.VisualElement = container;
handle.Label = container.Get<Label>();
}
while (_messageQueue.TryDequeue(out var message))
{
message.handle.Label.text = message.text;
}
while (_disposeQueue.TryDequeue(out var handle))
{
handle.VisualElement.RemoveFromHierarchy();
_visibleHandle.RemoveElement(handle);
}
2025-02-24 23:03:39 +08:00
try
{
_visibleHandle.Invoke();
}
catch (Exception e)
{
Debug.LogException(e);
}
2024-11-03 16:42:23 +08:00
}
public override async UniTask InitializeAsync()
{
await base.InitializeAsync();
_handleTemplate = await ModService.LoadAsset<VisualTreeAsset>(HandleTemplate);
if (_handleTemplate is null)
{
Debug.LogError($"{HandleTemplate} is null");
}
UXUtils.Inject(this);
_container.Clear();
2025-02-24 23:03:39 +08:00
_visibleHandle.Invoke();
2024-11-03 16:42:23 +08:00
_initializationState = InitializationState.Initialized;
}
private void Dispose(bool dontDispose)
{
if (dontDispose is false)
{
Dispose();
}
}
public override void Dispose()
{
_initializationState = 0;
base.Dispose();
}
}
}