using System.Collections.Generic; 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 UIWindow GetTopWindowInLayer(UICanvasLayer layer) { if (_layerWindowLists.TryGetValue((int)layer, out var windowList) && 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; } /// /// 获取所有可见窗口列表(从最上层到最下层) /// /// 按显示优先级排序的可见窗口列表 public List GetAllVisibleWindows() { var visibleWindows = new List(); // 从最高层级到最低层级遍历 for (int i = (int)UICanvasLayer.Max - 1; i >= 0; i--) { if (_layerWindowLists.TryGetValue(i, out var windowList)) { // 从链表尾到头(最上层到最下层)遍历该层级的窗口 var node = windowList.Last; while (node != null) { var window = node.Value; // 检查窗口是否逻辑上可见(未关闭、未销毁、且处于显示状态) if (window != null && !window.IsClosing && window.gameObject != null && window.IsShow()) { visibleWindows.Add(window); } node = node.Previous; } } } return visibleWindows; } #endregion #region Visibility Control /// /// 隐藏指定层级及以下的所有窗口 /// public List HideWindowsUpToLayer(UICanvasLayer maxLayer, params string[] exceptions) { var hiddenWindows = new List(); for (int i = 0; i <= (int)maxLayer; i++) { HideWindowsInLayerInternal((UICanvasLayer)i, hiddenWindows, exceptions); } return hiddenWindows; } /// /// 隐藏指定层级列表中的所有窗口 /// public List HideWindowsInLayers(UICanvasLayer[] layers, params string[] exceptions) { var hiddenWindows = new List(); foreach (var layer in layers) { HideWindowsInLayerInternal(layer, hiddenWindows, exceptions); } return hiddenWindows; } /// /// 隐藏单个层级的所有窗口(内部方法) /// private void HideWindowsInLayerInternal(UICanvasLayer layer, List hiddenWindows, string[] exceptions) { if (_layerWindowLists.TryGetValue((int)layer, out var windowList)) { foreach (var window in windowList) { if (window.gameObject.activeInHierarchy && !IsException(window.WindowName, exceptions)) { hiddenWindows.Add(window); window.CloseWindow(destroy:false); } } } } /// /// 检查窗口是否在例外列表中 /// private bool IsException(string windowName, string[] exceptions) { if (exceptions == null || exceptions.Length == 0) return false; foreach (var exception in exceptions) { if (exception == windowName) return true; } return false; } #endregion #region Utilities /// /// 获取层级掩码 /// public int GetLayerMask(UICanvasLayer layer) { return 1 << ((int)layer); } #endregion }