DCS/ruiyiweiUX/Assets/Scripts/Base/EnhancedUIManager.cs

486 lines
13 KiB
C#
Raw Normal View History

2026-06-09 13:59:11 +08:00
using System;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// UI面板类型用于确定面板的层级和行为
/// </summary>
public enum UIPanelType
{
Base, // 基础面板(主界面等)
Normal, // 普通面板(功能面板)
Popup, // 弹出面板(用户管理等)
Dialog, // 对话框(确认弹窗等)
System // 系统面板(警报覆盖等),最高优先级
}
/// <summary>
/// UI面板信息
/// </summary>
public class UIPanelInfo
{
public BasePanel Panel { get; set; }
public UIPanelType Type { get; set; }
public int Layer { get; set; }
public bool IsModal { get; set; } // 是否为模态面板
public string PanelName { get; set; }
public UIPanelInfo(BasePanel panel, UIPanelType type, bool isModal = false)
{
Panel = panel;
Type = type;
IsModal = isModal;
PanelName = panel.GetType().Name;
}
}
/// <summary>
/// 增强版UI管理器
/// 使用栈管理面板导航,支持层级管理和优雅的返回逻辑
/// </summary>
public class EnhancedUIManager : MonoBehaviour
{
#region
private static EnhancedUIManager _instance;
public static EnhancedUIManager Instance
{
get
{
if (_instance == null)
{
var go = new GameObject("EnhancedUIManager");
_instance = go.AddComponent<EnhancedUIManager>();
DontDestroyOnLoad(go);
}
return _instance;
}
}
#endregion
#region
[Header("UI容器")]
public Transform CanvasRoot;
public Transform BaseLayer; // 基础层(主界面)
public Transform NormalLayer; // 普通层(功能面板)
public Transform PopupLayer; // 弹窗层(用户管理)
public Transform DialogLayer; // 对话框层(确认弹窗)
public Transform SystemLayer; // 系统层(警报覆盖)
// 面板管理
private Dictionary<string, UIPanelInfo> _allPanels = new Dictionary<string, UIPanelInfo>();
private Stack<UIPanelInfo> _navigationStack = new Stack<UIPanelInfo>();
private List<UIPanelInfo> _activeDialogs = new List<UIPanelInfo>();
private UIPanelInfo _currentBasePanel;
// 层级管理
private readonly Dictionary<UIPanelType, int> _baseLayerValues = new Dictionary<UIPanelType, int>
{
{ UIPanelType.Base, 0 },
{ UIPanelType.Normal, 100 },
{ UIPanelType.Popup, 200 },
{ UIPanelType.Dialog, 300 },
{ UIPanelType.System, 400 }
};
private int _nextLayerIncrement = 0;
#endregion
#region
void Awake()
{
if (_instance == null)
{
_instance = this;
DontDestroyOnLoad(gameObject);
InitializeLayers();
}
else if (_instance != this)
{
Destroy(gameObject);
}
}
private void InitializeLayers()
{
// 查找或创建Canvas
if (CanvasRoot == null)
{
var canvas = FindObjectOfType<Canvas>();
if (canvas == null)
{
var canvasGO = new GameObject("Canvas");
canvas = canvasGO.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvasGO.AddComponent<UnityEngine.UI.CanvasScaler>();
canvasGO.AddComponent<UnityEngine.UI.GraphicRaycaster>();
}
CanvasRoot = canvas.transform;
}
// 创建层级
BaseLayer = CreateLayer("BaseLayer", 0);
NormalLayer = CreateLayer("NormalLayer", 100);
PopupLayer = CreateLayer("PopupLayer", 200);
DialogLayer = CreateLayer("DialogLayer", 300);
SystemLayer = CreateLayer("SystemLayer", 400);
}
private Transform CreateLayer(string layerName, int sortingOrder)
{
var layerGO = new GameObject(layerName);
layerGO.transform.SetParent(CanvasRoot, false);
var canvas = layerGO.AddComponent<Canvas>();
canvas.overrideSorting = true;
canvas.sortingOrder = sortingOrder;
layerGO.AddComponent<UnityEngine.UI.GraphicRaycaster>();
// 设置为全屏
var rectTransform = layerGO.GetComponent<RectTransform>();
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.sizeDelta = Vector2.zero;
rectTransform.anchoredPosition = Vector2.zero;
return layerGO.transform;
}
#endregion
#region
/// <summary>
/// 显示面板
/// </summary>
public T ShowPanel<T>(UIPanelType panelType = UIPanelType.Normal, bool isModal = false, bool isFade = true) where T : BasePanel
{
string panelName = typeof(T).Name;
// 检查是否已存在
if (_allPanels.ContainsKey(panelName))
{
BringPanelToFront(_allPanels[panelName]);
return _allPanels[panelName].Panel as T;
}
// 创建新面板
var panelGO = Instantiate(Resources.Load<GameObject>("UI/" + panelName));
if (panelGO == null)
{
Debug.LogError($"Failed to load UI prefab: {panelName}");
return null;
}
var panel = panelGO.GetComponent<T>();
if (panel == null)
{
Debug.LogError($"Panel {panelName} does not have component {typeof(T)}");
Destroy(panelGO);
return null;
}
// 设置层级
Transform targetLayer = GetTargetLayer(panelType);
panelGO.transform.SetParent(targetLayer, false);
// 创建面板信息
var panelInfo = new UIPanelInfo(panel, panelType, isModal);
panelInfo.Layer = _baseLayerValues[panelType] + _nextLayerIncrement++;
// 设置Canvas层级
SetPanelLayer(panelGO, panelInfo.Layer);
// 注册面板
_allPanels[panelName] = panelInfo;
// 处理导航逻辑
HandlePanelNavigation(panelInfo);
// 显示面板
panel.ShowMe(isFade);
// Debug.Log($"Showed panel {panelName} at layer {panelInfo.Layer}");
return panel;
}
private Transform GetTargetLayer(UIPanelType panelType)
{
return panelType switch
{
UIPanelType.Base => BaseLayer,
UIPanelType.Normal => NormalLayer,
UIPanelType.Popup => PopupLayer,
UIPanelType.Dialog => DialogLayer,
UIPanelType.System => SystemLayer,
_ => NormalLayer
};
}
private void SetPanelLayer(GameObject panelGO, int layer)
{
var canvas = panelGO.GetComponent<Canvas>();
if (canvas == null)
{
canvas = panelGO.AddComponent<Canvas>();
panelGO.AddComponent<UnityEngine.UI.GraphicRaycaster>();
}
canvas.overrideSorting = true;
canvas.sortingOrder = layer;
}
private void HandlePanelNavigation(UIPanelInfo panelInfo)
{
switch (panelInfo.Type)
{
case UIPanelType.Base:
// 基础面板,清空导航栈
ClearNavigationStack();
_currentBasePanel = panelInfo;
break;
case UIPanelType.Normal:
case UIPanelType.Popup:
// 普通面板,加入导航栈
_navigationStack.Push(panelInfo);
break;
case UIPanelType.Dialog:
// 对话框,加入对话框列表
_activeDialogs.Add(panelInfo);
break;
case UIPanelType.System:
// 系统面板,不影响导航
break;
}
}
#endregion
#region
/// <summary>
/// 关闭面板
/// </summary>
public void HidePanel<T>(bool isFade = true) where T : BasePanel
{
string panelName = typeof(T).Name;
if (_allPanels.ContainsKey(panelName))
{
HidePanel(_allPanels[panelName], isFade);
}
}
private void HidePanel(UIPanelInfo panelInfo, bool isFade = true)
{
if (panelInfo?.Panel == null) return;
// 从导航管理中移除
RemoveFromNavigation(panelInfo);
// 隐藏面板
if (isFade)
{
panelInfo.Panel.HideMe(true, () => {
DestroyPanel(panelInfo);
});
}
else
{
DestroyPanel(panelInfo);
}
// Debug.Log($"Hid panel {panelInfo.PanelName}");
}
private void RemoveFromNavigation(UIPanelInfo panelInfo)
{
// 从对话框列表移除
_activeDialogs.Remove(panelInfo);
// 从导航栈移除
if (_navigationStack.Contains(panelInfo))
{
var tempStack = new Stack<UIPanelInfo>();
while (_navigationStack.Count > 0)
{
var item = _navigationStack.Pop();
if (item != panelInfo)
{
tempStack.Push(item);
}
}
while (tempStack.Count > 0)
{
_navigationStack.Push(tempStack.Pop());
}
}
// 如果是基础面板
if (panelInfo == _currentBasePanel)
{
_currentBasePanel = null;
}
}
private void DestroyPanel(UIPanelInfo panelInfo)
{
if (panelInfo?.Panel != null)
{
Destroy(panelInfo.Panel.gameObject);
_allPanels.Remove(panelInfo.PanelName);
}
}
#endregion
#region
/// <summary>
/// 返回到主界面
/// </summary>
public void ReturnToHome()
{
// 关闭所有非基础面板
var panelsToClose = new List<UIPanelInfo>();
foreach (var panel in _allPanels.Values)
{
if (panel.Type != UIPanelType.Base)
{
panelsToClose.Add(panel);
}
}
foreach (var panel in panelsToClose)
{
HidePanel(panel, false);
}
// 清空导航栈
ClearNavigationStack();
Debug.Log("Returned to home");
}
/// <summary>
/// 返回上一个面板
/// </summary>
public bool GoBack()
{
// 优先关闭对话框
if (_activeDialogs.Count > 0)
{
var lastDialog = _activeDialogs[_activeDialogs.Count - 1];
HidePanel(lastDialog, true);
return true;
}
// 然后处理导航栈
if (_navigationStack.Count > 0)
{
var currentPanel = _navigationStack.Pop();
HidePanel(currentPanel, true);
return true;
}
return false;
}
/// <summary>
/// 关闭所有对话框
/// </summary>
public void CloseAllDialogs()
{
var dialogsToClose = new List<UIPanelInfo>(_activeDialogs);
foreach (var dialog in dialogsToClose)
{
HidePanel(dialog, false);
}
}
private void ClearNavigationStack()
{
_navigationStack.Clear();
}
private void BringPanelToFront(UIPanelInfo panelInfo)
{
if (panelInfo?.Panel == null) return;
panelInfo.Layer = _baseLayerValues[panelInfo.Type] + _nextLayerIncrement++;
SetPanelLayer(panelInfo.Panel.gameObject, panelInfo.Layer);
// 重新显示
if (!panelInfo.Panel.gameObject.activeInHierarchy)
{
panelInfo.Panel.ShowMe(true);
}
}
#endregion
#region
/// <summary>
/// 获取面板
/// </summary>
public T GetPanel<T>() where T : BasePanel
{
string panelName = typeof(T).Name;
if (_allPanels.ContainsKey(panelName))
{
return _allPanels[panelName].Panel as T;
}
return null;
}
/// <summary>
/// 检查面板是否显示
/// </summary>
public bool IsPanelShowing<T>() where T : BasePanel
{
return GetPanel<T>() != null;
}
/// <summary>
/// 获取当前活动面板数量
/// </summary>
public int GetActivePanelCount()
{
return _allPanels.Count;
}
/// <summary>
/// 获取导航栈深度
/// </summary>
public int GetNavigationDepth()
{
return _navigationStack.Count;
}
/// <summary>
/// 调试信息
/// </summary>
public void PrintDebugInfo()
{
Debug.Log($"=== UI Manager Debug Info ===");
Debug.Log($"Active Panels: {_allPanels.Count}");
Debug.Log($"Navigation Stack Depth: {_navigationStack.Count}");
Debug.Log($"Active Dialogs: {_activeDialogs.Count}");
foreach (var panel in _allPanels.Values)
{
Debug.Log($"Panel: {panel.PanelName}, Type: {panel.Type}, Layer: {panel.Layer}");
}
}
#endregion
#region Unity事件
void Update()
{
// 处理返回键
if (Input.GetKeyDown(KeyCode.Escape))
{
if (!GoBack())
{
// 如果无法返回,可以考虑退出应用或显示退出确认
Debug.Log("Cannot go back further");
}
}
}
#endregion
}