131 lines
3.6 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|