using System; using System.Collections.Generic; using UnityEngine; namespace UI.PanelStack { public class UIPanelStack : MonoBehaviour { public static UIPanelStack Instance { get; private set; } private readonly List stack = new List(); private Func escapeOpenHandler; [SerializeField] private bool debugLogs = true; private sealed class Entry { public UIPanelKind kind; public GameObject root; public Action closeAction; } private void Awake() { if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } public void Push(UIPanelKind kind, GameObject root, Action closeAction) { if (root == null) { return; } Remove(root); stack.Add(new Entry { kind = kind, root = root, closeAction = closeAction }); if (debugLogs) Debug.Log($"[UIPanelStack] Push kind={kind} root={root.name} count={stack.Count}"); } public bool Remove(GameObject root) { if (root == null) { return false; } for (int i = stack.Count - 1; i >= 0; i--) { if (stack[i].root == root) { stack.RemoveAt(i); if (debugLogs) Debug.Log($"[UIPanelStack] Remove root={root.name} count={stack.Count}"); return true; } } return false; } public bool CloseTop() { CleanupInactive(); if (stack.Count == 0) { return false; } Entry top = stack[stack.Count - 1]; stack.RemoveAt(stack.Count - 1); if (top.root == null) { return false; } if (top.closeAction != null) { if (debugLogs) Debug.Log($"[UIPanelStack] CloseTop via action kind={top.kind} root={top.root.name} remain={stack.Count}"); top.closeAction.Invoke(); return true; } if (debugLogs) Debug.Log($"[UIPanelStack] CloseTop via SetActive(false) kind={top.kind} root={top.root.name} remain={stack.Count}"); top.root.SetActive(false); return true; } public void SetEscapeOpenHandler(Func handler) { escapeOpenHandler = handler; if (debugLogs) Debug.Log($"[UIPanelStack] SetEscapeOpenHandler set={(handler!=null)}"); } public void ClearEscapeOpenHandler(Func handler) { if (handler == null) { return; } if (escapeOpenHandler == handler) { escapeOpenHandler = null; } } public bool TryOpenOnEscapeWhenEmpty() { if (escapeOpenHandler == null) { return false; } bool result = escapeOpenHandler.Invoke(); if (debugLogs) Debug.Log($"[UIPanelStack] TryOpenOnEscapeWhenEmpty result={result}"); return result; } public bool IsAnyOpen() { CleanupInactive(); return stack.Count > 0; } private void CleanupInactive() { for (int i = stack.Count - 1; i >= 0; i--) { if (stack[i].root == null || !stack[i].root.activeInHierarchy) { stack.RemoveAt(i); } } } } }