Files
Cielonos/Assets/Scripts/SLSUtilities/UI/UIPageManager.cs

90 lines
2.9 KiB
C#
Raw Normal View History

2026-05-10 11:47:55 -04:00
using System;
using System.Collections.Generic;
using SLSUtilities.General;
using UnityEngine;
namespace SLSUtilities.UI
{
/// <summary>
/// 栈式 UI 页面管理器。
/// 管理所有打开的 UIPageBase 页面,提供输入阻塞事件。
/// ESC 关闭栈顶由游戏层负责调用 CloseTopPage()。
/// 需要放置在场景中的 GameObject 上Singleton
/// </summary>
public class UIPageManager : Singleton<UIPageManager>
{
private readonly List<UIPageBase> openPages = new List<UIPageBase>();
/// <summary>
/// 输入阻塞状态变化时触发。
/// true = 首个页面打开应阻塞游戏输入false = 所有页面已关闭(应恢复输入)。
/// 游戏层通过订阅此事件联动 isCursorLocked 等状态。
/// </summary>
public event Action<bool> OnInputBlockChanged;
/// <summary>当前是否有打开的页面。</summary>
public bool HasOpenPages => openPages.Count > 0;
/// <summary>当前栈顶页面,若无则返回 null。</summary>
public UIPageBase TopPage => openPages.Count > 0 ? openPages[^1] : null;
/// <summary>
/// 将页面注册到栈顶。若为首个页面则触发 OnInputBlockChanged(true)。
/// 由 UIPageBase.Open() 内部调用,不要手动调用。
/// </summary>
public void RegisterPage(UIPageBase page)
{
if (openPages.Contains(page)) return;
bool wasEmpty = openPages.Count == 0;
openPages.Add(page);
if (wasEmpty)
{
OnInputBlockChanged?.Invoke(true);
}
}
/// <summary>
/// 将页面从栈中移除。若栈清空则触发 OnInputBlockChanged(false)。
/// 由 UIPageBase.Close() 内部调用,不要手动调用。
/// </summary>
public void UnregisterPage(UIPageBase page)
{
if (!openPages.Remove(page)) return;
if (openPages.Count == 0)
{
OnInputBlockChanged?.Invoke(false);
}
}
/// <summary>
/// 关闭栈顶页面(若其允许 ESC 关闭)。由游戏层的 ESC 处理逻辑调用。
/// </summary>
/// <returns>true 表示成功关闭了一个页面。</returns>
public bool CloseTopPage()
{
if (openPages.Count == 0) return false;
UIPageBase top = openPages[^1];
if (top.CloseOnEsc)
{
top.Close();
return true;
}
return false;
}
/// <summary>关闭所有打开的页面。</summary>
public void CloseAllPages()
{
for (int i = openPages.Count - 1; i >= 0; i--)
{
openPages[i].Close();
}
}
}
}