From 028ece27db3353dd474b1502362cfb6381e32e4f Mon Sep 17 00:00:00 2001 From: GwWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Sun, 21 Dec 2025 16:52:36 +0800 Subject: [PATCH] =?UTF-8?q?```=20refactor(input):=20=E9=87=8D=E6=9E=84Godo?= =?UTF-8?q?t=E8=BE=93=E5=85=A5=E6=A8=A1=E5=9D=97=E4=B8=BA=E6=8A=BD?= =?UTF-8?q?=E8=B1=A1=E5=9F=BA=E7=B1=BB=E5=B9=B6=E4=BC=98=E5=8C=96=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E5=A4=84=E7=90=86=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 `GodotInputModule` 重命名为 `AbstractGodotInputModule` 并改为抽象类, 以便支持更灵活的输入翻译器注册机制。引入 `GodotInputPhase` 枚举和 `GodotRawInput` 结构体以区分输入处理的不同阶段(捕获与冒泡)。 同时修改 `GodotInputTranslator` 仅在Bubble阶段生成游戏事件,提升输入处理精度。 ``` --- ...tModule.cs => AbstractGodotInputModule.cs} | 33 +++++++++++++++---- GFramework.Godot/input/GodotInputBridge.cs | 17 ++++++++-- GFramework.Godot/input/GodotInputPhase.cs | 19 +++++++++++ .../input/GodotInputTranslator.cs | 12 ++++--- GFramework.Godot/input/GodotRawInput.cs | 21 ++++++++++++ 5 files changed, 87 insertions(+), 15 deletions(-) rename GFramework.Godot/input/{GodotInputModule.cs => AbstractGodotInputModule.cs} (74%) create mode 100644 GFramework.Godot/input/GodotInputPhase.cs create mode 100644 GFramework.Godot/input/GodotRawInput.cs 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; +}