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