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