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