using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Cysharp.Threading.Tasks; #if UNITY_EDITOR using UnityEditor; #endif using UnityEngine; using UnityEngine.UIElements; 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(); } private static EntryGroup EntryGroup = new(); /// /// 内部注册面板队列 /// private static readonly Queue RegistryQueue = new(); /// /// 内部注销面板队列 /// private static readonly Queue UnRegistryQueue = new(); /// /// 已注册面板字典 /// internal static readonly Dictionary Panels = new(); /// /// 等待启用的面板队列 /// private static readonly Stack EntryQueue = new(); /// /// 已启用面板 /// internal static IUXPanel CurrentPanel; /// /// 历史面板 /// internal static readonly Stack History = new(); 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 (History.TryPop(out var returnPanel)) { Entry(returnPanel); } } public static void Entry(IUXPanel panel) => EntryQueue.Push(panel); public static void Entry(string panelName) => EntryQueue.Push(Panels[panelName]); [SerializeReference, SubclassSelector] private IUXPanel initialPanel; private bool initialized; private void Awake() { DI.Register(this); } private void Start() { EntryGroup.OnEntry += OnEntry; EntryGroup.OnExit += OnExit; if (initialPanel is not null) { Entry(initialPanel); } } private static void OnExit(IUXPanel obj) { History.Push(obj); } private static void OnEntry(IUXPanel obj) { CurrentPanel = obj; } private void Update() { while (UnRegistryQueue.TryDequeue(out var result)) { if (result is null) continue; EntryGroup.list.Remove(result); Panels.Remove(result.Index); } while (RegistryQueue.TryDequeue(out var result)) { if (result is null) continue; EntryGroup.list.Add(result); Panels.Set(result.Index, result); } if (EntryQueue.TryPop(out var nextPanel)) { 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 (initialized is false && initialPanel is not null) // { // initialized = true; // Entry(initialPanel); // } // // if (!EntryQueue.TryPop(out var next) || next is null) return; // // if (Panels.ContainsKey(next.Index) is false) return; // // while (EntryCompletedPanels.TryPop(out var entryCompletedPanel)) // { // entryCompletedPanel?.Exit(); // } // // try // { // next.Entry(); // } // catch (Exception e) // { // Debug.LogWarning(next.Index); // Debug.LogException(e); // } // // BITAppForUnity.AllowCursor.SetElements(this, next.AllowCursor); // BITInputSystem.AllowInput.SetElements(this, next.AllowInput); // // EntryCompletedPanels.Push(next); // History.Push(next); } 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); } #if UNITY_EDITOR [CustomEditor(typeof(UXService))] public class UXServiceInspector:BITInspector { private Label currentPanelLabel; private Label panelsLabel; private Label historyLabel; public override VisualElement CreateInspectorGUI() { FillDefaultInspector(); CreateSubTitle("States"); currentPanelLabel = root.Create