NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/UI/UICanvasLayerManager.cs

269 lines
7.5 KiB
C#
Raw Normal View History

2025-12-19 16:15:25 +08:00
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
/// <summary>
/// UI Canvas 层级管理器
/// 负责管理 UI 窗口的层级关系、排序和可见性控制
/// </summary>
public class UICanvasLayerManager
{
#region Singleton
private static UICanvasLayerManager _instance;
public static UICanvasLayerManager Instance
{
get
{
if (_instance == null)
{
_instance = new UICanvasLayerManager();
}
return _instance;
}
}
private UICanvasLayerManager() { }
#endregion
#region Fields
/// <summary>
/// UICanvasLayer 到 sortingOrder 的映射
/// </summary>
private static readonly Dictionary<UICanvasLayer, int> LayerToSortingOrderMap = new Dictionary<UICanvasLayer, int>
{
{ UICanvasLayer.BackGround, 100 },
{ UICanvasLayer.Normal, 200 },
{ UICanvasLayer.ForeGround, 300 },
{ UICanvasLayer.Tips, 400 },
{ UICanvasLayer.Guide, 500 },
{ UICanvasLayer.System, 600 },
};
/// <summary>
/// 每个层级的窗口列表
/// Key: UICanvasLayer 的整数值
/// Value: 该层级的窗口链表
/// </summary>
private Dictionary<int, LinkedList<UIWindow>> _layerWindowLists = new Dictionary<int, LinkedList<UIWindow>>(16);
#endregion
#region Initialization
/// <summary>
/// 初始化:为每个 Canvas 设置 sortingOrder
/// </summary>
/// <param name="rootDic">UI层级根节点字典</param>
public void Initialize(IReadOnlyDictionary<UICanvasLayer, GameObject> rootDic)
{
if (rootDic == null)
{
DebugUtil.LogError("[UICanvasLayerManager] Initialize failed: rootDic is null");
return;
}
foreach (var kv in LayerToSortingOrderMap)
{
var layer = kv.Key;
if (rootDic.TryGetValue(layer, out var rootGo))
{
var canvas = rootGo.GetComponent<Canvas>();
if (canvas != null)
{
canvas.overrideSorting = true;
canvas.sortingOrder = kv.Value;
DebugUtil.Log($"[UICanvasLayerManager] Set {rootGo.name} sortingOrder = {canvas.sortingOrder} for layer {layer}");
}
else
{
DebugUtil.LogWarning($"[UICanvasLayerManager] {rootGo.name} has no Canvas component!");
}
}
else
{
DebugUtil.LogWarning($"[UICanvasLayerManager] Cannot find Canvas for layer: {layer}");
}
}
}
/// <summary>
/// 清理所有数据
/// </summary>
public void Clear()
{
_layerWindowLists.Clear();
}
#endregion
#region Window Management
/// <summary>
/// 将窗口添加到指定层级
/// </summary>
public void AddWindow(UIWindow window)
{
if (window == null) return;
var layer = (int)window.uiWindowLayer;
if (!_layerWindowLists.TryGetValue(layer, out var windowList))
{
windowList = new LinkedList<UIWindow>();
_layerWindowLists.Add(layer, windowList);
}
// 移除已存在的(避免重复)
windowList.Remove(window);
// 添加到列表末尾(最上层)
windowList.AddLast(window);
// 设置 SiblingIndex(只在同层级内排序)
window.transform.SetAsLastSibling();
}
/// <summary>
/// 从层级中移除窗口
/// </summary>
public void RemoveWindow(UIWindow window)
{
if (window == null) return;
var layer = (int)window.uiWindowLayer;
if (_layerWindowLists.TryGetValue(layer, out var windowList))
{
windowList.Remove(window);
}
}
#endregion
#region Query
/// <summary>
/// 获取指定层级的所有窗口
/// </summary>
public LinkedList<UIWindow> GetWindowsInLayer(UICanvasLayer layer)
{
if (_layerWindowLists.TryGetValue((int)layer, out var windowList))
{
return windowList;
}
return new LinkedList<UIWindow>();
}
/// <summary>
/// 检查指定层级是否为空
/// </summary>
public bool IsLayerEmpty(UICanvasLayer layer)
{
if (_layerWindowLists.TryGetValue((int)layer, out var windowList))
{
return windowList.Count == 0;
}
return true;
}
/// <summary>
/// 获取指定层级的顶部窗口
/// </summary>
public UIWindow GetTopWindowInLayer(UICanvasLayer layer)
{
if (_layerWindowLists.TryGetValue((int)layer, out var windowList))
{
if (windowList.Count > 0)
{
return windowList.Last.Value;
}
}
return null;
}
/// <summary>
/// 获取所有层级的顶部窗口(从高到低遍历)
/// </summary>
public bool GetTopWindow(out UIWindow window, out UICanvasLayer layer, int banLayerMask = 0)
{
for (int i = (int)UICanvasLayer.Max - 1; i >= 0; i--)
{
if (((1 << i) & banLayerMask) == 0)
{
if (_layerWindowLists.TryGetValue(i, out var windowList) && windowList.Count > 0)
{
window = windowList.Last.Value;
if (window != null)
{
layer = (UICanvasLayer)i;
return true;
}
}
}
}
window = null;
layer = UICanvasLayer.Max;
return false;
}
#endregion
#region Visibility Control
/// <summary>
/// 隐藏指定层级及以下的所有窗口
/// </summary>
public List<UIWindow> HideWindowsUpToLayer(UICanvasLayer maxLayer, params string[] exceptions)
{
var hiddenWindows = new List<UIWindow>();
for (int i = 0; i <= (int)maxLayer; i++)
{
if (_layerWindowLists.TryGetValue(i, out var windowList))
{
foreach (var window in windowList)
{
if (window.gameObject.activeInHierarchy && !exceptions.Contains(window.WindowName))
{
hiddenWindows.Add(window);
window.HideWindow();
}
}
}
}
return hiddenWindows;
}
/// <summary>
/// 隐藏指定层级列表中的所有窗口
/// </summary>
public List<UIWindow> HideWindowsInLayers(UICanvasLayer[] layers, params string[] exceptions)
{
var hiddenWindows = new List<UIWindow>();
foreach (var layer in layers)
{
if (_layerWindowLists.TryGetValue((int)layer, out var windowList))
{
foreach (var window in windowList)
{
if (window.gameObject.activeInHierarchy && !exceptions.Contains(window.WindowName))
{
hiddenWindows.Add(window);
window.HideWindow();
}
}
}
}
return hiddenWindows;
}
#endregion
#region Utilities
/// <summary>
/// 获取层级掩码
/// </summary>
public int GetLayerMask(UICanvasLayer layer)
{
return 1 << ((int)layer);
}
#endregion
}