using System; using System.Collections.Generic; using System.Text; using UnityEngine; namespace BITKit.UX { /// /// 适用于Unity的UX Service /// public class UxService : MonoBehaviour, IUXService { /// /// 重新初始化,使用确保在所有子系统注册后执行 /// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void Initialized() { RegistryQueue.Clear(); UnRegistryQueue.Clear(); Panels.Clear(); EntryQueue.Clear(); _currentPanel = null; History.Clear(); _entryGroup = new EntryGroup(); _windowEntryGroup = new EntryGroup(); } private static EntryGroup _entryGroup = new(); private static EntryGroup _windowEntryGroup = new(); /// /// 内部注册面板队列 /// private static readonly Queue RegistryQueue = new(); /// /// 内部注销面板队列 /// private static readonly Queue UnRegistryQueue = new(); /// /// 已注册面板字典 /// private static readonly Dictionary Panels = new(); /// /// 等待启用的面板队列 /// private static readonly Stack EntryQueue = new(); /// /// 返回面板缓冲区 /// private static readonly DoubleBuffer ReturnBuffer = new(); /// /// 已启用面板 /// private static IUXPanel _currentPanel; /// /// 历史面板 /// private static readonly Stack History = new(); /// /// 清空历史面板,通常用于关闭返回上一步 /// public static void ClearHistory() => History.Clear(); public static void Register(IUXPanel panel) => RegistryQueue.Enqueue(panel); public static void UnRegister(IUXPanel panel) => UnRegistryQueue.Enqueue(panel); public static void Entry() where T : IUXPanel => EntryQueue.Push(Panels[typeof(T).Name]); public static void Return() { if(_windowEntryGroup.TryGetEntried(out _)) { _windowEntryGroup.Entry(-1); return; } if (History.TryPop(out var returnPanel)) { ReturnBuffer.Release(returnPanel); } } public static void Entry(IUXPanel panel) => EntryQueue.Push(panel); private static void Entry(string panelName) => EntryQueue.Push(Panels[panelName]); [SerializeReference, SubclassSelector] private IUXPanel initialPanel; [SerializeField, ReadOnly(HideLabel = true)] private string log; private StringBuilder _reportBuilder = new(); private bool _initialized; private void Start() { _entryGroup.OnEntry += OnEntry; _entryGroup.OnExit += OnExit; } private static void OnExit(IUXPanel obj) { //History.Push(obj); } private static void OnEntry(IUXPanel obj) { _currentPanel = obj; } private void Update() { try { while (RegistryQueue.TryDequeue(out var result)) { if (result is null) continue; _reportBuilder.AppendLine(("注册面板:" + result.Index)); _entryGroup.list.Add(result); Panels.Set(result.Index, result); } while (UnRegistryQueue.TryDequeue(out var result)) { if (result is null) continue; _reportBuilder.AppendLine(("注销面板:" + result.Index)); _entryGroup.list.Remove(result); Panels.Remove(result.Index); } if (ReturnBuffer.TryGetRelease(out var returnPanel)) { _reportBuilder.AppendLine(("返回面板:" + returnPanel.Index)); _entryGroup.Entry(x=>x.Index==returnPanel.Index); BITAppForUnity.AllowCursor.SetElements(this, returnPanel.AllowCursor); BITInputSystem.AllowInput.SetElements(this, returnPanel.AllowInput); } if (EntryQueue.TryPop(out var nextPanel)) { if (nextPanel.IsWindow) { _reportBuilder.AppendLine(("窗口面板:" + nextPanel.Index)); _windowEntryGroup.Entry(nextPanel); return; } _reportBuilder.AppendLine(("启用面板:" + nextPanel.Index)); _windowEntryGroup.Entry(-1); History.Push(_currentPanel); _entryGroup.Entry(x=>x.Index==nextPanel.Index); BITAppForUnity.AllowCursor.SetElements(this, nextPanel.AllowCursor); BITInputSystem.AllowInput.SetElements(this, nextPanel.AllowInput); } if (_entryGroup.TryGetEntried(out var currentPanel)) { currentPanel.OnUpdate(Time.deltaTime); } if(_windowEntryGroup.TryGetEntried(out var windowPanel)) { windowPanel.OnUpdate(Time.deltaTime); } if (currentPanel is null && Panels.Count > 0) { Entry(initialPanel); } } catch (Exception e) { BIT4Log.LogException(e); } log = _reportBuilder.ToString(); } void IUXService.Register(IUXPanel panel) => Register(panel); void IUXService.UnRegister(IUXPanel panel) => UnRegister(panel); void IUXService.Entry() => Entry(); void IUXService.Return() => Return(); void IUXService.Entry(IUXPanel panel) => Entry(panel); void IUXService.Entry(string panelName) => Entry(panelName); } }