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;
}
}
}