diff --git a/GFramework.Godot/input/GodotInputModule.cs b/GFramework.Godot/input/AbstractGodotInputModule.cs similarity index 74% rename from GFramework.Godot/input/GodotInputModule.cs rename to GFramework.Godot/input/AbstractGodotInputModule.cs index b498c39..0946b0a 100644 --- a/GFramework.Godot/input/GodotInputModule.cs +++ b/GFramework.Godot/input/AbstractGodotInputModule.cs @@ -11,23 +11,31 @@ namespace GFramework.Godot.input; /// Godot输入模块类,用于管理Godot游戏引擎中的输入系统 /// /// 架构类型,必须继承自Architecture且具有无参构造函数 -public sealed class GodotInputModule : AbstractGodotModule +public abstract class AbstractGodotInputModule : AbstractGodotModule where T : Architecture, new() { private GodotInputBridge? _node; + + /// + /// 启用默认的输入转换器 + /// + protected virtual bool EnableDefaultTranslator => false; + /// /// 架构锚点节点的唯一标识名称 /// 用于在Godot场景树中创建和查找架构锚点节点 /// private const string GodotInputBridgeName = $"__${GFrameworkConstants.FrameworkName}__GodotInputBridge__"; + /// /// 获取模块对应的节点对象 /// /// 当节点尚未创建时抛出异常 - public override Node Node => _node + public override Node Node => _node ?? throw new InvalidOperationException("Node not created yet"); + private InputSystem _inputSystem = null!; - + /// /// 当模块被附加到架构时调用此方法 /// @@ -35,7 +43,7 @@ public sealed class GodotInputModule : AbstractGodotModule public override void OnAttach(Architecture architecture) { // 创建Godot输入桥接节点并绑定输入系统 - _node = new GodotInputBridge { Name = GodotInputBridgeName}; + _node = new GodotInputBridge { Name = GodotInputBridgeName }; _node.Bind(_inputSystem); } @@ -57,7 +65,18 @@ public sealed class GodotInputModule : AbstractGodotModule { // 从架构中获取输入系统实例 _inputSystem = architecture.GetSystem()!; - // 注册输入转换器 - _inputSystem.RegisterTranslator(new GodotInputTranslator()); + if (EnableDefaultTranslator) + { + // 注册输入转换器 + _inputSystem.RegisterTranslator(new GodotInputTranslator(), true); + } + + RegisterTranslator(_inputSystem); } -} + + /// + /// 注册翻译器的抽象方法,由子类实现具体的注册逻辑 + /// + /// 输入系统实例 + protected abstract void RegisterTranslator(InputSystem inputSystem); +} \ No newline at end of file diff --git a/GFramework.Godot/input/GodotInputBridge.cs b/GFramework.Godot/input/GodotInputBridge.cs index 27f3ebf..cfb6b71 100644 --- a/GFramework.Godot/input/GodotInputBridge.cs +++ b/GFramework.Godot/input/GodotInputBridge.cs @@ -20,11 +20,22 @@ public partial class GodotInputBridge : Node } /// - /// 处理输入事件的回调方法 + /// 捕获阶段:最早 /// - /// Godot输入事件 public override void _Input(InputEvent @event) { - _inputSystem.HandleRaw(@event); + _inputSystem.HandleRaw( + new GodotRawInput(@event, GodotInputPhase.Capture) + ); + } + + /// + /// 冒泡阶段:UI 未处理 + /// + public override void _UnhandledInput(InputEvent @event) + { + _inputSystem.HandleRaw( + new GodotRawInput(@event, GodotInputPhase.Bubble) + ); } } diff --git a/GFramework.Godot/input/GodotInputPhase.cs b/GFramework.Godot/input/GodotInputPhase.cs new file mode 100644 index 0000000..e250a8d --- /dev/null +++ b/GFramework.Godot/input/GodotInputPhase.cs @@ -0,0 +1,19 @@ +namespace GFramework.Godot.input; + +/// +/// 输入处理阶段枚举,用于区分Godot引擎中不同的输入处理阶段 +/// +public enum GodotInputPhase +{ + /// + /// 捕获阶段,在_Input方法中处理输入事件 + /// 这是输入事件的第一个处理阶段,事件会沿着节点树向下传递 + /// + Capture, // _Input + + /// + /// 冒泡阶段,在_UnhandledInput方法中处理输入事件 + /// 这是输入事件的第二个处理阶段,未被处理的事件会向上冒泡传递 + /// + Bubble // _UnhandledInput +} diff --git a/GFramework.Godot/input/GodotInputTranslator.cs b/GFramework.Godot/input/GodotInputTranslator.cs index b01d1cd..9ac1ba9 100644 --- a/GFramework.Godot/input/GodotInputTranslator.cs +++ b/GFramework.Godot/input/GodotInputTranslator.cs @@ -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( @@ -48,7 +51,6 @@ public sealed class GodotInputTranslator : IInputTranslator } // Mouse motion - // 处理鼠标移动输入事件 if (evt is InputEventMouseMotion mm) { gameEvent = new InputEvents.PointerInputEvent( diff --git a/GFramework.Godot/input/GodotRawInput.cs b/GFramework.Godot/input/GodotRawInput.cs new file mode 100644 index 0000000..1888c7f --- /dev/null +++ b/GFramework.Godot/input/GodotRawInput.cs @@ -0,0 +1,21 @@ +using Godot; + +namespace GFramework.Godot.input; + +/// +/// 表示Godot原始输入数据的只读结构体 +/// +/// 输入事件对象 +/// 输入阶段 +public readonly struct GodotRawInput(InputEvent evt, GodotInputPhase phase) +{ + /// + /// 获取输入事件对象 + /// + public readonly InputEvent Event = evt; + + /// + /// 获取输入阶段 + /// + public readonly GodotInputPhase Phase = phase; +}