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