using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; using UnityEngine.Events; using Sirenix.OdinInspector; using Cysharp.Threading.Tasks; using System.Threading; using System.Threading.Tasks; using System.Linq; namespace BITKit.UX { public interface IWindowElement { string GetName(); UXElement Navigation { get; } UXElement Window { get; } UXWindowManager SubWindowManager { get; } Task Open(CancellationToken cancellationToken = default); Task Close(CancellationToken cancellationToken = default); } [System.Serializable] public class UXWindowElement : IWindowElement { [SerializeField] protected string name; [SerializeField] protected UXElement navigation; [SerializeField] protected UXElement window; [SerializeField] protected UXWindowManager subWindowManager; [SerializeField] protected bool enabled; public UXElement Navigation => navigation; public UXElement Window => window; public UXWindowManager SubWindowManager => subWindowManager; public async Task Close(CancellationToken cancellationToken = default) { try { await UniTask.SwitchToMainThread(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); await UniTask.Yield(); try { navigation.GetVisualElement().SetEnabled(true); } catch (System.Exception) { Debug.LogWarning($"Navgation:{name} 已丢失"); throw; } try { window.Set(false); } catch (System.Exception) { Debug.LogWarning($"Window:{name} 已丢失"); throw; } enabled = false; } catch (System.Exception) { Debug.LogWarning(name); throw; } } public async Task Open(CancellationToken cancellationToken = default) { await UniTask.SwitchToMainThread(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); navigation.GetVisualElement().SetEnabled(false); window.Set(true); enabled = true; } public string GetName() => name; } public class UXWindowManager : MonoBehaviour, INextble { public enum WindowState { None, Flex, Hidden } [Header(Constant.Header.Components)] [SerializeReference, SubclassSelector] public List windows = new(); public UXWindowManager subWindowManager; [Header(Constant.Header.Settings)] public UXElement startElement; [SerializeField] bool hidden; [Header(Constant.Header.Events)] public UnityEvent OnEntry = new(); public UnityEvent OnExit = new(); [Header(Constant.Header.InternalVariables)] List activeWindows = new(); IWindowElement activeWindow; public int index { get; private set; } CancellationTokenSource cts; public async void Select(UXElement element) { cts.Cancel(); cts = new(); foreach (var activeWindow in activeWindows) { await activeWindow.Close(cts.Token); OnExit.Invoke(activeWindow.GetName()); } activeWindows.Clear(); var window = windows .Find(x => x.GetName() == element.name || x.Navigation == element || x.Window == element); index = windows.IndexOf(window); activeWindows.Add(window); activeWindow = window; // currentWindow = window; try { await window.Open(); } catch (System.Exception) { Debug.LogWarning(name); if (window is null) { Debug.Log("Window is Null"); } throw; } OnEntry.Invoke(window.GetName()); } public bool Next() { if (activeWindow is not null && activeWindow.SubWindowManager) { if (activeWindow.SubWindowManager.Next()) { return true; } } if (windows.Count > index + 1) { var element = windows[index + 1].Navigation; Select(element); } else { return false; } return true; } public bool Previous() { if (activeWindow is not null && activeWindow.SubWindowManager) { if (activeWindow.SubWindowManager.Previous()) { return true; } } if (index - 1 >= 0) { var element = windows[index - 1].Navigation; Select(element); return true; } return false; } public bool Hidden { get => hidden; set { if (hidden) { Exit(); } else { Recovery(); } } } public void Exit() { hidden = true; activeWindow?.Close(); } public void Recovery() { hidden = false; activeWindow?.Open(); } void Awake() { cts = new(); var ct = gameObject.GetCancellationTokenOnDestroy(); ct.Register(cts.Cancel); } async void Start() { await UniTask.Yield(); foreach (var window in windows) { await window.Close(cts.Token); } Select(startElement); } } }