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,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 OnSetMessage; public async void SetMessage(string message) { OnSetMessage?.Invoke(label,message); // await UniTask.SwitchToMainThread(); // BIT4Log.Log($"SetMessage {message}"); // if(container.panel!=null) // { // label.text = message; // } // else // { // BIT4Log.Log("WaitingHandle is destroyed"); // } } 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 Pool _pool; private readonly HashSet _handles = new(); private readonly ConcurrentQueue<(Label label,string text)> _messageQueue = new(); public IUXWaitingHandle Get() { var handle = _pool.Take(); Active(); _handles.Add(handle); handle.OnDispose = () => Release(handle); return handle; async void Active() { await UniTask.SwitchToMainThread(); handle.As().container.SetActive(true); _root.SetActive(true); } } public async void Release(IUXWaitingHandle handle) { await UniTask.SwitchToMainThread(); if (destroyCancellationToken.IsCancellationRequested) return; _pool.Return(handle.As()); _handles.Remove(handle.As()); Check(); } private void Update() { while (_messageQueue.TryDequeue(out var message)) { message.label.text = message.text; } } protected override void Awake() { base.Awake(); UXUtils.Inject(this); _container.Clear(); _pool = new Pool(Create,OnReset,10); if (asGlobal) { DI.Register(this); } _root.SetActive(false); } private void Start() { Check(); } private async void OnReset(IUXWaitingHandle obj) { await UniTask.SwitchToMainThread(); obj.As().container.SetActive(false); } [BIT] private async void Check() { await UniTask.Yield(); await UniTask.SwitchToMainThread(); if(destroyCancellationToken.IsCancellationRequested) return; _root.SetActive(_handles.Count>0); } private WaitingHandle Create() { var handle = new WaitingHandle { container = _container.Create(handleTemplate), label = _container.Q