Extension.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using System;
  2. using System.Collections.Generic;
  3. using Godot;
  4. using Godot.Collections;
  5. namespace TBL.GodotSharp
  6. {
  7. /// <summary>
  8. /// Godot 扩展工具类
  9. /// </summary>
  10. public static class Extension
  11. {
  12. /// <summary>
  13. /// 使节点在世界变换下保持只有八方向旋转
  14. /// </summary>
  15. public static void SetDir8(this Spatial node)
  16. {
  17. node.Rotation = new Vector3(node.Rotation.x, 0, node.Rotation.z);
  18. var angle = node.GlobalTransform.basis.GetEuler().y;
  19. var diff = Mathf.PosMod(angle, Mathf.Deg2Rad(45.0f));
  20. node.RotateY(-diff);
  21. if (Mathf.Abs(diff) > Mathf.Deg2Rad(22.5f))
  22. {
  23. node.RotateY(Mathf.Deg2Rad(45.0f) * Mathf.Sign(diff));
  24. }
  25. }
  26. /// <summary>
  27. /// 使节点在世界变换下保持只有八方向旋转
  28. /// </summary>
  29. public static void SetDir8(this Node node)
  30. {
  31. if (node is Spatial spatial)
  32. SetDir8(spatial);
  33. }
  34. /// <summary>
  35. /// 遍历所有子节点
  36. /// </summary>
  37. public static IEnumerable<T> EnumChildrenNodes<T>(this Node node, bool recursive = true)
  38. where T : Node
  39. {
  40. for (int i = 0, count = node.GetChildCount(); i < count; i++)
  41. {
  42. var child = node.GetChild(i);
  43. if (child == null)
  44. continue;
  45. if (child is T target)
  46. yield return target;
  47. if (recursive)
  48. foreach (var next in EnumChildrenNodes<T>(child, true))
  49. yield return next;
  50. }
  51. }
  52. /// <summary>
  53. /// 获取所有此类型的子节点到列表中
  54. /// <para>获取前不会清空 <see cref="result"/> 请留意</para>
  55. /// </summary>
  56. public static void GetAllNodesOfType<T>(this Node root, Array<T> result, bool recursive = true)
  57. where T : Node
  58. {
  59. foreach ( var node in EnumChildrenNodes<T>(root, recursive) )
  60. result.Add(node);
  61. }
  62. /// <summary>
  63. /// 设置铺满父节点
  64. /// </summary>
  65. public static void SetFullParent(this Control canvasItem)
  66. {
  67. canvasItem.AnchorLeft = canvasItem.AnchorTop = 0;
  68. canvasItem.AnchorRight = canvasItem.AnchorBottom = 1;
  69. canvasItem.MarginLeft = canvasItem.MarginRight = canvasItem.MarginTop = canvasItem.MarginBottom = 0;
  70. }
  71. /// <summary>
  72. /// 设置铺满父节点
  73. /// </summary>
  74. public static void SetCenterParent(this Control canvasItem, bool withMargin = false)
  75. {
  76. canvasItem.AnchorLeft = canvasItem.AnchorTop = canvasItem.AnchorRight = canvasItem.AnchorBottom = 0.5f;
  77. if (withMargin)
  78. {
  79. var size = canvasItem.GetParentControl().RectSize;
  80. canvasItem.MarginLeft = -size.x * 0.5f;
  81. canvasItem.MarginRight = size.x * 0.5f;
  82. canvasItem.MarginTop = -size.y * 0.5f;
  83. canvasItem.MarginBottom = size.y * 0.5f;
  84. }
  85. else
  86. canvasItem.MarginLeft = canvasItem.MarginRight = canvasItem.MarginTop = canvasItem.MarginBottom = 0;
  87. }
  88. /// <summary>
  89. /// 退出场景树并销毁
  90. /// </summary>
  91. public static void QueueFreeAndExitTree(this Node node)
  92. {
  93. try
  94. {
  95. node.GetParent()?.RemoveChild(node);
  96. node.QueueFree();
  97. }
  98. catch (ObjectDisposedException)
  99. {
  100. }
  101. }
  102. /// <summary>
  103. /// 获取完整路径
  104. /// </summary>
  105. public static string GetFullPath(this string name, string dir, string ext) => $"{dir}/{name}{ext}";
  106. /// <summary>
  107. /// 削除所有动画
  108. /// </summary>
  109. public static void RemoveAllAnimations(this AnimationPlayer animationPlayer)
  110. {
  111. foreach (var name in animationPlayer.GetAnimationList())
  112. {
  113. animationPlayer.RemoveAnimation(name);
  114. }
  115. }
  116. /// <summary>
  117. /// 将本地节点变为 <see cref="PackedScene"/>
  118. /// 多用作快捷预制体
  119. /// </summary>
  120. public static PackedScene MakePrefab(this Godot.Node node, bool deferredFree = true)
  121. {
  122. var prefab = new PackedScene();
  123. prefab.Pack(node);
  124. if (deferredFree)
  125. node.QueueFreeAndExitTree();
  126. else
  127. node.Free();
  128. return prefab;
  129. }
  130. }
  131. }