Files
Cielonos/Assets/Scripts/SLSUtilities/UI/UIPageManager.cs
2026-05-10 11:47:55 -04:00

90 lines
2.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();
}
}
}
}