AkiraPixelWind/Assets/Scripts/Main/UI/UIMgr/UIMgr.cs

626 lines
17 KiB
C#
Raw Permalink Normal View History

2022-12-29 18:20:40 +08:00
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);
}
}
}