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

486 lines
13 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 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
}