-
Notifications
You must be signed in to change notification settings - Fork 4
feat(input): 新增统一输入抽象与Godot集成 #346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| // Copyright (c) 2025-2026 GeWuYou | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| namespace GFramework.Game.Abstractions.Input; | ||
|
|
||
| /// <summary> | ||
| /// 定义逻辑动作绑定的查询、修改与快照导入导出契约。 | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// 该接口承担框架输入系统的持久化与重绑定边界。 | ||
| /// 宿主层可以把自己的原生输入系统适配到这里,上层业务则只依赖动作名和绑定描述,不直接接触宿主输入事件。 | ||
| /// </remarks> | ||
| public interface IInputBindingStore | ||
| { | ||
| /// <summary> | ||
| /// 获取指定动作的当前绑定。 | ||
| /// </summary> | ||
| /// <param name="actionName">动作名称。</param> | ||
| /// <returns>动作绑定快照。</returns> | ||
| InputActionBinding GetBindings(string actionName); | ||
|
|
||
| /// <summary> | ||
| /// 获取所有动作的当前绑定快照。 | ||
| /// </summary> | ||
| /// <returns>全量输入绑定快照。</returns> | ||
| InputBindingSnapshot ExportSnapshot(); | ||
|
|
||
| /// <summary> | ||
| /// 使用给定快照替换当前绑定。 | ||
| /// </summary> | ||
| /// <param name="snapshot">要导入的快照。</param> | ||
| void ImportSnapshot(InputBindingSnapshot snapshot); | ||
|
|
||
| /// <summary> | ||
| /// 把指定绑定设置为动作的主绑定。 | ||
| /// </summary> | ||
| /// <param name="actionName">动作名称。</param> | ||
| /// <param name="binding">新绑定。</param> | ||
| /// <param name="swapIfTaken">是否在冲突时交换已占用绑定。</param> | ||
| void SetPrimaryBinding(string actionName, InputBindingDescriptor binding, bool swapIfTaken = true); | ||
|
|
||
| /// <summary> | ||
| /// 将指定动作恢复为默认绑定。 | ||
| /// </summary> | ||
| /// <param name="actionName">动作名称。</param> | ||
| void ResetAction(string actionName); | ||
|
|
||
| /// <summary> | ||
| /// 将所有动作恢复为默认绑定。 | ||
| /// </summary> | ||
| void ResetAll(); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| // Copyright (c) 2025-2026 GeWuYou | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| namespace GFramework.Game.Abstractions.Input; | ||
|
|
||
| /// <summary> | ||
| /// 定义当前活跃输入设备上下文的查询入口。 | ||
| /// </summary> | ||
| public interface IInputDeviceTracker | ||
| { | ||
| /// <summary> | ||
| /// 获取当前输入设备上下文。 | ||
| /// </summary> | ||
| InputDeviceContext CurrentDevice { get; } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // Copyright (c) 2025-2026 GeWuYou | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| using GFramework.Game.Abstractions.UI; | ||
|
|
||
| namespace GFramework.Game.Abstractions.Input; | ||
|
|
||
| /// <summary> | ||
| /// 定义逻辑动作名到 UI 语义动作的映射规则。 | ||
| /// </summary> | ||
| public interface IUiInputActionMap | ||
| { | ||
| /// <summary> | ||
| /// 尝试把逻辑动作映射为 UI 语义动作。 | ||
| /// </summary> | ||
| /// <param name="actionName">逻辑动作名称。</param> | ||
| /// <param name="action">映射出的 UI 语义动作。</param> | ||
| /// <returns>如果映射成功则返回 <see langword="true" />。</returns> | ||
| bool TryMap(string actionName, out UiInputAction action); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| // Copyright (c) 2025-2026 GeWuYou | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| namespace GFramework.Game.Abstractions.Input; | ||
|
|
||
| /// <summary> | ||
| /// 定义面向 UI 语义动作的输入分发入口。 | ||
| /// </summary> | ||
| public interface IUiInputDispatcher | ||
| { | ||
| /// <summary> | ||
| /// 尝试把逻辑动作分发到当前 UI 路由。 | ||
| /// </summary> | ||
| /// <param name="actionName">逻辑动作名称。</param> | ||
| /// <returns>如果该动作被映射为 UI 动作并成功分发,则返回 <see langword="true" />。</returns> | ||
| bool TryDispatch(string actionName); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // Copyright (c) 2025-2026 GeWuYou | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| namespace GFramework.Game.Abstractions.Input; | ||
|
|
||
| /// <summary> | ||
| /// 描述一个逻辑动作当前持有的绑定集合。 | ||
| /// </summary> | ||
| public sealed class InputActionBinding | ||
| { | ||
| /// <summary> | ||
| /// 初始化一个动作绑定快照。 | ||
| /// </summary> | ||
| /// <param name="actionName">动作名称。</param> | ||
| /// <param name="bindings">当前绑定列表。</param> | ||
| /// <exception cref="ArgumentException">当 <paramref name="actionName" /> 为空时抛出。</exception> | ||
| public InputActionBinding(string actionName, IReadOnlyList<InputBindingDescriptor> bindings) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(actionName)) | ||
| { | ||
| throw new ArgumentException("Action name cannot be null or whitespace.", nameof(actionName)); | ||
| } | ||
|
|
||
| ActionName = actionName; | ||
| Bindings = bindings ?? Array.Empty<InputBindingDescriptor>(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// 获取动作名称。 | ||
| /// </summary> | ||
| public string ActionName { get; } | ||
|
|
||
| /// <summary> | ||
| /// 获取当前绑定列表。 | ||
| /// </summary> | ||
| public IReadOnlyList<InputBindingDescriptor> Bindings { get; } | ||
| } |
67 changes: 67 additions & 0 deletions
67
GFramework.Game.Abstractions/Input/InputBindingDescriptor.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| // Copyright (c) 2025-2026 GeWuYou | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| namespace GFramework.Game.Abstractions.Input; | ||
|
|
||
| /// <summary> | ||
| /// 描述一个框架无关的动作绑定。 | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// 该模型是运行时输入系统与宿主适配层之间的稳定交换格式。 | ||
| /// 宿主层负责把原生输入事件转成此描述,抽象层和默认运行时只根据这些字段做查询、冲突检测和持久化。 | ||
| /// </remarks> | ||
| public sealed class InputBindingDescriptor | ||
| { | ||
| /// <summary> | ||
| /// 初始化一个动作绑定描述。 | ||
| /// </summary> | ||
| /// <param name="deviceKind">设备族。</param> | ||
| /// <param name="bindingKind">绑定类型。</param> | ||
| /// <param name="code">宿主无关的物理码值。</param> | ||
| /// <param name="displayName">用于设置界面展示的名称。</param> | ||
| /// <param name="axisDirection">轴向方向;非轴向绑定时为 <see langword="null" />。</param> | ||
| /// <exception cref="ArgumentException">当 <paramref name="code" /> 为空时抛出。</exception> | ||
| public InputBindingDescriptor( | ||
| InputDeviceKind deviceKind, | ||
| InputBindingKind bindingKind, | ||
| string code, | ||
| string displayName, | ||
| float? axisDirection = null) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(code)) | ||
| { | ||
| throw new ArgumentException("Binding code cannot be null or whitespace.", nameof(code)); | ||
| } | ||
|
|
||
| DeviceKind = deviceKind; | ||
| BindingKind = bindingKind; | ||
| Code = code; | ||
| DisplayName = displayName ?? string.Empty; | ||
| AxisDirection = axisDirection; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// 获取设备族。 | ||
| /// </summary> | ||
| public InputDeviceKind DeviceKind { get; } | ||
|
|
||
| /// <summary> | ||
| /// 获取绑定类型。 | ||
| /// </summary> | ||
| public InputBindingKind BindingKind { get; } | ||
|
|
||
| /// <summary> | ||
| /// 获取宿主无关的物理码值。 | ||
| /// </summary> | ||
| public string Code { get; } | ||
|
|
||
| /// <summary> | ||
| /// 获取用于展示的标签。 | ||
| /// </summary> | ||
| public string DisplayName { get; } | ||
|
|
||
| /// <summary> | ||
| /// 获取轴向方向。 | ||
| /// </summary> | ||
| public float? AxisDirection { get; } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // Copyright (c) 2025-2026 GeWuYou | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| namespace GFramework.Game.Abstractions.Input; | ||
|
|
||
| /// <summary> | ||
| /// 描述一个逻辑绑定使用的物理输入类型。 | ||
| /// </summary> | ||
| public enum InputBindingKind | ||
| { | ||
| /// <summary> | ||
| /// 未指定。 | ||
| /// </summary> | ||
| Unknown = 0, | ||
|
|
||
| /// <summary> | ||
| /// 键盘按键。 | ||
| /// </summary> | ||
| Key = 1, | ||
|
|
||
| /// <summary> | ||
| /// 鼠标按钮。 | ||
| /// </summary> | ||
| MouseButton = 2, | ||
|
|
||
| /// <summary> | ||
| /// 手柄按钮。 | ||
| /// </summary> | ||
| GamepadButton = 3, | ||
|
|
||
| /// <summary> | ||
| /// 手柄轴向。 | ||
| /// </summary> | ||
| GamepadAxis = 4 | ||
| } |
24 changes: 24 additions & 0 deletions
24
GFramework.Game.Abstractions/Input/InputBindingSnapshot.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // Copyright (c) 2025-2026 GeWuYou | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| namespace GFramework.Game.Abstractions.Input; | ||
|
|
||
| /// <summary> | ||
| /// 描述一组动作绑定的可持久化快照。 | ||
| /// </summary> | ||
| public sealed class InputBindingSnapshot | ||
| { | ||
| /// <summary> | ||
| /// 初始化一个输入绑定快照。 | ||
| /// </summary> | ||
| /// <param name="actions">动作绑定集合。</param> | ||
| public InputBindingSnapshot(IReadOnlyList<InputActionBinding> actions) | ||
| { | ||
| Actions = actions ?? Array.Empty<InputActionBinding>(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// 获取动作绑定集合。 | ||
| /// </summary> | ||
| public IReadOnlyList<InputActionBinding> Actions { get; } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| // Copyright (c) 2025-2026 GeWuYou | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| namespace GFramework.Game.Abstractions.Input; | ||
|
|
||
| /// <summary> | ||
| /// 描述当前活跃输入设备上下文。 | ||
| /// </summary> | ||
| public sealed class InputDeviceContext | ||
| { | ||
| /// <summary> | ||
| /// 初始化一个输入设备上下文。 | ||
| /// </summary> | ||
| /// <param name="deviceKind">当前设备族。</param> | ||
| /// <param name="deviceIndex">设备索引;未知时为 <see langword="null" />。</param> | ||
| /// <param name="deviceName">宿主归一化后的设备名称。</param> | ||
| public InputDeviceContext( | ||
| InputDeviceKind deviceKind, | ||
| int? deviceIndex = null, | ||
| string? deviceName = null) | ||
| { | ||
| DeviceKind = deviceKind; | ||
| DeviceIndex = deviceIndex; | ||
| DeviceName = deviceName ?? string.Empty; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// 获取当前设备族。 | ||
| /// </summary> | ||
| public InputDeviceKind DeviceKind { get; } | ||
|
|
||
| /// <summary> | ||
| /// 获取当前设备索引。 | ||
| /// </summary> | ||
| public int? DeviceIndex { get; } | ||
|
|
||
| /// <summary> | ||
| /// 获取宿主归一化后的设备名称。 | ||
| /// </summary> | ||
| public string DeviceName { get; } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // Copyright (c) 2025-2026 GeWuYou | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| namespace GFramework.Game.Abstractions.Input; | ||
|
|
||
| /// <summary> | ||
| /// 描述框架级输入设备族。 | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// 该枚举用于跨宿主共享“当前输入来自哪一类设备”的语义。 | ||
| /// 它故意避免暴露 Godot、Unity 或平台 SDK 的原生事件类型,确保上层业务只依赖稳定的设备族判断。 | ||
| /// </remarks> | ||
| public enum InputDeviceKind | ||
| { | ||
| /// <summary> | ||
| /// 未识别或尚未产生任何输入。 | ||
| /// </summary> | ||
| Unknown = 0, | ||
|
|
||
| /// <summary> | ||
| /// 键盘与鼠标输入。 | ||
| /// </summary> | ||
| KeyboardMouse = 1, | ||
|
|
||
| /// <summary> | ||
| /// 游戏手柄输入。 | ||
| /// </summary> | ||
| Gamepad = 2, | ||
|
|
||
| /// <summary> | ||
| /// 触摸输入。 | ||
| /// </summary> | ||
| Touch = 3 | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.