BITKit/Src/Unity/Scripts/UX/Waiting/UXWaiting.cs

112 lines
3.5 KiB
C#

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using BITKit.UX;
using UnityEngine;
using Cysharp.Threading.Tasks;
using kcp2k;
using UnityEngine.Pool;
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);
}
}
[CustomType(typeof(IUXWaiting))]
public class UXWaiting : MonoBehaviourSingleton<UXWaiting>,IUXWaiting
{
public sealed class WaitingHandle : IUXWaitingHandle
{
public string Message
{
get => label.text;
set => SetMessage(value);
}
public object Container => container;
internal VisualElement container;
internal Label label;
internal Action OnDispose;
internal Action<string> OnSetMessage;
public void SetMessage(string message) => OnSetMessage?.Invoke(message);
public void Dispose() => OnDispose?.Invoke();
}
[SerializeField] private VisualTreeAsset handleTemplate;
[SerializeField] private bool asGlobal;
[UXBindPath("waiting-container")]
private VisualElement _container;
[UXBindPath("waiting-root")]
private VisualElement _root;
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();
public IUXWaitingHandle Get()
{
var handle = new WaitingHandle();
_initializedHandles.Enqueue(handle);
handle.OnSetMessage = (text) =>
{
_messageQueue.Enqueue((handle,text));
};
handle.OnDispose = () =>
{
_disposeQueue.Enqueue(handle);
};
return handle;
}
public void Release(IUXWaitingHandle handle)
{
handle.Dispose();
}
private void Update()
{
while (_initializedHandles.TryDequeue(out var handle))
{
var container = _container.Create(handleTemplate);
handle.container = 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.container.RemoveFromHierarchy();
}
_visibleHandle.SetElements(0, _container.childCount>0);
}
protected override void Awake()
{
base.Awake();
UXUtils.Inject(this);
_container.Clear();
if (asGlobal)
{
DI.Register<IUXWaiting>(this);
}
_root.SetActive(false);
}
private void Start()
{
_visibleHandle.AddListener(_root.SetActive);
_visibleHandle.Invoke();
}
}
}