From be6a2588460a7c5cae778a7663e984ccd56aa498 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 3 Feb 2025 21:57:14 -0600 Subject: [PATCH] Add runtime input mapping helpers. --- Source/Engine/Input/Input.cpp | 204 ++++++++++++++++++++++++++++++++++ Source/Engine/Input/Input.h | 111 ++++++++++++++++++ 2 files changed, 315 insertions(+) diff --git a/Source/Engine/Input/Input.cpp b/Source/Engine/Input/Input.cpp index d1ccd367e..e708be2c9 100644 --- a/Source/Engine/Input/Input.cpp +++ b/Source/Engine/Input/Input.cpp @@ -614,6 +614,210 @@ float Input::GetAxisRaw(const StringView& name) return e ? e->ValueRaw : false; } +void Input::SetInputMappingFromSettings(const JsonAssetReference& settings) +{ + ActionMappings.Clear(); + auto actionMappings = settings.GetInstance()->ActionMappings; + ActionMappings.Resize(actionMappings.Count(), false); + for (int i = 0; i < actionMappings.Count(); i++) + { + ActionMappings[i] = actionMappings.At(i); + } + + auto axisMappings = settings.GetInstance()->AxisMappings; + AxisMappings.Resize(axisMappings.Count(), false); + for (int i = 0; i < axisMappings.Count(); i++) + { + AxisMappings[i] = axisMappings.At(i); + } + Axes.Clear(); + Actions.Clear(); +} + +void Input::SetInputMappingToDefaultSettings() +{ + InputSettings* settings = InputSettings::Get(); + if (settings) + { + ActionMappings = settings->ActionMappings; + AxisMappings = settings->AxisMappings; + Axes.Clear(); + Actions.Clear(); + } +} + +ActionConfig Input::GetActionConfigByName(const StringView& name) +{ + ActionConfig config = {}; + for (const auto& a : ActionMappings) + { + if (a.Name == name) + { + config = a; + return config; + } + } + return config; +} + +Array Input::GetAllActionConfigsByName(const StringView& name) +{ + Array actionConfigs; + for (const auto& a : ActionMappings) + { + if (a.Name == name) + actionConfigs.Add(a); + } + return actionConfigs; +} + +AxisConfig Input::GetAxisConfigByName(const StringView& name) +{ + AxisConfig config = {}; + for (const auto& a : AxisMappings) + { + if (a.Name == name) + { + config = a; + return config; + } + } + return config; +} + +Array Input::GetAllAxisConfigsByName(const StringView& name) +{ + Array actionConfigs; + for (const auto& a : AxisMappings) + { + if (a.Name == name) + actionConfigs.Add(a); + } + return actionConfigs; +} + +void Input::SetAxisConfigByName(const StringView& name, AxisConfig& config, bool all) +{ + for (int i = 0; i < AxisMappings.Count(); ++i) + { + auto& mapping = AxisMappings.At(i); + if (mapping.Name.Compare(name.ToString()) == 0) + { + if (config.Name.IsEmpty()) + config.Name = name; + mapping = config; + if (!all) + break; + } + } +} + +void Input::SetAxisConfigByName(const StringView& name, InputAxisType inputType, const KeyboardKeys positiveButton, const KeyboardKeys negativeButton, bool all) +{ + for (int i = 0; i < AxisMappings.Count(); ++i) + { + auto& mapping = AxisMappings.At(i); + if (mapping.Name.Compare(name.ToString()) == 0 && mapping.Axis == inputType) + { + mapping.PositiveButton = positiveButton; + mapping.NegativeButton = negativeButton; + if (!all) + break; + } + } +} + +void Input::SetAxisConfigByName(const StringView& name, InputAxisType inputType, const GamepadButton positiveButton, const GamepadButton negativeButton, InputGamepadIndex gamepadIndex, bool all) +{ + for (int i = 0; i < AxisMappings.Count(); ++i) + { + auto& mapping = AxisMappings.At(i); + if (mapping.Name.Compare(name.ToString()) == 0 && mapping.Gamepad == gamepadIndex && mapping.Axis == inputType) + { + mapping.GamepadPositiveButton = positiveButton; + mapping.GamepadNegativeButton = negativeButton; + if (!all) + break; + } + } +} + +void Input::SetAxisConfigByName(const StringView& name, InputAxisType inputType, const float gravity, const float deadZone, const float sensitivity, const float scale, const bool snap, bool all) +{ + for (int i = 0; i < AxisMappings.Count(); ++i) + { + auto& mapping = AxisMappings.At(i); + if (mapping.Name.Compare(name.ToString()) == 0 && mapping.Axis == inputType) + { + mapping.Gravity = gravity; + mapping.DeadZone = deadZone; + mapping.Sensitivity = sensitivity; + mapping.Scale = scale; + mapping.Snap = snap; + if (!all) + break; + } + } +} + +void Input::SetActionConfigByName(const StringView& name, const KeyboardKeys key, bool all) +{ + for (int i = 0; i < ActionMappings.Count(); ++i) + { + auto& mapping = ActionMappings.At(i); + if (mapping.Name.Compare(name.ToString()) == 0) + { + mapping.Key = key; + if (!all) + break; + } + } +} + +void Input::SetActionConfigByName(const StringView& name, const MouseButton mouseButton, bool all) +{ + for (int i = 0; i < ActionMappings.Count(); ++i) + { + auto& mapping = ActionMappings.At(i); + if (mapping.Name.Compare(name.ToString()) == 0) + { + mapping.MouseButton = mouseButton; + if (!all) + break; + } + } +} + +void Input::SetActionConfigByName(const StringView& name, const GamepadButton gamepadButton, InputGamepadIndex gamepadIndex, bool all) +{ + for (int i = 0; i < ActionMappings.Count(); ++i) + { + auto& mapping = ActionMappings.At(i); + if (mapping.Name.Compare(name.ToString()) == 0 && mapping.Gamepad == gamepadIndex) + { + mapping.GamepadButton = gamepadButton; + if (!all) + break; + } + } +} + +void Input::SetActionConfigByName(const StringView& name, ActionConfig& config, bool all) +{ + for (int i = 0; i < ActionMappings.Count(); ++i) + { + auto& mapping = ActionMappings.At(i); + if (mapping.Name.Compare(name.ToString()) == 0) + { + if (config.Name.IsEmpty()) + config.Name = name; + mapping = config; + if (!all) + break; + } + } +} + void InputService::Update() { PROFILE_CPU(); diff --git a/Source/Engine/Input/Input.h b/Source/Engine/Input/Input.h index 2f8c09b38..a937f4f2e 100644 --- a/Source/Engine/Input/Input.h +++ b/Source/Engine/Input/Input.h @@ -9,6 +9,7 @@ #include "KeyboardKeys.h" #include "Enums.h" #include "VirtualInput.h" +#include "Engine/Content/JsonAssetReference.h" class Mouse; class Keyboard; @@ -332,4 +333,114 @@ public: /// The current axis value (e.g for gamepads it's in the range -1..1). No smoothing applied. /// API_FUNCTION() static float GetAxisRaw(const StringView& name); + + /// + /// Sets and overwrites the Action and Axis mappings with the values from a new InputSettings. + /// + /// The input settings. + API_FUNCTION() static void SetInputMappingFromSettings(const JsonAssetReference& settings); + + /// + /// Sets and overwrites the Action and Axis mappings with the values from the InputSettings in GameSettings. + /// + API_FUNCTION() static void SetInputMappingToDefaultSettings(); + + /// + /// Gets the first action configuration by name. + /// + /// The name of the action config. + API_FUNCTION() static ActionConfig GetActionConfigByName(const StringView& name); + + /// + /// Gets all the action configurations by name. + /// + /// The name of the action config. + API_FUNCTION() static Array GetAllActionConfigsByName(const StringView& name); + + /// + /// Sets the action configuration keyboard key by name. + /// + /// The name of the action config. + /// The key to set. + /// Whether to set only the first config found or all of them. + API_FUNCTION() static void SetActionConfigByName(const StringView& name, const KeyboardKeys key, bool all = false); + + /// + /// Sets the action configuration mouse button by name. + /// + /// The name of the action config. + /// The mouse button to set. + /// Whether to set only the first config found or all of them. + API_FUNCTION() static void SetActionConfigByName(const StringView& name, const MouseButton mouseButton, bool all = false); + + /// + /// Sets the action configuration gamepad button by name and index. + /// + /// The name of the action config. + /// The gamepad button to set. + /// The gamepad index used to find the correct config. + /// Whether to set only the first config found or all of them. + API_FUNCTION() static void SetActionConfigByName(const StringView& name, const GamepadButton gamepadButton, InputGamepadIndex gamepadIndex, bool all = false); + + /// + /// Sets the action configuration by name. + /// + /// The name of the action config. + /// The action configuration to set. Leave the config name empty to use set name. + /// Whether to set only the first config found or all of them. + API_FUNCTION() static void SetActionConfigByName(const StringView& name, ActionConfig& config, bool all = false); + + /// + /// Gets the first axis configurations by name. + /// + /// The name of the axis config. + API_FUNCTION() static AxisConfig GetAxisConfigByName(const StringView& name); + + /// + /// Gets all the axis configurations by name. + /// + /// The name of the axis config. + API_FUNCTION() static Array GetAllAxisConfigsByName(const StringView& name); + + /// + /// Sets the axis configuration keyboard key by name and type. + /// + /// The name of the action config. + /// The configuration to set. Leave the config name empty to use set name. + /// Whether to set only the first config found or all of them. + API_FUNCTION() static void SetAxisConfigByName(const StringView& name, AxisConfig& config, bool all = false); + + /// + /// Sets the axis configuration keyboard key buttons by name and type. + /// + /// The name of the action config. + /// The type to sort by. + /// The positive key button. + /// The negative key button. + /// Whether to set only the first config found or all of them. + API_FUNCTION() static void SetAxisConfigByName(const StringView& name, InputAxisType inputType, const KeyboardKeys positiveButton, const KeyboardKeys negativeButton, bool all = false); + + /// + /// Sets the axis configuration gamepad buttons by name, type, and index. + /// + /// The name of the action config. + /// The type to sort by. + /// The positive gamepad button. + /// The negative gamepad button. + /// The gamepad index to sort by. + /// Whether to set only the first config found or all of them. + API_FUNCTION() static void SetAxisConfigByName(const StringView& name, InputAxisType inputType, const GamepadButton positiveButton, const GamepadButton negativeButton, InputGamepadIndex gamepadIndex, bool all = false); + + /// + /// Sets the axis configuration accessories by name, and type.. + /// + /// The name of the action config. + /// The type to sort by. + /// The gravity to set. + /// The dead zone to set. + /// The sensitivity to set. + /// The scale to set. + /// The snap to set. + /// Whether to set only the first config found or all of them. + API_FUNCTION() static void SetAxisConfigByName(const StringView& name, InputAxisType inputType, const float gravity, const float deadZone, const float sensitivity, const float scale, const bool snap, bool all = false); };