refactor(input): 重构Godot输入模块为抽象基类并优化输入处理流程

将 `GodotInputModule` 重命名为 `AbstractGodotInputModule` 并改为抽象类,
以便支持更灵活的输入翻译器注册机制。引入 `GodotInputPhase` 枚举和
`GodotRawInput` 结构体以区分输入处理的不同阶段(捕获与冒泡)。
同时修改 `GodotInputTranslator` 仅在Bubble阶段生成游戏事件,提升输入处理精度。
```
This commit is contained in:
GwWuYou 2025-12-21 16:52:36 +08:00
parent 4bd9853ec1
commit 028ece27db
5 changed files with 87 additions and 15 deletions

View File

@ -11,23 +11,31 @@ namespace GFramework.Godot.input;
/// Godot输入模块类用于管理Godot游戏引擎中的输入系统
/// </summary>
/// <typeparam name="T">架构类型必须继承自Architecture且具有无参构造函数</typeparam>
public sealed class GodotInputModule<T> : AbstractGodotModule<T>
public abstract class AbstractGodotInputModule<T> : AbstractGodotModule<T>
where T : Architecture<T>, new()
{
private GodotInputBridge? _node;
/// <summary>
/// 启用默认的输入转换器
/// </summary>
protected virtual bool EnableDefaultTranslator => false;
/// <summary>
/// 架构锚点节点的唯一标识名称
/// 用于在Godot场景树中创建和查找架构锚点节点
/// </summary>
private const string GodotInputBridgeName = $"__${GFrameworkConstants.FrameworkName}__GodotInputBridge__";
/// <summary>
/// 获取模块对应的节点对象
/// </summary>
/// <exception cref="InvalidOperationException">当节点尚未创建时抛出异常</exception>
public override Node Node => _node
public override Node Node => _node
?? throw new InvalidOperationException("Node not created yet");
private InputSystem _inputSystem = null!;
/// <summary>
/// 当模块被附加到架构时调用此方法
/// </summary>
@ -35,7 +43,7 @@ public sealed class GodotInputModule<T> : AbstractGodotModule<T>
public override void OnAttach(Architecture<T> architecture)
{
// 创建Godot输入桥接节点并绑定输入系统
_node = new GodotInputBridge { Name = GodotInputBridgeName};
_node = new GodotInputBridge { Name = GodotInputBridgeName };
_node.Bind(_inputSystem);
}
@ -57,7 +65,18 @@ public sealed class GodotInputModule<T> : AbstractGodotModule<T>
{
// 从架构中获取输入系统实例
_inputSystem = architecture.GetSystem<InputSystem>()!;
// 注册输入转换器
_inputSystem.RegisterTranslator(new GodotInputTranslator());
if (EnableDefaultTranslator)
{
// 注册输入转换器
_inputSystem.RegisterTranslator(new GodotInputTranslator(), true);
}
RegisterTranslator(_inputSystem);
}
}
/// <summary>
/// 注册翻译器的抽象方法,由子类实现具体的注册逻辑
/// </summary>
/// <param name="inputSystem">输入系统实例</param>
protected abstract void RegisterTranslator(InputSystem inputSystem);
}

View File

@ -20,11 +20,22 @@ public partial class GodotInputBridge : Node
}
/// <summary>
/// 处理输入事件的回调方法
/// 捕获阶段:最早
/// </summary>
/// <param name="event">Godot输入事件</param>
public override void _Input(InputEvent @event)
{
_inputSystem.HandleRaw(@event);
_inputSystem.HandleRaw(
new GodotRawInput(@event, GodotInputPhase.Capture)
);
}
/// <summary>
/// 冒泡阶段UI 未处理
/// </summary>
public override void _UnhandledInput(InputEvent @event)
{
_inputSystem.HandleRaw(
new GodotRawInput(@event, GodotInputPhase.Bubble)
);
}
}

View File

@ -0,0 +1,19 @@
namespace GFramework.Godot.input;
/// <summary>
/// 输入处理阶段枚举用于区分Godot引擎中不同的输入处理阶段
/// </summary>
public enum GodotInputPhase
{
/// <summary>
/// 捕获阶段在_Input方法中处理输入事件
/// 这是输入事件的第一个处理阶段,事件会沿着节点树向下传递
/// </summary>
Capture, // _Input
/// <summary>
/// 冒泡阶段在_UnhandledInput方法中处理输入事件
/// 这是输入事件的第二个处理阶段,未被处理的事件会向上冒泡传递
/// </summary>
Bubble // _UnhandledInput
}

View File

@ -18,12 +18,16 @@ public sealed class GodotInputTranslator : IInputTranslator
{
gameEvent = null!;
// 检查输入是否为Godot的InputEvent类型
if (rawInput is not InputEvent evt)
if (rawInput is not GodotRawInput raw)
return false;
var evt = raw.Event;
// 示例规则:只在 Bubble 阶段生成游戏输入
if (raw.Phase != GodotInputPhase.Bubble)
return false;
// Action
// 处理动作输入事件(如键盘按键、手柄按钮等)
if (evt is InputEventAction action)
{
gameEvent = new InputEvents.KeyInputEvent(
@ -35,7 +39,6 @@ public sealed class GodotInputTranslator : IInputTranslator
}
// Mouse button
// 处理鼠标按钮输入事件
if (evt is InputEventMouseButton mb)
{
gameEvent = new InputEvents.PointerInputEvent<Vector2>(
@ -48,7 +51,6 @@ public sealed class GodotInputTranslator : IInputTranslator
}
// Mouse motion
// 处理鼠标移动输入事件
if (evt is InputEventMouseMotion mm)
{
gameEvent = new InputEvents.PointerInputEvent<Vector2>(

View File

@ -0,0 +1,21 @@
using Godot;
namespace GFramework.Godot.input;
/// <summary>
/// 表示Godot原始输入数据的只读结构体
/// </summary>
/// <param name="evt">输入事件对象</param>
/// <param name="phase">输入阶段</param>
public readonly struct GodotRawInput(InputEvent evt, GodotInputPhase phase)
{
/// <summary>
/// 获取输入事件对象
/// </summary>
public readonly InputEvent Event = evt;
/// <summary>
/// 获取输入阶段
/// </summary>
public readonly GodotInputPhase Phase = phase;
}