feat(input): 引入输入转换器接口及实现

新增 `IInputTranslator` 接口用于解耦原始输入与游戏事件的转换逻辑。
在 `InputSystem` 中增加注册、注销和处理原始输入的方法,支持优先级控制。
重构 `GodotInputBridge`,移除原有硬编码翻译逻辑,改为通过 `HandleRaw` 调用转换器处理。
新增 `GodotInputTranslator` 实现 `IInputTranslator`,负责将 Godot 输入事件翻译为游戏事件。
模块初始化时自动注册该转换器至输入系统。
This commit is contained in:
GwWuYou 2025-12-21 16:32:36 +08:00
parent 339498e629
commit 4bd9853ec1
6 changed files with 125 additions and 53 deletions

View File

@ -0,0 +1,15 @@
namespace GFramework.Game.input;
/// <summary>
/// 输入转换器接口
/// </summary>
public interface IInputTranslator
{
/// <summary>
/// 尝试将引擎输入翻译为游戏输入
/// </summary>
/// <param name="rawInput">原始的引擎输入对象</param>
/// <param name="gameEvent">输出参数,如果翻译成功则包含对应的游戏输入事件</param>
/// <returns>如果翻译成功返回true否则返回false</returns>
bool TryTranslate(object rawInput, out IGameInputEvent gameEvent);
}

View File

@ -1,6 +1,4 @@
using System.Numerics;
namespace GFramework.Game.input;
namespace GFramework.Game.input;
public static class InputEvents
{

View File

@ -8,6 +8,7 @@ namespace GFramework.Game.input;
/// </summary>
public class InputSystem : AbstractSystem
{
private readonly List<IInputTranslator> _translators = [];
private readonly InputContextStack _contextStack = new();
/// <summary>
@ -43,4 +44,44 @@ public class InputSystem : AbstractSystem
{
}
/// <summary>
/// 注销输入转换器
/// </summary>
/// <param name="translator">要注销的输入转换器接口实例</param>
public void UnregisterTranslator(IInputTranslator translator)
=> _translators.Remove(translator);
/// <summary>
/// 注册输入转换器
/// </summary>
/// <param name="translator">输入转换器接口实例</param>
/// <param name="highPriority">是否为高优先级true时插入到转换器列表开头false时添加到列表末尾</param>
public void RegisterTranslator(IInputTranslator translator, bool highPriority = false)
{
if (_translators.Contains(translator))
return;
// 根据优先级设置决定插入位置
if (highPriority)
_translators.Insert(0, translator);
else
_translators.Add(translator);
}
/// <summary>
/// 处理原始输入数据
/// </summary>
/// <param name="rawInput">原始输入对象</param>
public void HandleRaw(object rawInput)
{
// 遍历所有注册的转换器,尝试将原始输入转换为游戏事件
foreach (var t in _translators)
{
if (!t.TryTranslate(rawInput, out var gameEvent)) continue;
Handle(gameEvent);
return;
}
}
}

View File

@ -25,55 +25,6 @@ public partial class GodotInputBridge : Node
/// <param name="event">Godot输入事件</param>
public override void _Input(InputEvent @event)
{
var gameEvent = Translate(@event);
if (gameEvent == null)
{
return;
}
_inputSystem.Handle(gameEvent);
GetViewport().SetInputAsHandled();
}
/// <summary>
/// 将Godot输入事件翻译为游戏框架输入事件
/// </summary>
/// <param name="evt">Godot输入事件</param>
/// <returns>翻译后的游戏输入事件如果无法翻译则返回null</returns>
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<Vector2>(
mb.Position,
Vector2.Zero,
(int)mb.ButtonIndex,
mb.Pressed
);
}
// 鼠标移动
if (evt is InputEventMouseMotion mm)
{
return new InputEvents.PointerInputEvent<Vector2>(
mm.Position,
mm.Relative,
0,
false
);
}
return null;
_inputSystem.HandleRaw(@event);
}
}

View File

@ -57,5 +57,7 @@ public sealed class GodotInputModule<T> : AbstractGodotModule<T>
{
// 从架构中获取输入系统实例
_inputSystem = architecture.GetSystem<InputSystem>()!;
// 注册输入转换器
_inputSystem.RegisterTranslator(new GodotInputTranslator());
}
}

View File

@ -0,0 +1,65 @@
using GFramework.Game.input;
using Godot;
namespace GFramework.Godot.input;
/// <summary>
/// 将Godot引擎的输入事件转换为游戏通用输入事件的翻译器
/// </summary>
public sealed class GodotInputTranslator : IInputTranslator
{
/// <summary>
/// 尝试将原始输入对象转换为游戏输入事件
/// </summary>
/// <param name="rawInput">原始输入对象应为Godot的InputEvent类型</param>
/// <param name="gameEvent">输出参数转换成功时返回对应的游戏输入事件失败时返回null</param>
/// <returns>转换成功返回true否则返回false</returns>
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<Vector2>(
mb.Position,
Vector2.Zero,
(int)mb.ButtonIndex,
mb.Pressed
);
return true;
}
// Mouse motion
// 处理鼠标移动输入事件
if (evt is InputEventMouseMotion mm)
{
gameEvent = new InputEvents.PointerInputEvent<Vector2>(
mm.Position,
mm.Relative,
0,
false
);
return true;
}
return false;
}
}