// 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)) { InputMap.ActionEraseEvents(actionName); } } /// public void ResetAll() { foreach (var actionName in GetActionNames()) { ResetAction(actionName); } } }