using System; using System.Collections.Generic; using Godot; using Godot.Collections; namespace TBL.GodotSharp { /// /// Godot 扩展工具类 /// public static class Extension { /// /// 使节点在世界变换下保持只有八方向旋转 /// public static void SetDir8(this Spatial node) { node.Rotation = new Vector3(node.Rotation.x, 0, node.Rotation.z); var angle = node.GlobalTransform.basis.GetEuler().y; var diff = Mathf.PosMod(angle, Mathf.Deg2Rad(45.0f)); node.RotateY(-diff); if (Mathf.Abs(diff) > Mathf.Deg2Rad(22.5f)) { node.RotateY(Mathf.Deg2Rad(45.0f) * Mathf.Sign(diff)); } } /// /// 使节点在世界变换下保持只有八方向旋转 /// public static void SetDir8(this Node node) { if (node is Spatial spatial) SetDir8(spatial); } /// /// 遍历所有子节点 /// public static IEnumerable EnumChildrenNodes(this Node node, bool recursive = true) where T : Node { for (int i = 0, count = node.GetChildCount(); i < count; i++) { var child = node.GetChild(i); if (child == null) continue; if (child is T target) yield return target; if (recursive) foreach (var next in EnumChildrenNodes(child, true)) yield return next; } } /// /// 获取所有此类型的子节点到列表中 /// 获取前不会清空 请留意 /// public static void GetAllNodesOfType(this Node root, Array result, bool recursive = true) where T : Node { foreach ( var node in EnumChildrenNodes(root, recursive) ) result.Add(node); } /// /// 设置铺满父节点 /// public static void SetFullParent(this Control canvasItem) { canvasItem.AnchorLeft = canvasItem.AnchorTop = 0; canvasItem.AnchorRight = canvasItem.AnchorBottom = 1; canvasItem.MarginLeft = canvasItem.MarginRight = canvasItem.MarginTop = canvasItem.MarginBottom = 0; } /// /// 设置铺满父节点 /// public static void SetCenterParent(this Control canvasItem, bool withMargin = false) { canvasItem.AnchorLeft = canvasItem.AnchorTop = canvasItem.AnchorRight = canvasItem.AnchorBottom = 0.5f; if (withMargin) { var size = canvasItem.GetParentControl().RectSize; canvasItem.MarginLeft = -size.x * 0.5f; canvasItem.MarginRight = size.x * 0.5f; canvasItem.MarginTop = -size.y * 0.5f; canvasItem.MarginBottom = size.y * 0.5f; } else canvasItem.MarginLeft = canvasItem.MarginRight = canvasItem.MarginTop = canvasItem.MarginBottom = 0; } /// /// 退出场景树并销毁 /// public static void QueueFreeAndExitTree(this Node node) { try { node.GetParent()?.RemoveChild(node); node.QueueFree(); } catch (ObjectDisposedException) { } } /// /// 获取完整路径 /// public static string GetFullPath(this string name, string dir, string ext) => $"{dir}/{name}{ext}"; /// /// 削除所有动画 /// public static void RemoveAllAnimations(this AnimationPlayer animationPlayer) { foreach (var name in animationPlayer.GetAnimationList()) { animationPlayer.RemoveAnimation(name); } } /// /// 将本地节点变为 /// 多用作快捷预制体 /// public static PackedScene MakePrefab(this Godot.Node node, bool deferredFree = true) { var prefab = new PackedScene(); prefab.Pack(node); if (deferredFree) node.QueueFreeAndExitTree(); else node.Free(); return prefab; } } }