From 4bd9853ec104d784931094cfd9e8d04967df2cf9 Mon Sep 17 00:00:00 2001
From: GwWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Sun, 21 Dec 2025 16:32:36 +0800
Subject: [PATCH] =?UTF-8?q?feat(input):=20=E5=BC=95=E5=85=A5=E8=BE=93?=
=?UTF-8?q?=E5=85=A5=E8=BD=AC=E6=8D=A2=E5=99=A8=E6=8E=A5=E5=8F=A3=E5=8F=8A?=
=?UTF-8?q?=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
新增 `IInputTranslator` 接口用于解耦原始输入与游戏事件的转换逻辑。
在 `InputSystem` 中增加注册、注销和处理原始输入的方法,支持优先级控制。
重构 `GodotInputBridge`,移除原有硬编码翻译逻辑,改为通过 `HandleRaw` 调用转换器处理。
新增 `GodotInputTranslator` 实现 `IInputTranslator`,负责将 Godot 输入事件翻译为游戏事件。
模块初始化时自动注册该转换器至输入系统。
---
GFramework.Game/input/IInputTranslator.cs | 15 +++++
GFramework.Game/input/InputEvents.cs | 4 +-
GFramework.Game/input/InputSystem.cs | 41 ++++++++++++
GFramework.Godot/input/GodotInputBridge.cs | 51 +--------------
GFramework.Godot/input/GodotInputModule.cs | 2 +
.../input/GodotInputTranslator.cs | 65 +++++++++++++++++++
6 files changed, 125 insertions(+), 53 deletions(-)
create mode 100644 GFramework.Game/input/IInputTranslator.cs
create mode 100644 GFramework.Godot/input/GodotInputTranslator.cs
diff --git a/GFramework.Game/input/IInputTranslator.cs b/GFramework.Game/input/IInputTranslator.cs
new file mode 100644
index 0000000..2936b28
--- /dev/null
+++ b/GFramework.Game/input/IInputTranslator.cs
@@ -0,0 +1,15 @@
+namespace GFramework.Game.input;
+
+///
+/// 输入转换器接口
+///
+public interface IInputTranslator
+{
+ ///
+ /// 尝试将引擎输入翻译为游戏输入
+ ///
+ /// 原始的引擎输入对象
+ /// 输出参数,如果翻译成功则包含对应的游戏输入事件
+ /// 如果翻译成功返回true,否则返回false
+ bool TryTranslate(object rawInput, out IGameInputEvent gameEvent);
+}
diff --git a/GFramework.Game/input/InputEvents.cs b/GFramework.Game/input/InputEvents.cs
index 3e672e2..b6c30b0 100644
--- a/GFramework.Game/input/InputEvents.cs
+++ b/GFramework.Game/input/InputEvents.cs
@@ -1,6 +1,4 @@
-using System.Numerics;
-
-namespace GFramework.Game.input;
+namespace GFramework.Game.input;
public static class InputEvents
{
diff --git a/GFramework.Game/input/InputSystem.cs b/GFramework.Game/input/InputSystem.cs
index 796dfc6..3de55d4 100644
--- a/GFramework.Game/input/InputSystem.cs
+++ b/GFramework.Game/input/InputSystem.cs
@@ -8,6 +8,7 @@ namespace GFramework.Game.input;
///
public class InputSystem : AbstractSystem
{
+ private readonly List _translators = [];
private readonly InputContextStack _contextStack = new();
///
@@ -43,4 +44,44 @@ public class InputSystem : AbstractSystem
{
}
+
+ ///
+ /// 注销输入转换器
+ ///
+ /// 要注销的输入转换器接口实例
+ public void UnregisterTranslator(IInputTranslator translator)
+ => _translators.Remove(translator);
+
+ ///
+ /// 注册输入转换器
+ ///
+ /// 输入转换器接口实例
+ /// 是否为高优先级,true时插入到转换器列表开头,false时添加到列表末尾
+ public void RegisterTranslator(IInputTranslator translator, bool highPriority = false)
+ {
+ if (_translators.Contains(translator))
+ return;
+ // 根据优先级设置决定插入位置
+ if (highPriority)
+ _translators.Insert(0, translator);
+ else
+ _translators.Add(translator);
+ }
+
+
+ ///
+ /// 处理原始输入数据
+ ///
+ /// 原始输入对象
+ public void HandleRaw(object rawInput)
+ {
+ // 遍历所有注册的转换器,尝试将原始输入转换为游戏事件
+ foreach (var t in _translators)
+ {
+ if (!t.TryTranslate(rawInput, out var gameEvent)) continue;
+ Handle(gameEvent);
+ return;
+ }
+ }
+
}
diff --git a/GFramework.Godot/input/GodotInputBridge.cs b/GFramework.Godot/input/GodotInputBridge.cs
index 7c89986..27f3ebf 100644
--- a/GFramework.Godot/input/GodotInputBridge.cs
+++ b/GFramework.Godot/input/GodotInputBridge.cs
@@ -25,55 +25,6 @@ public partial class GodotInputBridge : Node
/// Godot输入事件
public override void _Input(InputEvent @event)
{
- var gameEvent = Translate(@event);
- if (gameEvent == null)
- {
- return;
- }
-
- _inputSystem.Handle(gameEvent);
- GetViewport().SetInputAsHandled();
- }
-
- ///
- /// 将Godot输入事件翻译为游戏框架输入事件
- ///
- /// Godot输入事件
- /// 翻译后的游戏输入事件,如果无法翻译则返回null
- private static IGameInputEvent? Translate(InputEvent evt)
- {
- // 处理动作输入事件
- if (evt is InputEventAction action)
- {
- return new InputEvents.KeyInputEvent(
- action.Action,
- action.Pressed,
- false
- );
- }
-
- // 鼠标按钮
- if (evt is InputEventMouseButton mb)
- {
- return new InputEvents.PointerInputEvent(
- mb.Position,
- Vector2.Zero,
- (int)mb.ButtonIndex,
- mb.Pressed
- );
- }
-
- // 鼠标移动
- if (evt is InputEventMouseMotion mm)
- {
- return new InputEvents.PointerInputEvent(
- mm.Position,
- mm.Relative,
- 0,
- false
- );
- }
-
- return null;
+ _inputSystem.HandleRaw(@event);
}
}
diff --git a/GFramework.Godot/input/GodotInputModule.cs b/GFramework.Godot/input/GodotInputModule.cs
index 9b020e3..b498c39 100644
--- a/GFramework.Godot/input/GodotInputModule.cs
+++ b/GFramework.Godot/input/GodotInputModule.cs
@@ -57,5 +57,7 @@ public sealed class GodotInputModule : AbstractGodotModule
{
// 从架构中获取输入系统实例
_inputSystem = architecture.GetSystem()!;
+ // 注册输入转换器
+ _inputSystem.RegisterTranslator(new GodotInputTranslator());
}
}
diff --git a/GFramework.Godot/input/GodotInputTranslator.cs b/GFramework.Godot/input/GodotInputTranslator.cs
new file mode 100644
index 0000000..b01d1cd
--- /dev/null
+++ b/GFramework.Godot/input/GodotInputTranslator.cs
@@ -0,0 +1,65 @@
+using GFramework.Game.input;
+using Godot;
+
+namespace GFramework.Godot.input;
+
+///
+/// 将Godot引擎的输入事件转换为游戏通用输入事件的翻译器
+///
+public sealed class GodotInputTranslator : IInputTranslator
+{
+ ///
+ /// 尝试将原始输入对象转换为游戏输入事件
+ ///
+ /// 原始输入对象,应为Godot的InputEvent类型
+ /// 输出参数,转换成功时返回对应的游戏输入事件,失败时返回null
+ /// 转换成功返回true,否则返回false
+ public bool TryTranslate(object rawInput, out IGameInputEvent gameEvent)
+ {
+ gameEvent = null!;
+
+ // 检查输入是否为Godot的InputEvent类型
+ if (rawInput is not InputEvent evt)
+ return false;
+
+ // Action
+ // 处理动作输入事件(如键盘按键、手柄按钮等)
+ if (evt is InputEventAction action)
+ {
+ gameEvent = new InputEvents.KeyInputEvent(
+ action.Action,
+ action.Pressed,
+ false
+ );
+ return true;
+ }
+
+ // Mouse button
+ // 处理鼠标按钮输入事件
+ if (evt is InputEventMouseButton mb)
+ {
+ gameEvent = new InputEvents.PointerInputEvent(
+ mb.Position,
+ Vector2.Zero,
+ (int)mb.ButtonIndex,
+ mb.Pressed
+ );
+ return true;
+ }
+
+ // Mouse motion
+ // 处理鼠标移动输入事件
+ if (evt is InputEventMouseMotion mm)
+ {
+ gameEvent = new InputEvents.PointerInputEvent(
+ mm.Position,
+ mm.Relative,
+ 0,
+ false
+ );
+ return true;
+ }
+
+ return false;
+ }
+}