// Copyright (c) 2025-2026 GeWuYou
// SPDX-License-Identifier: Apache-2.0
using GFramework.Game.Abstractions.Input;
namespace GFramework.Godot.Input;
///
/// 基于 Godot `InputMap` 的默认后端实现。
///
internal sealed class GodotInputMapBackend : IGodotInputMapBackend
{
private readonly Dictionary> _defaults;
///
/// 初始化后端,并捕获当前 `InputMap` 作为默认快照。
///
public GodotInputMapBackend()
{
_defaults = GetActionNames().ToDictionary(
static actionName => actionName,
actionName => GetBindings(actionName).ToList(),
StringComparer.Ordinal);
}
///
public IReadOnlyList GetActionNames()
{
return [..InputMap.GetActions().Select(static action => action.ToString())];
}
///
public IReadOnlyList GetBindings(string actionName)
{
ArgumentException.ThrowIfNullOrWhiteSpace(actionName);
if (!InputMap.HasAction(actionName))
{
return Array.Empty();
}
var bindings = new List();
foreach (var inputEvent in InputMap.ActionGetEvents(actionName))
{
if (GodotInputBindingCodec.TryCreateBinding(inputEvent, out var binding))
{
bindings.Add(binding);
}
}
return bindings;
}
///
public void SetBindings(string actionName, IReadOnlyList 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));
}
}
///
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);
}
}
///
public void ResetAll()
{
foreach (var actionName in GetActionNames())
{
ResetAction(actionName);
}
}
}