mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-11 12:14:30 +08:00
- 修复 InputBindingStore 的线程安全使用说明并消除 GodotInputBindingCodec 的重复键码计算\n- 修复 GodotInputMapBackend 在全量重置时未移除运行时新增动作的语义偏差并补回归测试\n- 更新 input-system-godot-integration 的 tracking 与 trace,补录 PR review follow-up 验证结果
100 lines
2.8 KiB
C#
100 lines
2.8 KiB
C#
// Copyright (c) 2025-2026 GeWuYou
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
using GFramework.Game.Abstractions.Input;
|
|
|
|
namespace GFramework.Godot.Input;
|
|
|
|
/// <summary>
|
|
/// 基于 Godot `InputMap` 的默认后端实现。
|
|
/// </summary>
|
|
internal sealed class GodotInputMapBackend : IGodotInputMapBackend
|
|
{
|
|
private readonly Dictionary<string, List<InputBindingDescriptor>> _defaults;
|
|
|
|
/// <summary>
|
|
/// 初始化后端,并捕获当前 `InputMap` 作为默认快照。
|
|
/// </summary>
|
|
public GodotInputMapBackend()
|
|
{
|
|
_defaults = GetActionNames().ToDictionary(
|
|
static actionName => actionName,
|
|
actionName => GetBindings(actionName).ToList(),
|
|
StringComparer.Ordinal);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public IReadOnlyList<string> GetActionNames()
|
|
{
|
|
return [..InputMap.GetActions().Select(static action => action.ToString())];
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public IReadOnlyList<InputBindingDescriptor> GetBindings(string actionName)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(actionName);
|
|
|
|
if (!InputMap.HasAction(actionName))
|
|
{
|
|
return Array.Empty<InputBindingDescriptor>();
|
|
}
|
|
|
|
var bindings = new List<InputBindingDescriptor>();
|
|
foreach (var inputEvent in InputMap.ActionGetEvents(actionName))
|
|
{
|
|
if (GodotInputBindingCodec.TryCreateBinding(inputEvent, out var binding))
|
|
{
|
|
bindings.Add(binding);
|
|
}
|
|
}
|
|
|
|
return bindings;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void SetBindings(string actionName, IReadOnlyList<InputBindingDescriptor> bindings)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(actionName);
|
|
ArgumentNullException.ThrowIfNull(bindings);
|
|
|
|
if (!InputMap.HasAction(actionName))
|
|
{
|
|
InputMap.AddAction(actionName);
|
|
}
|
|
|
|
InputMap.ActionEraseEvents(actionName);
|
|
foreach (var binding in bindings)
|
|
{
|
|
InputMap.ActionAddEvent(actionName, GodotInputBindingCodec.CreateInputEvent(binding));
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void ResetAction(string actionName)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(actionName);
|
|
|
|
if (_defaults.TryGetValue(actionName, out var bindings))
|
|
{
|
|
SetBindings(actionName, bindings);
|
|
return;
|
|
}
|
|
|
|
if (InputMap.HasAction(actionName))
|
|
{
|
|
// Actions absent from the captured default snapshot should disappear after reset
|
|
// so the live InputMap matches the original project defaults exactly.
|
|
InputMap.EraseAction(actionName);
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void ResetAll()
|
|
{
|
|
foreach (var actionName in GetActionNames())
|
|
{
|
|
ResetAction(actionName);
|
|
}
|
|
}
|
|
}
|