Files
2026-07-08 20:42:51 +08:00

131 lines
3.6 KiB
C#

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<Entry> stack = new List<Entry>();
private Func<bool> 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<bool> handler)
{
escapeOpenHandler = handler;
if (debugLogs) Debug.Log($"[UIPanelStack] SetEscapeOpenHandler set={(handler!=null)}");
}
public void ClearEscapeOpenHandler(Func<bool> 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);
}
}
}
}
}