Unity 框架

UIManager.cs 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Reflection;
  5. using UnityEngine;
  6. namespace TFramework
  7. {
  8. [DefaultExecutionOrder(-9999)]
  9. public class UIManager : BaseManager
  10. {
  11. private Stack<BasePanel> panelStack;
  12. private Dictionary<string, BasePanel> panelDict;
  13. private List<BasePanel> panelBuffer;
  14. private Dictionary<string, Transform> _worldUIDomain;
  15. private TAction<BasePanel, BasePanel> OnPanelChanged;
  16. private BasePanel _currentPanel;
  17. /// <summary>
  18. /// 当前打开的面板
  19. /// </summary>
  20. public BasePanel CurrentPanel
  21. {
  22. get => _currentPanel;
  23. private set
  24. {
  25. OnPanelChanged?.Invoke(_currentPanel, value);
  26. _currentPanel = value;
  27. }
  28. }
  29. public const string DEFAULTDOMAIN = "默认UI域";
  30. public void Awake()
  31. {
  32. panelStack = new Stack<BasePanel>();
  33. panelDict = new Dictionary<string, BasePanel>();
  34. panelBuffer = new List<BasePanel>();
  35. _worldUIDomain = new Dictionary<string, Transform>();
  36. }
  37. /// <summary>
  38. /// 注册UI作用域 (即父物体)
  39. /// </summary>
  40. /// <param name="name">名字</param>
  41. /// <param name="domain">作用域</param>
  42. public void RegisterUIDomain(string name, Transform domain)
  43. {
  44. if (_worldUIDomain.ContainsKey(name))
  45. Log.Error($"UI作用域名称【{name}】被重复注册");
  46. else
  47. _worldUIDomain.Add(name, domain);
  48. }
  49. public void UnregisterUIDomain(string name)
  50. {
  51. if (_worldUIDomain.ContainsKey(name))
  52. _worldUIDomain.Remove(name);
  53. else
  54. Log.Error($"不存在名为【{name}】的UI作用域");
  55. }
  56. /// <summary>
  57. /// 打开UI
  58. /// </summary>
  59. /// <typeparam name="T"></typeparam>
  60. public T OpenUI<T>(IPanelData args = null) where T : BasePanel => OpenUI(typeof(T), args) as T;
  61. public BasePanel OpenUI(Type type, IPanelData args = null)
  62. {
  63. if (panelStack.Count > 0)
  64. panelStack.Peek().OnPause(args);
  65. BasePanel panel = GetPanel(type);
  66. if (panel == null) return null;
  67. panel.UIEntity.SetActive(true);
  68. CurrentPanel = panel;
  69. panel.UIEntity.transform.SetAsLastSibling();
  70. panelStack.Push(panel);
  71. panel.OnEnter(args);
  72. StickyTopic();
  73. return panel;
  74. }
  75. /// <summary>
  76. /// 预加载UI 加载完成不打开
  77. /// </summary>
  78. /// <typeparam name="T"></typeparam>
  79. public void PreopenUI<T>() => PreopenUI(typeof(T));
  80. /// <summary>
  81. /// 预加载UI 加载完成不打开
  82. /// </summary>
  83. /// <typeparam name="Type"></typeparam>
  84. public void PreopenUI(Type type)
  85. {
  86. BasePanel panel = GetPanel(type);
  87. if (panel != null)
  88. panel.UIEntity.SetActive(false);
  89. }
  90. /// <summary>
  91. /// 置顶UI
  92. /// </summary>
  93. private void StickyTopic()
  94. {
  95. foreach (var item in panelDict.Values)
  96. if (item.UIEntity!=null && item.UIEntity.activeSelf && item.StickyTopic)
  97. item.UIEntity.transform.SetAsLastSibling();
  98. }
  99. /// <summary>
  100. /// 关闭UI
  101. /// </summary>
  102. public void CloseUI(IPanelData args=null)
  103. {
  104. if (panelStack.Count <= 0) return;
  105. BasePanel toPanel = panelStack.Pop();
  106. if (toPanel.UIEntity == null) return;
  107. toPanel.UIEntity.SetActive(false);
  108. toPanel.OnExit(args);
  109. if (panelStack.Count <= 0) return;
  110. CurrentPanel = panelStack.Peek();
  111. CurrentPanel.OnResume(args);
  112. }
  113. /// <summary>
  114. /// 关闭UI
  115. /// </summary>
  116. /// <param name="type">UI类型</param>
  117. /// <param name="isDestroy">是否销毁</param>
  118. /// <param name="args">参数</param>
  119. public void CloseUI<T>(bool isDestroy = false, IPanelData args=null) => CloseUI(typeof(T), isDestroy, args);
  120. /// <summary>
  121. /// 关闭UI
  122. /// </summary>
  123. /// <param name="type">UI类型</param>
  124. /// <param name="isDestroy">是否销毁</param>
  125. /// <param name="args">参数</param>
  126. public void CloseUI(Type type, bool isDestroy = false, IPanelData args=null)
  127. {
  128. BasePanel panel = GetAlreadyHavePanel(type.FullName);
  129. if (panel == null) return;
  130. if (panelStack.Peek() == panel)
  131. CloseUI(args);
  132. else
  133. {
  134. panelBuffer.Clear();
  135. if (panel.UIEntity.activeSelf)
  136. {
  137. while (panelStack.Peek() != panel)
  138. panelBuffer.Add(panelStack.Pop());
  139. BasePanel toPanel = panelStack.Pop();
  140. if(toPanel.UIEntity!=null)
  141. {
  142. toPanel.UIEntity.SetActive(false);
  143. toPanel.OnExit(args);
  144. }
  145. for (int i = panelBuffer.Count - 1; i >= 0; i--)
  146. panelStack.Push(panelBuffer[i]);
  147. }
  148. }
  149. if (isDestroy)
  150. {
  151. GameObject.DestroyImmediate(panel.UIEntity);
  152. panelDict.Remove(type.FullName);
  153. }
  154. }
  155. /// <summary>
  156. /// 获取面板
  157. /// </summary>
  158. /// <param name="type"></param>
  159. /// <returns></returns>
  160. private BasePanel GetPanel(Type type)
  161. {
  162. UIResourceAttribute attribute = type.GetCustomAttribute<UIResourceAttribute>();
  163. BasePanel panel = panelDict.TryGet(type.FullName);
  164. if (panel == null)
  165. {
  166. panel = Activator.CreateInstance(type) as BasePanel;
  167. GameObject game = Main.GetMagr<ResourceManager>().LoadAsset(new LoadResHandle<GameObject>(attribute));
  168. if(game==null)
  169. {
  170. Log.Error($"未加载到【{type}】UI实体,请检查实体路径是否正确!");
  171. return panel;
  172. }
  173. panel.UIEntity = Instantiate(game);
  174. if (!string.IsNullOrEmpty(attribute.WorlUIDomain))
  175. {
  176. if (!_worldUIDomain.ContainsKey(attribute.WorlUIDomain))
  177. Log.Error($"UI【{game.name}】执行文件【{type.Name}】的作用域未注册,请确定其作用域对象挂载了【WorldUIDomain】脚本!");
  178. else
  179. panel.UIEntity.transform.SetParent(_worldUIDomain[attribute.WorlUIDomain], false);
  180. }
  181. panel.OnInit();
  182. panel.ChangedWord();
  183. panelDict.Add(type.FullName, panel);
  184. }
  185. return panel;
  186. }
  187. /// <summary>
  188. /// 获取已创建的面板
  189. /// </summary>
  190. /// <returns></returns>
  191. public T GetAlreadyHavePanel<T>() where T : BasePanel => panelDict.TryGet(typeof(T).FullName) as T;
  192. /// <summary>
  193. /// 获取已创建的面板
  194. /// </summary>
  195. /// <returns></returns>
  196. public BasePanel GetAlreadyHavePanel(string typeFullName) => panelDict.TryGet(typeFullName);
  197. /// <summary>
  198. /// 关闭指定UIPanel
  199. /// </summary>
  200. /// <typeparam name="T"></typeparam>
  201. public void CloseUI<T>(IPanelData args) where T : BasePanel => CloseUI<T>(false, args);
  202. public void AddPanelChanged(TAction<BasePanel, BasePanel> action) => OnPanelChanged += action;
  203. public void RemovePanelChanged(TAction<BasePanel, BasePanel> action) => OnPanelChanged -= action;
  204. /// <summary>
  205. /// 切换语言
  206. /// </summary>
  207. internal void ChangedWord()
  208. {
  209. foreach (var item in panelDict.Values)
  210. {
  211. item.ChangedWord();
  212. }
  213. }
  214. }
  215. }