AkiraPixelWind/Assets/Scripts/Main/UI/UIMgr/UIMgr.cs
2022-12-29 18:20:40 +08:00

626 lines
17 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;
using UnityEngine.UI;
//using UnityEditor;
using Game;
using Axibug.Resources;
using Axibug.Runtime;
using UnityEngine.Events;
using Axibug;
using UnityEditor;
using Game;
public enum eUINodeType
{
NodeBg = 0, // 游戏根层显示, 主要用来显示背景贴图
NodeScreen, // 全屏UI, 比如主场景的主UI, 战斗场景战斗UI.
NodeUI, // 功能UI等
NodeLoading, // 加载界面层
NodeTip, // 提示层
}
/// <summary>
/// 为了兼容异步加载的问题定义的数据结构
/// </summary>
public class CustomUserData
{
public UIBase ui;
public Type mType;
public string uiName;
public Transform tfParent;
public AssetBundle descBundle;
public object[] userData;
}
/// <summary>
/// UIManager
/// UI管理器
/// 常用方法:
/// UIMgr.Instance.Open<T>() 显示某个UI
/// UIMgr.Instance.OpenInChild() 在某个结点下显示UI
/// UIMgr.Instance.GetUI<T>() 获取某个打开的UI实例
/// UIMgr.Instance.GetTopUI() 获取最外层UI
/// UIMgr.Instance.Hide<T>() 隐藏某个UI
/// UIMgr.Instance.HideAll() 隐藏所有UI
/// UIMgr.Instance.CloseUI<T>() 销毁某个UI
/// UIMgr.Instance.CloseUI(UIBase _ui) 销毁某个UI
/// UIMgr.Instance.Clean() 销毁所有UI
/// UIMgr.Instance.CleanExceptLoading() 销毁除LoadingUI外的所有UI
/// UIMgr.Instance.MoveRootUp() 移动UI上下位置
/// </summary>
public class UIMgr : GameComponent
{
public static UIMgr Instance;
public static readonly string UIPrefabRootPath = "Assets/GameAssets/Prefabs/UI"; // UI Prefab根目录
//public static readonly string UIPathConfigFile = "Assets/GameAssets/TextAssets/UIMgrPath.asset"; // UI Prefab资源路径文件名
public static readonly string UIPathConfigFile = "Assets/GameAssets/TextAssets/UIMgrPath.json"; // UI Prefab资源路径文件名
public static readonly string UIMainHubSubConfigFile = "Assets/GameAssets/TextAssets/UIMainHubSubConfig.asset"; //主UI的子UI预制体名
public Transform m_NodeBg; // 背景层
public Transform m_NodeScreen; // 全屏UI层, 比如主场景的主UI, 战斗场景战斗UI. 人物信息, 血条, 主界面的小地图等等
public Transform m_NodeUI; // UI层, 功能层. 比如强化, 宠物等
public Transform m_NodeLoading; // 加载界面层
public Transform m_NodeTip; // 弹窗提示层
public RectTransform m_RtfShelter; // 遮挡 用于4:3屏幕适配
private Transform m_NodeUITop; // UI顶层
private static UIBase mTopUI; // 当前最外层UI
private static Dictionary<string, UIBase> m_UIDic;
public static Dictionary<string, UIBase> UIDic
{
get
{
if (m_UIDic == null)
m_UIDic = new Dictionary<string, UIBase>();
return m_UIDic;
}
}
// 同步方式 保留
private static Dictionary<string, string> m_AllUIPath;
public static Dictionary<string, string> AllUIPath
{
get
{
if (m_AllUIPath == null)
{
m_AllUIPath = new Dictionary<string, string>();
m_AllUIPath = UIMgrPath.GetDic();
}
return m_AllUIPath;
}
}
public static Dictionary<eUINodeType, Transform> m_TypeParent;
private RawImage m_imgBg;
public Camera m_camera;
private bool m_isScreenClip; // 屏幕是否用黑边裁剪了
public bool IsScreenClip
{
get { return m_isScreenClip; }
set { m_isScreenClip = true; }
}
public Type hotResources = null;
protected override void Awake()
{
base.Awake();
Instance = this;
//DontDestroyOnLoad(this);
m_camera = transform.Find("Camera").GetComponent<Camera>();
m_NodeBg = transform.Find("Canvas/NodeBg");
m_NodeScreen = transform.Find("Canvas/NodeScreen");
m_NodeUI = transform.Find("Canvas/NodeUI");
m_NodeLoading = transform.Find("Canvas/NodeLoading");
m_NodeTip = transform.Find("Canvas/NodeTip");
m_RtfShelter = transform.Find("Canvas/RtfShelter").GetComponent<RectTransform>();
m_TypeParent = new Dictionary<eUINodeType, Transform>
{
{eUINodeType.NodeBg, m_NodeBg },
{eUINodeType.NodeScreen, m_NodeScreen },
{eUINodeType.NodeUI, m_NodeUI },
{eUINodeType.NodeTip, m_NodeTip },
{eUINodeType.NodeLoading, m_NodeLoading },
};
m_NodeUITop = m_NodeUI.Find("Top");
m_imgBg = m_NodeBg.Find("imgBg").GetComponent<RawImage>();
}
private void OnEnable()
{
Inform.Listen(eInformId.SenceChange, CleanExceptLoading);
}
private void OnDisable()
{
Inform.Cancel(eInformId.SenceChange, CleanExceptLoading);
}
public T LoadAsset<T>(string assetName) where T : UnityEngine.Object
{
if (AppEntry.Base.EditorResourceMode)
{
#if UNITY_EDITOR
T asset = AssetDatabase.LoadAssetAtPath<T>(assetName);
return asset;
#endif
}
string rootPath = "Assets/GameAssets";
string tmp = assetName.Remove(0, rootPath.Length + 1);
int idx = tmp.LastIndexOf('/');
string bundleName = tmp.Substring(0, idx);
int id = assetName.GetHashCode();
return PrefabManager.LoadPrefab<T>(bundleName.ToLower(), assetName, id, null);
}
public GameObject Clone(string assetName, Transform parent = null)
{
string rootPath = "Assets/GameAssets";
string tmp = assetName.Remove(0, rootPath.Length + 1);
int idx = tmp.LastIndexOf('/');
string bundleName = tmp.Substring(0, idx);
//if (bundleName.Contains("Login/"))
//{
// idx = bundleName.LastIndexOf('/');
// bundleName = bundleName.Substring(0, idx);
//}
UnityEngine.Object asset = null;
if (AppEntry.Base.EditorResourceMode)
{
#if UNITY_EDITOR
asset = AssetDatabase.LoadAssetAtPath<GameObject>(assetName);
#endif
}
else
{
int id = assetName.GetHashCode();
asset = PrefabManager.LoadPrefab<UnityEngine.Object>(bundleName.ToLower(), assetName, id, parent);
}
if (asset == null)
{
Debug.LogError($"asset加载失败path={assetName}");
return null;
}
GameObject go = Instantiate(asset, parent) as GameObject;
if (go == null)
{
Debug.LogError("LoadPrefabByEditor2. go == null. asset:" + asset);
}
return go;
}
public UIBase OpenUI<T>(eUINodeType _layer = eUINodeType.NodeUI, params object[] _params) where T : UIBase
{
Transform _tfParent = m_TypeParent[_layer];
return OpenUIInChild<T>(_tfParent, _params);
//return OpenUIInChild<T>(_layer, _params);
}
public UIBase OpenUIInChild<T>(Transform _tfParent = null , params object[] _params) where T:UIBase
{
Type vT = typeof(T);
string uiName = vT.Name;
return OpenUIInChild(uiName, _tfParent, vT, _params) as T;
}
public UIBase OpenUIInChild(string _uiName, Transform _tfParent = null, Type _typeOfT = null, params object[] _params)
{
string uiName = _uiName;
if (!AllUIPath.ContainsKey(uiName))
{
Debug.LogError("OpenUIInChild. not found UIPath. uiName:" + uiName);
return null;
}
var uiPath = AllUIPath[uiName];
if (string.IsNullOrEmpty(uiPath))
{
Debug.LogError("OpenUIInChild. string.IsNullOrEmpty(uiPath). uiName:" + uiName);
return null;
}
if(_tfParent == null)
_tfParent = m_TypeParent[eUINodeType.NodeUI];
// 如果已经有缓存的了 则直接激活换成缓存里的
if (UIDic.ContainsKey(uiName))
{
var uiScript = UIDic[uiName];
uiScript.gameObject.SetActive(true);
uiScript.transform.SetParent(_tfParent);
UIMoveTop(uiScript);
uiScript.Show(_params);
return uiScript;
}
Log.Debug($"uipath = {uiPath}");
GameObject uiObj = Clone(uiPath, _tfParent);
uiObj.name = uiName;
UIBase uiBase = uiObj.GetComponent<UIBase>();
if (uiBase == null)
{
uiBase = uiObj.AddComponent(_typeOfT) as UIBase;
}
UIDic.Add(uiName, uiBase);
UIMoveTop(uiBase);
uiBase.Show(_params);
return uiBase;
}
/// <summary>
/// 跳转UI, 请用Common.SkipToUI 来跳转UI
/// </summary>
/// <param name="uiScript"></param>
//public UIBase SkipToUI(int _funcCid, int _funcSubCid = 0)
private void UIMoveTop(UIBase uiScript)
{
mTopUI = uiScript;
MoveRootUp(uiScript.transform, m_NodeUITop);
MoveRootUp(m_NodeUITop, uiScript.transform);
}
/// <summary>
/// 关闭UI 建议在UI内直接调用CloseUI(this)
/// </summary>
public void CloseUI(string _uiName)
{
var strNameAry = _uiName.Split('.');
_uiName = strNameAry[strNameAry.Length - 1];
if (!UIDic.ContainsKey(_uiName))
{
Debug.LogError("缓存中 没找到该UI _uiName:" + _uiName);
return;
}
//这里改一下直接删除ab包
if (!AllUIPath.ContainsKey(_uiName))
{
Debug.LogError("CloseUI. not found UIPath. uiName:" + _uiName);
return ;
}
var uiPath = AllUIPath[_uiName];
string rootPath = "Assets/GameAssets";
string tmp = uiPath.Remove(0, rootPath.Length + 1);
int idx = tmp.LastIndexOf('/');
string bundleName = tmp.Substring(0, idx);
Hide(_uiName);
if(!AppEntry.Base.EditorResourceMode)
AssetBundleManager.UnLoad(bundleName.ToLower());
GameObject.Destroy(UIDic[_uiName].gameObject);
if (UIDic.ContainsKey(_uiName))
UIDic.Remove(_uiName);
}
/// <summary>
/// 关闭UI
/// </summary>
public void CloseUI<T>() where T : UIBase
{
string uiName = typeof(T).Name;
CloseUI(uiName);
}
/// <summary>
/// 关闭UI 建议在UI内直接调用CloseUI(this)
/// </summary>
/// <param name="_ui">界面实力</param>
public void CloseUI(UIBase _ui)
{
if (_ui == null)
{
Debug.LogError("CloseUI, _ui == null.");
return;
}
Type _t = _ui.GetType();
string uiName = _t.Name;
CloseUI(uiName);
}
public void CloseAll()
{
List<string> needCloseUIName = new List<string>();
foreach (KeyValuePair<string, UIBase> Pair in UIDic)
{
needCloseUIName.Add(Pair.Key);
}
UIDic.Clear();
HideBg();
}
public void CloseAllUI()
{
List<UIBase> tCloseList = new List<UIBase>();
foreach (var ui in UIDic.Values)
{
tCloseList.Add(ui);
}
foreach (var ui in tCloseList)
{
CloseUI(ui);
}
}
public void Hide(UIBase _ui)
{
if (_ui == null)
{
Debug.LogError("CloseUI, _ui == null.");
return;
}
Type _t = _ui.GetType();
string uiName = _t.Name;
Hide(uiName);
}
public void Hide<T>() where T : UIBase
{
string uiName = typeof(T).Name;
Hide(uiName);
}
public void Hide(string uiName)
{
if (!UIDic.ContainsKey(uiName))
{
Debug.LogError("缓存中 没找到该UI uiName:" + uiName);
return;
}
var ui = UIDic[uiName];
if (ui == null)
{
UIDic.Remove(uiName);
return;
}
ui.gameObject.SetActive(false);
if (ui == mTopUI)
mTopUI = null;
}
public void HideAll()
{
foreach (KeyValuePair<string, UIBase> Pair in UIDic)
{
Hide(Pair.Key);
}
}
/// <summary>
/// 判断某个界面是否已经打开
/// </summary>
public bool IsOpen<T>() where T : UIBase
{
string uiName = typeof(T).Name;
return IsOpen(uiName);
}
public bool IsOpen(string uiName)
{
if (!UIDic.ContainsKey(uiName))
{
//Debug.LogError("缓存中 没找到该UI uiName:" + uiName);
return false;
}
var ui = UIDic[uiName];
if (ui == null)
{
UIDic.Remove(uiName);
return false;
}
return ui.gameObject.activeSelf;
}
/// <summary>
/// 获取打开的某个界面
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>null:没有打开</returns>
public T GetUI<T>() where T : UIBase
{
string uiName = typeof(T).Name;
return GetUI(uiName) as T;
}
/// <summary>
/// 获取UI
/// </summary>
/// <param name="_uiName"></param>
/// <returns></returns>
public UIBase GetUI(string _uiName)
{
if (UIDic.ContainsKey(_uiName))
{
return UIDic[_uiName];
}
Debug.Log("GetUI. return null. _uiName:" + _uiName);
return null;
}
/// <summary>
/// 获取最顶层的UI
/// </summary>
/// <returns>null:没有打开的UI</returns>
public UIBase GetTopUI()
{
if (mTopUI != null)
return mTopUI;
int maxSiblingIdx = -9999;
foreach (var ui in UIDic.Values)
{
if (ui == null)
continue;
int siblingIdx = ui.transform.GetSiblingIndex();
if (siblingIdx <= maxSiblingIdx)
continue;
mTopUI = ui;
maxSiblingIdx = siblingIdx;
}
if (mTopUI == null)
{
// 获取最外层
Debug.Log("GetTopUI. mTopUI == null. 当前没有打开的UI");
}
return mTopUI;
}
public void HideBg()
{
if (m_imgBg.gameObject.activeSelf)
m_imgBg.gameObject.SetActive(false);
}
public void Clean()
{
foreach (KeyValuePair<string, UIBase> Pair in UIDic)
{
if (Pair.Value.gameObject != null)
GameObject.Destroy(Pair.Value.gameObject);
}
UIDic.Clear();
HideBg();
}
// 清理除Loading以外的UI
public void CleanExceptLoading()
{
List<string> exceptUIList = new List<string>() { "LoadingUI" };
CleanExceptList(exceptUIList);
}
// 清理除传入列表相关UI
public void CleanExceptList(List<string> _uiNameList = null)
{
if (_uiNameList == null || _uiNameList.Count <= 0)
{
Clean();
return;
}
List<string> needRemoveKeyLst = new List<string>();
foreach (KeyValuePair<string, UIBase> Pair in UIDic)
{
if (Pair.Value.transform.parent == m_NodeLoading)
continue;
if (Pair.Value.gameObject != null)
{
if (_uiNameList.Contains(Pair.Key))
continue;
needRemoveKeyLst.Add(Pair.Key);
}
}
for (int i = 0; i < needRemoveKeyLst.Count; i++)
{
CloseUI(needRemoveKeyLst[i]);
}
needRemoveKeyLst.Clear();
HideBg();
}
public void CloseCamera()
{
m_camera.gameObject.SetActive(false);
}
public void ShowCamera()
{
if (m_camera)
m_camera.gameObject.SetActive(true);
}
/// <summary>
/// 把一个UI的Transform _Tf1 移到 另一个UI的Transform _Tf2 上面
/// </summary>
public void MoveRootUp(Transform _Tf1, Transform _Tf2)
{
_Tf1.SetSiblingIndex(_Tf2.GetSiblingIndex() + 1);
}
/// <summary>
/// 改变UI透明度, 先不对外开放功能
/// </summary>
/// <param name="_tf"></param>
/// <param name="_alpha"></param>
private void ChangeAlpha(Transform _tf, float _alpha)
{
// 是否有必要改成canvasGroup
Image[] imageAry = _tf.GetComponentsInChildren<Image>();
for (int i = 0; i < imageAry.Length; i++)
{
Color old = imageAry[i].color;
imageAry[i].color = new Color(old.r, old.g, old.b, _alpha);
}
Text[] textAry = _tf.GetComponentsInChildren<Text>();
for (int i = 0; i < textAry.Length; i++)
{
Color old = textAry[i].color;
textAry[i].color = new Color(old.r, old.g, old.b, _alpha);
}
}
}