Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / common / NodeExtend.cs
  1. using System;
  2. using System.Collections;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// 该类为 node 节点通用扩展函数类
  7. /// </summary>
  8. public static class NodeExtend
  9. {
  10. /// <summary>
  11. /// 获取 IHurt 绑定的 ActivityObject, 没有则返回 null
  12. /// </summary>
  13. /// <param name="hurt"></param>
  14. /// <returns></returns>
  15. public static ActivityObject GetActivityObject(this IHurt hurt)
  16. {
  17. if (hurt is ActivityObject activityObject)
  18. {
  19. return activityObject;
  20. }
  21.  
  22. if (hurt is HurtArea hurtArea)
  23. {
  24. return hurtArea.ActivityObject;
  25. }
  26.  
  27. return null;
  28. }
  29.  
  30. /// <summary>
  31. /// 获取 IHurt 节点的坐标
  32. /// </summary>
  33. public static Vector2 GetPosition(this IHurt hurt)
  34. {
  35. if (hurt is ActivityObject role)
  36. {
  37. return role.GetCenterPosition();
  38. }
  39.  
  40. if (hurt is Node2D node2D)
  41. {
  42. return node2D.GlobalPosition;
  43. }
  44. return Vector2.Zero;
  45. }
  46. /// <summary>
  47. /// 将节点插入的房间物体根节点
  48. /// </summary>
  49. /// <param name="node">实例</param>
  50. /// <param name="layer">放入的层</param>
  51. public static void AddToActivityRoot(this Node2D node, RoomLayerEnum layer)
  52. {
  53. GameApplication.Instance.World.GetRoomLayer(layer).AddChild(node);
  54. }
  55. /// <summary>
  56. /// 将节点插入的房间物体根节点,延时调用
  57. /// </summary>
  58. /// <param name="node">实例</param>
  59. /// <param name="layer">放入的层</param>
  60. public static void AddToActivityRootDeferred(this Node2D node, RoomLayerEnum layer)
  61. {
  62. GameApplication.Instance.World.GetRoomLayer(layer).CallDeferred(Node.MethodName.AddChild, node);
  63. }
  64.  
  65. /// <summary>
  66. /// 设置Ui布局方式是否横向扩展, 如果为 true, 则 GridContainer 的宽度会撑满父物体
  67. /// </summary>
  68. public static void SetHorizontalExpand(this Control control, bool flag)
  69. {
  70. if (flag)
  71. {
  72. control.SizeFlagsHorizontal |= Control.SizeFlags.Expand;
  73. }
  74. else if ((control.SizeFlagsHorizontal & Control.SizeFlags.Expand) != 0)
  75. {
  76. control.SizeFlagsHorizontal ^= Control.SizeFlags.Expand;
  77. }
  78. }
  79.  
  80. /// <summary>
  81. /// 获取Ui布局方式是否横向扩展
  82. /// </summary>
  83. public static bool GetHorizontalExpand(this Control control)
  84. {
  85. return (control.SizeFlagsHorizontal & Control.SizeFlags.Expand) != 0;
  86. }
  87. /// <summary>
  88. /// 返回鼠标是否在Ui矩形内
  89. /// </summary>
  90. public static bool IsMouseInRect(this Control control, float border = 0)
  91. {
  92. var pos = control.GetLocalMousePosition();
  93. if (pos.X < border || pos.Y < border)
  94. {
  95. return false;
  96. }
  97.  
  98. var size = control.Size;
  99. return pos.X <= size.X - border && pos.Y <= size.Y - border;
  100. }
  101.  
  102. /// <summary>
  103. /// 设置是否启用节点
  104. /// </summary>
  105. public static void SetActive(this Node node, bool value)
  106. {
  107. if (node is CanvasItem canvasItem)
  108. {
  109. canvasItem.Visible = value;
  110. }
  111. node.SetProcess(value);
  112. node.SetPhysicsProcess(value);
  113. node.SetProcessInput(value);
  114. node.SetPhysicsProcessInternal(value);
  115. node.SetProcessInput(value);
  116. }
  117. /// <summary>
  118. /// 延时指定时间调用一个回调函数
  119. /// </summary>
  120. public static void CallDelay(this ICoroutine coroutine, float delayTime, Action cb)
  121. {
  122. coroutine.StartCoroutine(_CallDelay(delayTime, cb));
  123. }
  124. /// <summary>
  125. /// 延时指定时间调用一个回调函数
  126. /// </summary>
  127. public static void CallDelay<T1>(this ICoroutine coroutine, float delayTime, Action<T1> cb, T1 arg1)
  128. {
  129. coroutine.StartCoroutine(_CallDelay(delayTime, cb, arg1));
  130. }
  131. /// <summary>
  132. /// 延时指定时间调用一个回调函数
  133. /// </summary>
  134. public static void CallDelay<T1, T2>(this ICoroutine coroutine, float delayTime, Action<T1, T2> cb, T1 arg1, T2 arg2)
  135. {
  136. coroutine.StartCoroutine(_CallDelay(delayTime, cb, arg1, arg2));
  137. }
  138. /// <summary>
  139. /// 延时指定时间调用一个回调函数
  140. /// </summary>
  141. public static void CallDelay<T1, T2, T3>(this ICoroutine coroutine, float delayTime, Action<T1, T2, T3> cb, T1 arg1, T2 arg2, T3 arg3)
  142. {
  143. coroutine.StartCoroutine(_CallDelay(delayTime, cb, arg1, arg2, arg3));
  144. }
  145. //---------------------------
  146. /// <summary>
  147. /// 延时指定时间调用一个回调函数
  148. /// </summary>
  149. public static void CallDelayInNode(this Node node, float delayTime, Action cb)
  150. {
  151. GameApplication.Instance.StartCoroutine(_CallDelay(delayTime, cb));
  152. }
  153. /// <summary>
  154. /// 延时指定时间调用一个回调函数
  155. /// </summary>
  156. public static void CallDelayInNode<T1>(this Node node, float delayTime, Action<T1> cb, T1 arg1)
  157. {
  158. GameApplication.Instance.StartCoroutine(_CallDelay(delayTime, cb, arg1));
  159. }
  160. /// <summary>
  161. /// 延时指定时间调用一个回调函数
  162. /// </summary>
  163. public static void CallDelayInNode<T1, T2>(this Node node, float delayTime, Action<T1, T2> cb, T1 arg1, T2 arg2)
  164. {
  165. GameApplication.Instance.StartCoroutine(_CallDelay(delayTime, cb, arg1, arg2));
  166. }
  167. /// <summary>
  168. /// 延时指定时间调用一个回调函数
  169. /// </summary>
  170. public static void CallDelayInNode<T1, T2, T3>(this Node node, float delayTime, Action<T1, T2, T3> cb, T1 arg1, T2 arg2, T3 arg3)
  171. {
  172. GameApplication.Instance.StartCoroutine(_CallDelay(delayTime, cb, arg1, arg2, arg3));
  173. }
  174. private static IEnumerator _CallDelay(float delayTime, Action cb)
  175. {
  176. yield return new WaitForSeconds(delayTime);
  177. cb();
  178. }
  179. private static IEnumerator _CallDelay<T1>(float delayTime, Action<T1> cb, T1 arg1)
  180. {
  181. yield return new WaitForSeconds(delayTime);
  182. cb(arg1);
  183. }
  184. private static IEnumerator _CallDelay<T1, T2>(float delayTime, Action<T1, T2> cb, T1 arg1, T2 arg2)
  185. {
  186. yield return new WaitForSeconds(delayTime);
  187. cb(arg1, arg2);
  188. }
  189. private static IEnumerator _CallDelay<T1, T2, T3>(float delayTime, Action<T1, T2, T3> cb, T1 arg1, T2 arg2, T3 arg3)
  190. {
  191. yield return new WaitForSeconds(delayTime);
  192. cb(arg1,arg2, arg3);
  193. }
  194.  
  195. /// <summary>
  196. /// 给Ui节点添加拖拽事件
  197. /// </summary>
  198. /// <param name="control">需要绑定事件的节点对象</param>
  199. /// <param name="callback">拖拽回调函数</param>
  200. public static UiEventBinder AddDragListener(this Control control, Action<DragState, Vector2> callback)
  201. {
  202. return AddDragListener(control, DragButtonEnum.Left, callback);
  203. }
  204.  
  205. /// <summary>
  206. /// 给Ui节点添加拖拽事件
  207. /// </summary>
  208. /// <param name="control">需要绑定拖拽的节点对象</param>
  209. /// <param name="triggerButton">可触发拖拽的按钮</param>
  210. /// <param name="callback">拖拽回调函数</param>
  211. public static UiEventBinder AddDragListener(this Control control, DragButtonEnum triggerButton, Action<DragState, Vector2> callback)
  212. {
  213. var dragFlag = false;
  214. Control.GuiInputEventHandler handler = (ev) =>
  215. {
  216. if (!dragFlag) //未开始拖拽
  217. {
  218. if (ev is InputEventMouseButton mouseButton && mouseButton.Pressed &&
  219. CheckDragButton(mouseButton.ButtonIndex, triggerButton)) //按下按钮
  220. {
  221. control.AcceptEvent();
  222. dragFlag = true;
  223. callback(DragState.DragStart, Vector2.Zero);
  224. }
  225. }
  226. else //拖拽中
  227. {
  228. if (ev is InputEventMouseButton mouseButton)
  229. {
  230. if (!mouseButton.Pressed && CheckDragButton(mouseButton.ButtonIndex, triggerButton)) //松开按钮
  231. {
  232. control.AcceptEvent();
  233. dragFlag = false;
  234. callback(DragState.DragEnd, Vector2.Zero);
  235. }
  236. } else if (ev is InputEventMouseMotion mouseMotion) //拖拽中
  237. {
  238. control.AcceptEvent();
  239. var delta = mouseMotion.Relative;
  240. if (delta != Vector2.Zero)
  241. {
  242. callback(DragState.DragMove, mouseMotion.Relative);
  243. }
  244. }
  245. }
  246. };
  247. control.GuiInput += handler;
  248. return new UiEventBinder(control, handler);
  249. }
  250.  
  251. private static bool CheckDragButton(MouseButton button, DragButtonEnum triggerButton)
  252. {
  253. DragButtonEnum buttonEnum;
  254. switch (button)
  255. {
  256. case MouseButton.Left:
  257. buttonEnum = DragButtonEnum.Left;
  258. break;
  259. case MouseButton.Right:
  260. buttonEnum = DragButtonEnum.Right;
  261. break;
  262. case MouseButton.Middle:
  263. buttonEnum = DragButtonEnum.Middle;
  264. break;
  265. default: return false;
  266. }
  267.  
  268. return (buttonEnum & triggerButton) != 0;
  269. }
  270.  
  271. /// <summary>
  272. /// 给Ui节点添加鼠标滚轮事件
  273. /// </summary>
  274. /// <param name="control">需要绑定事件的节点对象</param>
  275. /// <param name="callback">滚轮回调, 参数 -1 表示滚轮向下滚动, 1 表示滚轮向上滚动</param>
  276. public static UiEventBinder AddMouseWheelListener(this Control control, Action<int> callback)
  277. {
  278. Control.GuiInputEventHandler handler = (ev) =>
  279. {
  280. if (ev is InputEventMouseButton mouseButton)
  281. {
  282. if (mouseButton.ButtonIndex == MouseButton.WheelDown)
  283. {
  284. control.AcceptEvent();
  285. callback(-1);
  286. }
  287. else if (mouseButton.ButtonIndex == MouseButton.WheelUp)
  288. {
  289. control.AcceptEvent();
  290. callback(1);
  291. }
  292. }
  293. };
  294. control.GuiInput += handler;
  295. return new UiEventBinder(control, handler);
  296. }
  297. }