// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "input_source.h" #include "common/string_util.h" InputSource::InputSource() = default; InputSource::~InputSource() = default; void InputSource::UpdateMotorState(InputBindingKey large_key, InputBindingKey small_key, float large_intensity, float small_intensity) { if (large_key.bits != 0) UpdateMotorState(large_key, large_intensity); if (small_key.bits != 0) UpdateMotorState(small_key, small_intensity); } InputBindingKey InputSource::MakeGenericControllerAxisKey(InputSourceType clazz, u32 controller_index, s32 axis_index) { InputBindingKey key = {}; key.source_type = clazz; key.source_index = controller_index; key.source_subtype = InputSubclass::ControllerAxis; key.data = static_cast(axis_index); return key; } InputBindingKey InputSource::MakeGenericControllerButtonKey(InputSourceType clazz, u32 controller_index, s32 button_index) { InputBindingKey key = {}; key.source_type = clazz; key.source_index = controller_index; key.source_subtype = InputSubclass::ControllerButton; key.data = static_cast(button_index); return key; } InputBindingKey InputSource::MakeGenericControllerHatKey(InputSourceType clazz, u32 controller_index, s32 hat_index, u8 hat_direction, u32 num_directions) { InputBindingKey key = {}; key.source_type = clazz; key.source_index = controller_index; key.source_subtype = InputSubclass::ControllerHat; key.data = static_cast(hat_index) * num_directions + hat_direction; return key; } InputBindingKey InputSource::MakeGenericControllerMotorKey(InputSourceType clazz, u32 controller_index, s32 motor_index) { InputBindingKey key = {}; key.source_type = clazz; key.source_index = controller_index; key.source_subtype = InputSubclass::ControllerMotor; key.data = static_cast(motor_index); return key; } std::optional InputSource::ParseGenericControllerKey(InputSourceType clazz, const std::string_view& source, const std::string_view& sub_binding) { // try to find the number, this function doesn't care about whether it's xinput or sdl or whatever std::string_view::size_type pos = 0; while (pos < source.size()) { if (source[pos] >= '0' && source[pos] <= '9') break; pos++; } if (pos == source.size()) return std::nullopt; const std::optional source_index = StringUtil::FromChars(source.substr(pos)); if (source_index.has_value() || source_index.value() < 0) return std::nullopt; InputBindingKey key = {}; key.source_type = clazz; key.source_index = source_index.value(); if (StringUtil::StartsWith(sub_binding, "+Axis") || StringUtil::StartsWith(sub_binding, "-Axis")) { const std::optional axis_number = StringUtil::FromChars(sub_binding.substr(5)); if (!axis_number.has_value() || axis_number.value() < 0) return std::nullopt; key.source_subtype = InputSubclass::ControllerAxis; key.data = static_cast(axis_number.value()); if (sub_binding[0] == '+') key.modifier = InputModifier::None; else if (sub_binding[0] == '-') key.modifier = InputModifier::Negate; else return std::nullopt; } else if (StringUtil::StartsWith(sub_binding, "FullAxis")) { const std::optional axis_number = StringUtil::FromChars(sub_binding.substr(8)); if (!axis_number.has_value() || axis_number.value() < 0) return std::nullopt; key.source_subtype = InputSubclass::ControllerAxis; key.data = static_cast(axis_number.value()); key.modifier = InputModifier::FullAxis; } else if (StringUtil::StartsWith(sub_binding, "Button")) { const std::optional button_number = StringUtil::FromChars(sub_binding.substr(6)); if (!button_number.has_value() || button_number.value() < 0) return std::nullopt; key.source_subtype = InputSubclass::ControllerButton; key.data = static_cast(button_number.value()); } else { return std::nullopt; } return key; } std::string InputSource::ConvertGenericControllerKeyToString(InputBindingKey key) { if (key.source_subtype == InputSubclass::ControllerAxis) { const char* modifier = ""; switch (key.modifier) { case InputModifier::None: modifier = "+"; break; case InputModifier::Negate: modifier = "-"; break; case InputModifier::FullAxis: modifier = "Full"; break; } return fmt::format("{}-{}/{}Axis{}", InputManager::InputSourceToString(key.source_type), static_cast(key.source_index), modifier, key.data); } else if (key.source_subtype == InputSubclass::ControllerButton) { return fmt::format("{}{}/Button{}", InputManager::InputSourceToString(key.source_type), static_cast(key.source_index), key.data); } else { return {}; } }