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