using System.Collections.Generic; using System.Linq; using UnityEngine; /// /// UI Canvas 层级管理器 /// 负责管理 UI 窗口的层级关系、排序和可见性控制 /// 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 /// /// UICanvasLayer 到 sortingOrder 的映射 /// private static readonly Dictionary LayerToSortingOrderMap = new Dictionary { { UICanvasLayer.BackGround, 100 }, { UICanvasLayer.Normal, 200 }, { UICanvasLayer.ForeGround, 300 }, { UICanvasLayer.Tips, 400 }, { UICanvasLayer.Guide, 500 }, { UICanvasLayer.System, 600 }, }; /// /// 每个层级的窗口列表 /// Key: UICanvasLayer 的整数值 /// Value: 该层级的窗口链表 /// private Dictionary> _layerWindowLists = new Dictionary>(16); #endregion #region Initialization /// /// 初始化:为每个 Canvas 设置 sortingOrder /// /// UI层级根节点字典 public void Initialize(IReadOnlyDictionary 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(); 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}"); } } } /// /// 清理所有数据 /// public void Clear() { _layerWindowLists.Clear(); } #endregion #region Window Management /// /// 将窗口添加到指定层级 /// public void AddWindow(UIWindow window) { if (window == null) return; var layer = (int)window.uiWindowLayer; if (!_layerWindowLists.TryGetValue(layer, out var windowList)) { windowList = new LinkedList(); _layerWindowLists.Add(layer, windowList); } // 移除已存在的(避免重复) windowList.Remove(window); // 添加到列表末尾(最上层) windowList.AddLast(window); // 设置 SiblingIndex(只在同层级内排序) window.transform.SetAsLastSibling(); } /// /// 从层级中移除窗口 /// 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 /// /// 获取指定层级的所有窗口 /// public LinkedList GetWindowsInLayer(UICanvasLayer layer) { if (_layerWindowLists.TryGetValue((int)layer, out var windowList)) { return windowList; } return new LinkedList(); } /// /// 检查指定层级是否为空 /// public bool IsLayerEmpty(UICanvasLayer layer) { if (_layerWindowLists.TryGetValue((int)layer, out var windowList)) { return windowList.Count == 0; } return true; } /// /// 获取指定层级的顶部窗口 /// public UIWindow GetTopWindowInLayer(UICanvasLayer layer) { if (_layerWindowLists.TryGetValue((int)layer, out var windowList)) { if (windowList.Count > 0) { return windowList.Last.Value; } } return null; } /// /// 获取所有层级的顶部窗口(从高到低遍历) /// 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 /// /// 隐藏指定层级及以下的所有窗口 /// public List HideWindowsUpToLayer(UICanvasLayer maxLayer, params string[] exceptions) { var hiddenWindows = new List(); 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; } /// /// 隐藏指定层级列表中的所有窗口 /// public List HideWindowsInLayers(UICanvasLayer[] layers, params string[] exceptions) { var hiddenWindows = new List(); 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 /// /// 获取层级掩码 /// public int GetLayerMask(UICanvasLayer layer) { return 1 << ((int)layer); } #endregion }