626 lines
17 KiB
C#
626 lines
17 KiB
C#
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);
|
||
}
|
||
}
|
||
} |