feat(godot): 扩展Node功能并优化项目配置

- 新增多个Node扩展方法,包括输入处理、节点查找、子节点遍历等功能
- 添加异步添加子节点支持
- 实现节点路径打印和树形结构输出功能
- 增加安全延迟调用机制
- 移除废弃的ControlExtensions.cs文件引用
- 修复命名空间声明问题
- 添加必要的using引用以支持新功能实现
This commit is contained in:
GwWuYou 2025-12-11 19:13:30 +08:00
parent d8fd3745c5
commit 6da64eaf01
2 changed files with 170 additions and 2 deletions

View File

@ -16,4 +16,8 @@
<ProjectReference Include="..\GFramework.Core\GFramework.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Remove="extensions\ControlExtensions.cs" />
</ItemGroup>
</Project>

View File

@ -1,5 +1,8 @@
using Godot;
namespace GFramework.Core.Godot.godot.extensions;
using System;
using System.Threading.Tasks;
using Godot;
namespace GFramework.Core.Godot.extensions;
/// <summary>
/// 节点扩展方法类提供对Godot节点的扩展功能
@ -101,4 +104,165 @@ public static class NodeExtensions
!GodotObject.IsInstanceValid(node) ||
!node.IsInsideTree();
}
/// <summary>
/// 将当前节点的输入事件标记为已处理,防止事件继续向父节点传播。
/// </summary>
/// <param name="node">要处理输入事件的节点实例</param>
public static void SetInputAsHandled(this Node node)
{
// 获取节点的视口并标记输入事件为已处理
node.GetViewport().SetInputAsHandled();
}
/// <summary>
/// 设置节点所在场景树的暂停状态
/// </summary>
/// <param name="node">要操作的节点对象</param>
/// <param name="paused">暂停状态标识默认为true表示暂停false表示恢复运行</param>
public static void Paused(this Node node, bool paused = true)
{
var tree = node.GetTree();
tree.Paused = paused;
}
/// <summary>
/// 查找指定名称的子节点并将其转换为指定类型
/// </summary>
/// <typeparam name="T">要转换到的目标节点类型</typeparam>
/// <param name="node">要在其子节点中进行查找的父节点</param>
/// <param name="name">要查找的子节点名称</param>
/// <param name="recursive">是否递归查找所有层级的子节点默认为true</param>
/// <returns>找到的子节点转换为指定类型后的结果如果未找到或转换失败则返回null</returns>
public static T? FindChildX<T>(this Node node, string name, bool recursive = true)
where T : Node
{
var child = node.FindChild(name, recursive, owned: false);
return child as T;
}
/// <summary>
/// 获取指定路径的节点,如果不存在则创建一个新的节点
/// </summary>
/// <typeparam name="T">节点类型必须继承自Node且具有无参构造函数</typeparam>
/// <param name="node">父节点</param>
/// <param name="path">节点路径</param>
/// <returns>找到的现有节点或新创建的节点</returns>
public static T GetOrCreateNode<T>(this Node node, string path)
where T : Node, new()
{
// 尝试获取现有节点
if (node.GetNodeOrNull<T>(path) is { } found)
return found;
// 创建新节点并添加到父节点
var created = new T();
node.AddChild(created);
created.Name = path;
return created;
}
/// <summary>
/// 异步添加子节点并等待其准备就绪
/// </summary>
/// <param name="parent">父节点</param>
/// <param name="child">要添加的子节点</param>
/// <returns>异步任务</returns>
public static async Task AddChildX(this Node parent, Node child)
{
parent.AddChild(child);
await child.WaitUntilReady();
}
/// <summary>
/// 获取父节点并将其转换为指定类型
/// </summary>
/// <typeparam name="T">要转换到的目标节点类型</typeparam>
/// <param name="node">当前节点</param>
/// <returns>父节点转换为指定类型后的结果如果转换失败则返回null</returns>
public static T? GetParentX<T>(this Node node) where T : Node
{
return node.GetParent() as T;
}
/// <summary>
/// 获取场景树的根节点的第一个子节点
/// </summary>
/// <param name="node">扩展方法的目标节点</param>
/// <returns>根节点的第一个子节点</returns>
public static Node GetRootNodeX(this Node node)
{
return node.GetTree().Root.GetChild(0);
}
/// <summary>
/// 遍历节点的所有子节点,并对指定类型的子节点执行特定操作
/// </summary>
/// <typeparam name="T">要筛选的节点类型</typeparam>
/// <param name="node">扩展方法的目标节点</param>
/// <param name="action">对符合条件的子节点执行的操作</param>
public static void ForEachChild<T>(this Node node, Action<T> action) where T : Node
{
foreach (var child in node.GetChildren())
if (child is T t)
action(t);
}
/// <summary>
/// 禁用节点所在场景树的输入处理功能
/// </summary>
/// <param name="node">扩展方法的目标节点</param>
public static void DisableInput(this Node node)
{
// 检查根节点是否为Viewport类型如果是则禁用GUI输入
if (node.GetTree().Root is Viewport vp)
vp.GuiDisableInput = true;
}
/// <summary>
/// 启用节点所在场景树的输入处理功能
/// </summary>
/// <param name="node">扩展方法的目标节点</param>
public static void EnableInput(this Node node)
{
// 检查根节点是否为Viewport类型如果是则启用GUI输入
if (node.GetTree().Root is Viewport vp)
vp.GuiDisableInput = false;
}
/// <summary>
/// 打印节点的路径信息到控制台
/// </summary>
/// <param name="node">扩展方法的目标节点</param>
public static void LogNodePath(this Node node)
{
GD.Print($"[NodePath] {node.GetPath()}");
}
/// <summary>
/// 以树形结构递归打印节点及其所有子节点的名称
/// </summary>
/// <param name="node">扩展方法的目标节点</param>
/// <param name="indent">缩进字符串,用于显示层级关系</param>
public static void PrintTreeX(this Node node, string indent = "")
{
GD.Print($"{indent}- {node.Name}");
// 递归打印所有子节点
foreach (var child in node.GetChildren())
child.PrintTreeX(indent + " ");
}
/// <summary>
/// 安全地延迟调用指定方法,确保节点有效后再执行
/// </summary>
/// <param name="node">扩展方法的目标节点</param>
/// <param name="method">要延迟调用的方法名</param>
public static void SafeCallDeferred(this Node? node, string method)
{
// 检查节点是否为空且实例是否有效,有效时才执行延迟调用
if (node != null && GodotObject.IsInstanceValid(node))
node.CallDeferred(method);
}
}