Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / ui / UiBase.cs
@小李xl 小李xl on 6 Aug 2023 6 KB 更新Ui生成器
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// Ui 基类
  7. /// </summary>
  8. public abstract partial class UiBase : Control, IDestroy, ICoroutine
  9. {
  10. /// <summary>
  11. /// 当前 UI 所属层级
  12. /// </summary>
  13. [Export]
  14. public UiLayer Layer = UiLayer.Middle;
  15.  
  16. /// <summary>
  17. /// ui名称
  18. /// </summary>
  19. public string UiName { get; }
  20. /// <summary>
  21. /// 是否已经打开ui
  22. /// </summary>
  23. public bool IsOpen { get; private set; } = false;
  24.  
  25. public bool IsDestroyed { get; private set; }
  26.  
  27. /// <summary>
  28. /// 负责记录上一个Ui
  29. /// </summary>
  30. public UiBase PrevUi { get; set; }
  31.  
  32. /// <summary>
  33. /// 所属父级Ui, 仅当通过 UiNode.OpenNestedUi() 打开时才会赋值<br/>
  34. /// 注意: 如果是在预制体中放置的子 Ui, 那么子 Ui 的该属性会在 父 Ui 的 OnCreateUi() 之后赋值
  35. /// </summary>
  36. public UiBase ParentUi { get; private set; }
  37.  
  38. //开启的协程
  39. private List<CoroutineData> _coroutineList;
  40. //嵌套打开的Ui列表
  41. private HashSet<UiBase> _nestedUiSet;
  42.  
  43. public UiBase(string uiName)
  44. {
  45. UiName = uiName;
  46. //记录ui打开
  47. UiManager.RecordUi(this, UiManager.RecordType.Open);
  48. }
  49.  
  50. /// <summary>
  51. /// 创建当前ui时调用
  52. /// </summary>
  53. public virtual void OnCreateUi()
  54. {
  55. }
  56. /// <summary>
  57. /// 用于初始化打开的子Ui, 在 OnCreateUi() 之后调用
  58. /// </summary>
  59. public virtual void OnInitNestedUi()
  60. {
  61. }
  62.  
  63. /// <summary>
  64. /// 当前ui显示时调用
  65. /// </summary>
  66. public virtual void OnShowUi()
  67. {
  68. }
  69.  
  70. /// <summary>
  71. /// 当前ui隐藏时调用
  72. /// </summary>
  73. public virtual void OnHideUi()
  74. {
  75. }
  76.  
  77. /// <summary>
  78. /// 销毁当前ui时调用
  79. /// </summary>
  80. public virtual void OnDestroyUi()
  81. {
  82. }
  83.  
  84. /// <summary>
  85. /// 每帧调用一次
  86. /// </summary>
  87. public virtual void Process(float delta)
  88. {
  89. }
  90.  
  91. /// <summary>
  92. /// 显示ui
  93. /// </summary>
  94. public void ShowUi()
  95. {
  96. if (IsOpen)
  97. {
  98. return;
  99. }
  100.  
  101. IsOpen = true;
  102. Visible = true;
  103. OnShowUi();
  104. //子Ui调用显示
  105. if (_nestedUiSet != null)
  106. {
  107. foreach (var uiBase in _nestedUiSet)
  108. {
  109. uiBase.ShowUi();
  110. }
  111. }
  112. }
  113. /// <summary>
  114. /// 隐藏ui, 不会执行销毁
  115. /// </summary>
  116. public void HideUi()
  117. {
  118. if (!IsOpen)
  119. {
  120. return;
  121. }
  122.  
  123. IsOpen = false;
  124. Visible = false;
  125. OnHideUi();
  126. //子Ui调用隐藏
  127. if (_nestedUiSet != null)
  128. {
  129. foreach (var uiBase in _nestedUiSet)
  130. {
  131. uiBase.HideUi();
  132. }
  133. }
  134. }
  135.  
  136. /// <summary>
  137. /// 关闭并销毁ui
  138. /// </summary>
  139. public void Destroy()
  140. {
  141. if (IsDestroyed)
  142. {
  143. return;
  144. }
  145. //记录ui关闭
  146. UiManager.RecordUi(this, UiManager.RecordType.Close);
  147. HideUi();
  148. IsDestroyed = true;
  149. OnDestroyUi();
  150. //子Ui调用销毁
  151. if (_nestedUiSet != null)
  152. {
  153. foreach (var uiBase in _nestedUiSet)
  154. {
  155. uiBase.ParentUi = null;
  156. uiBase.Destroy();
  157. }
  158. _nestedUiSet.Clear();
  159. }
  160.  
  161. //在父Ui中移除当前Ui
  162. if (ParentUi != null)
  163. {
  164. ParentUi.RecordNestedUi(this, UiManager.RecordType.Close);
  165. }
  166. QueueFree();
  167. }
  168.  
  169. public sealed override void _Process(double delta)
  170. {
  171. if (!IsOpen)
  172. {
  173. return;
  174. }
  175. var newDelta = (float)delta;
  176. Process(newDelta);
  177. //协程更新
  178. if (_coroutineList != null)
  179. {
  180. ProxyCoroutineHandler.ProxyUpdateCoroutine(ref _coroutineList, newDelta);
  181. }
  182. }
  183.  
  184. /// <summary>
  185. /// 记录嵌套打开/关闭的UI
  186. /// </summary>
  187. public void RecordNestedUi(UiBase uiBase, UiManager.RecordType type)
  188. {
  189. if (type == UiManager.RecordType.Open)
  190. {
  191. if (uiBase.ParentUi != null && uiBase.ParentUi != this)
  192. {
  193. GD.PrintErr($"子Ui:'{uiBase.UiName}'已经被其他Ui:'{uiBase.ParentUi.UiName}'嵌套打开!");
  194. uiBase.ParentUi.RecordNestedUi(uiBase, UiManager.RecordType.Close);
  195. }
  196. if (_nestedUiSet == null)
  197. {
  198. _nestedUiSet = new HashSet<UiBase>();
  199. }
  200.  
  201. uiBase.ParentUi = this;
  202. _nestedUiSet.Add(uiBase);
  203. }
  204. else
  205. {
  206. if (uiBase.ParentUi == this)
  207. {
  208. uiBase.ParentUi = null;
  209. }
  210. else
  211. {
  212. GD.PrintErr($"当前Ui:'{UiName}'没有嵌套打开子Ui:'{uiBase.UiName}'!");
  213. return;
  214. }
  215. if (_nestedUiSet == null)
  216. {
  217. return;
  218. }
  219. _nestedUiSet.Remove(uiBase);
  220. }
  221. }
  222.  
  223. /// <summary>
  224. /// 打开下一级Ui, 当前Ui会被隐藏
  225. /// </summary>
  226. /// <param name="uiName">下一级Ui的名称</param>
  227. public UiBase OpenNextUi(string uiName)
  228. {
  229. var uiBase = UiManager.OpenUi(uiName, this);
  230. HideUi();
  231. return uiBase;
  232. }
  233. /// <summary>
  234. /// 打开下一级Ui, 当前Ui会被隐藏
  235. /// </summary>
  236. /// <param name="uiName">下一级Ui的名称</param>
  237. public T OpenNextUi<T>(string uiName) where T : UiBase
  238. {
  239. return (T)OpenNextUi(uiName);
  240. }
  241.  
  242. /// <summary>
  243. /// 返回上一级Ui, 当前Ui会被销毁
  244. /// </summary>
  245. public void OpenPrevUi()
  246. {
  247. Destroy();
  248. if (PrevUi == null)
  249. {
  250. GD.PrintErr($"Ui: {UiName} 没有记录上一级Ui!");
  251. }
  252. else
  253. {
  254. PrevUi.ShowUi();
  255. }
  256. }
  257.  
  258. public long StartCoroutine(IEnumerator able)
  259. {
  260. return ProxyCoroutineHandler.ProxyStartCoroutine(ref _coroutineList, able);
  261. }
  262. public void StopCoroutine(long coroutineId)
  263. {
  264. ProxyCoroutineHandler.ProxyStopCoroutine(ref _coroutineList, coroutineId);
  265. }
  266. public void StopAllCoroutine()
  267. {
  268. ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList);
  269. }
  270. }