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