From 675559b1ba62d178ee3c615e275ad7bc98986f6b Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Sun, 24 Nov 2024 21:00:17 +0100 Subject: [PATCH] Initial controller support --- src/common/config.cpp | 52 +++++++--- src/input/input_handler.cpp | 199 ++++++++++++++++++++++++++++++------ src/input/input_handler.h | 25 +++-- src/sdl_window.cpp | 110 +++----------------- 4 files changed, 238 insertions(+), 148 deletions(-) diff --git a/src/common/config.cpp b/src/common/config.cpp index a46347b0f..3fe8f3590 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -704,19 +704,21 @@ void setDefaultValues() { constexpr std::string_view GetDefaultKeyboardConfig() { return R"(#Feeling lost? Check out the Help section! +#Keyboard bindings + triangle = f circle = space cross = e square = r -up = w, lalt -up = mousewheelup -down = s, lalt -down = mousewheeldown -left = a, lalt -left = mousewheelleft -right = d, lalt -right = mousewheelright +pad_up = w, lalt +pad_up = mousewheelup +pad_down = s, lalt +pad_down = mousewheeldown +pad_left = a, lalt +pad_left = mousewheelleft +pad_right = d, lalt +pad_right = mousewheelright l1 = rightbutton, lshift r1 = leftbutton @@ -726,21 +728,45 @@ l3 = x r3 = q r3 = middlebutton -key_toggle = i, lalt - options = escape touchpad = g - +key_toggle = i, lalt mouse_to_joystick = right mouse_movement_params = 0.5, 1, 0.125 - leftjoystick_halfmode = lctrl axis_left_x_minus = a axis_left_x_plus = d axis_left_y_minus = w axis_left_y_plus = s + +#Controller bindings + +triangle = triangle +cross = cross +square = square +circle = circle + +l1 = l1 +l2 = l2 +l3 = l3 +r1 = r1 +r2 = r2 +r3 = r3 + +pad_up = pad_up +pad_down = pad_down +pad_left = pad_left +pad_right = pad_right + +options = options + +axis_left_x = axis_left_x +axis_left_y = axis_left_y + +axis_right_x = axis_right_x +axis_right_y = axis_right_y )"; } std::filesystem::path GetFoolproofKbmConfigFile(const std::string& game_id) { @@ -748,7 +774,7 @@ std::filesystem::path GetFoolproofKbmConfigFile(const std::string& game_id) { // If that doesn't exist either, generate that from getDefaultConfig() and try again // If even the folder is missing, we start with that. - const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "kbmConfig"; + const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "inputConfig"; const auto config_file = config_dir / (game_id + ".ini"); const auto default_config_file = config_dir / "default.ini"; diff --git a/src/input/input_handler.cpp b/src/input/input_handler.cpp index fac61ec3b..6da3c0f52 100644 --- a/src/input/input_handler.cpp +++ b/src/input/input_handler.cpp @@ -98,7 +98,62 @@ ControllerOutput output_array[] = { void ToggleMouseEnabled() { mouse_enabled ^= true; } + // parsing related functions +u32 GetAxisInputId(AxisMapping a) { + //LOG_INFO(Input, "Parsing an axis..."); + if (a.axis == Axis::AxisMax || a.value != 0) { + LOG_ERROR(Input, "Invalid axis given!"); + return 0; + } + u32 value = (u32)a.axis + 0x80000000; + LOG_DEBUG(Input, "Listening to {0:X}", value); + return value; +} + +u32 GetOrbisToSdlButtonKeycode(u32 cbutton) { + switch (cbutton) { + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_CIRCLE: + return SDL_GAMEPAD_BUTTON_EAST; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TRIANGLE: + return SDL_GAMEPAD_BUTTON_NORTH; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_SQUARE: + return SDL_GAMEPAD_BUTTON_WEST; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_CROSS: + return SDL_GAMEPAD_BUTTON_SOUTH; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_L1: + return SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_R1: + return SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_L3: + return SDL_GAMEPAD_BUTTON_LEFT_STICK; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_R3: + return SDL_GAMEPAD_BUTTON_RIGHT_STICK; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_UP: + return SDL_GAMEPAD_BUTTON_DPAD_UP; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_DOWN: + return SDL_GAMEPAD_BUTTON_DPAD_DOWN; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_LEFT: + return SDL_GAMEPAD_BUTTON_DPAD_LEFT; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_RIGHT: + return SDL_GAMEPAD_BUTTON_DPAD_RIGHT; + case OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_OPTIONS: + return SDL_GAMEPAD_BUTTON_START; + + default: + return ((u32)-1) - 0x10000000; + } +} +u32 GetControllerButtonInputId(u32 cbutton) { + if((cbutton & (OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD | + LEFTJOYSTICK_HALFMODE | + RIGHTJOYSTICK_HALFMODE)) != 0) { + //LOG_ERROR(Input, "You can't use this as a button input!"); + return (u32)-1; + } + return GetOrbisToSdlButtonKeycode(cbutton) + 0x10000000; +} + // syntax: 'name, name,name' or 'name,name' or 'name' InputBinding GetBindingFromString(std::string& line) { @@ -113,21 +168,41 @@ InputBinding GetBindingFromString(std::string& line) { tokens.push_back(token); } - // Check for invalid tokens and map valid ones to keys + // Check and process tokens for (const auto& t : tokens) { - if (string_to_keyboard_key_map.find(t) == string_to_keyboard_key_map.end()) { - return InputBinding(0, 0, 0); // Skip by setting all keys to 0 + if (string_to_keyboard_key_map.find(t) != string_to_keyboard_key_map.end()) { + // Map to keyboard key + u32 key_id = string_to_keyboard_key_map.at(t); + if (!key1) key1 = key_id; + else if (!key2) key2 = key_id; + else if (!key3) key3 = key_id; + } + else if (string_to_axis_map.find(t) != string_to_axis_map.end()) { + // Map to axis input ID + u32 axis_id = GetAxisInputId(string_to_axis_map.at(t)); + if (axis_id == (u32)-1) { + return InputBinding(0, 0, 0); + } + if (!key1) key1 = axis_id; + else if (!key2) key2 = axis_id; + else if (!key3) key3 = axis_id; + } + else if (string_to_cbutton_map.find(t) != string_to_cbutton_map.end()) { + // Map to controller button input ID + u32 cbutton_id = GetControllerButtonInputId(string_to_cbutton_map.at(t)); + if (cbutton_id == (u32)-1) { + return InputBinding(0, 0, 0); + } + if (!key1) key1 = cbutton_id; + else if (!key2) key2 = cbutton_id; + else if (!key3) key3 = cbutton_id; + } + else { + // Invalid token found; return default binding + return InputBinding(0, 0, 0); } } - // Assign values to keys if all tokens were valid - if (tokens.size() > 0) - key1 = string_to_keyboard_key_map.at(tokens[0]); - if (tokens.size() > 1) - key2 = string_to_keyboard_key_map.at(tokens[1]); - if (tokens.size() > 2) - key3 = string_to_keyboard_key_map.at(tokens[2]); - return InputBinding(key1, key2, key3); } @@ -176,8 +251,8 @@ void ParseInputConfig(const std::string game_id = "") { // Split the line by '=' std::size_t equal_pos = line.find('='); if (equal_pos == std::string::npos) { - LOG_ERROR(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, - line); + LOG_WARNING(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", + lineCount, line); continue; } @@ -185,7 +260,6 @@ void ParseInputConfig(const std::string game_id = "") { std::string input_string = line.substr(equal_pos + 1); std::size_t comma_pos = input_string.find(','); - // special check for mouse to joystick input if (output_string == "mouse_to_joystick") { if (input_string == "left") { mouse_joystick_binding = 1; @@ -196,13 +270,12 @@ void ParseInputConfig(const std::string game_id = "") { } continue; } - // key toggle if (output_string == "key_toggle") { if (comma_pos != std::string::npos) { // handle key-to-key toggling (separate list?) InputBinding toggle_keys = GetBindingFromString(input_string); if (toggle_keys.KeyCount() != 2) { - LOG_ERROR(Input, + LOG_WARNING(Input, "Syntax error: Please provide exactly 2 keys: " "first is the toggler, the second is the key to toggle: {}", line); @@ -214,7 +287,7 @@ void ParseInputConfig(const std::string game_id = "") { connections.insert(connections.end(), toggle_connection); continue; } - LOG_ERROR(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, + LOG_WARNING(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, line); continue; } @@ -225,12 +298,8 @@ void ParseInputConfig(const std::string game_id = "") { // Check for invalid input (in case there's an unexpected format) if (ss.fail()) { - LOG_ERROR(Input, "Failed to parse mouse movement parameters from line: {}", line); - } else { - // LOG_DEBUG(Input, "Mouse movement parameters parsed: {} {} {}", - // mouse_deadzone_offset, mouse_speed, mouse_speed_offset); + LOG_WARNING(Input, "Failed to parse mouse movement parameters from line: {}", line); } - continue; } @@ -241,7 +310,7 @@ void ParseInputConfig(const std::string game_id = "") { auto axis_it = string_to_axis_map.find(output_string); if (binding.IsEmpty()) { - LOG_DEBUG(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, + LOG_WARNING(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, line); continue; } @@ -251,12 +320,15 @@ void ParseInputConfig(const std::string game_id = "") { connections.insert(connections.end(), connection); } else if (axis_it != string_to_axis_map.end()) { + int value_to_set = (binding.key3 & 0x80000000) != 0 ? 0 : + (axis_it->second.axis == Axis::TriggerLeft || axis_it->second.axis == Axis::TriggerRight) ? + 127 : axis_it->second.value; connection = BindingConnection( binding, GetOutputPointer(ControllerOutput(0, axis_it->second.axis)), - axis_it->second.value); + value_to_set); connections.insert(connections.end(), connection); } else { - LOG_DEBUG(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, + LOG_WARNING(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, line); continue; } @@ -270,7 +342,7 @@ void ParseInputConfig(const std::string game_id = "") { u32 GetMouseWheelEvent(const SDL_Event& event) { if (event.type != SDL_EVENT_MOUSE_WHEEL && event.type != SDL_EVENT_MOUSE_WHEEL_OFF) { LOG_DEBUG(Input, "Something went wrong with wheel input parsing!"); - return 0; + return (u32)-1; } if (event.wheel.y > 0) { return SDL_MOUSE_WHEEL_UP; @@ -285,6 +357,7 @@ u32 GetMouseWheelEvent(const SDL_Event& event) { } u32 InputBinding::GetInputIDFromEvent(const SDL_Event& e) { + int value_mask; switch (e.type) { case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: @@ -295,6 +368,15 @@ u32 InputBinding::GetInputIDFromEvent(const SDL_Event& e) { case SDL_EVENT_MOUSE_WHEEL: case SDL_EVENT_MOUSE_WHEEL_OFF: return GetMouseWheelEvent(e); + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_BUTTON_UP: + return (u32)e.gbutton.button + 0x10000000; // I believe this range is unused + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + // todo: somehow put this value into the correct connection + // solution 1: add it to the keycode as a 0x0FF00000 (a bit hacky but works I guess?) + // I guess in software developement, there really is nothing more permanent than a temporary solution + value_mask = (u32)((e.gaxis.value / 256 + 128) << 20); // +-32000 to +-128 to 0-255 + return (u32)e.gaxis.axis + 0x80000000 + value_mask; // they are pushed to the end of the sorted array default: return (u32)-1; } @@ -306,6 +388,10 @@ void ControllerOutput::SetControllerOutputController(GameController* c) { } void ToggleKeyInList(u32 key) { + if ((key & 0x80000000) != 0) { + LOG_ERROR(Input, "Toggling analog inputs is not supported!"); + return; + } auto it = std::find(toggled_keys.begin(), toggled_keys.end(), key); if (it == toggled_keys.end()) { toggled_keys.insert(toggled_keys.end(), key); @@ -327,13 +413,16 @@ void ControllerOutput::AddUpdate(bool pressed, u32 param) { new_button_state |= pressed; new_param = param; } else if (axis != Axis::AxisMax) { - float multiplier = 1.0; switch (axis) { case Axis::TriggerLeft: case Axis::TriggerRight: + // if it's a button input, then we know the value to set, so the param is 0. + // if it's an analog input, then the param isn't 0 + // warning: doesn't work yet new_param = SDL_clamp((pressed ? (s32)param : 0) + new_param, 0, 127); break; default: + // todo: do the same as above new_param = SDL_clamp((pressed ? (s32)param : 0) + new_param, -127, 127); break; } @@ -401,6 +490,28 @@ void ControllerOutput::FinalizeUpdate() { // Updates the list of pressed keys with the given input. // Returns whether the list was updated or not. bool UpdatePressedKeys(u32 value, bool is_pressed) { + // Skip invalid inputs + if (value == (u32)-1) { + return false; + } + if ((value & 0x80000000) != 0) { + // analog input, it gets added when it first sends an event, + // and from there, it only changes the parameter + // reverse iterate until we get out of the 0x8000000 range, if found, + // update the parameter, if not, add it to the end + //LOG_DEBUG(Input, "Updating an analog input..."); + u32 value_to_search = value & 0xF00FFFFF; + for (auto& it = --pressed_keys.end(); (it->first & 0x80000000) != 0; it--) { + if ((it->first & 0xF00FFFFF) == value_to_search) { + it->first = value; + LOG_DEBUG(Input, "New value for {:X}: {:x}", value, value); + return true; + } + } + //LOG_DEBUG(Input, "Input activated for the first time, adding it to the list"); + pressed_keys.insert(pressed_keys.end(), {value, false}); + return true; + } if (is_pressed) { // Find the correct position for insertion to maintain order auto it = @@ -425,9 +536,11 @@ bool UpdatePressedKeys(u32 value, bool is_pressed) { return false; } // Check if a given binding's all keys are currently active. -bool IsInputActive(const InputBinding& i) { - // Extract keys from InputBinding and ignore unused (0) or virtually pressed keys - std::list input_keys = {i.key1, i.key2, i.key3}; +// For now it also extracts the analog inputs' parameters. +bool IsInputActive(BindingConnection& connection) { + InputBinding i = connection.binding; + // Extract keys from InputBinding and ignore unused (0) or toggled keys + std::list input_keys = {i.key1, i.key2, i.key3}; input_keys.remove(0); for (auto key = input_keys.begin(); key != input_keys.end();) { if (std::find(toggled_keys.begin(), toggled_keys.end(), *key) != toggled_keys.end()) { @@ -436,20 +549,23 @@ bool IsInputActive(const InputBinding& i) { ++key; // Increment only if no erase happened } } + if (input_keys.empty()) { + LOG_DEBUG(Input, "No actual inputs to check, returning true"); + return true; + } // Iterator for pressed_keys, starting from the beginning auto pressed_it = pressed_keys.begin(); - auto pressed_end = pressed_keys.end(); // Store pointers to flags in pressed_keys that need to be set if all keys are active std::list flags_to_set; // Check if all keys in input_keys are active - for (uint32_t key : input_keys) { + for (u32 key : input_keys) { bool key_found = false; // Search for the current key in pressed_keys starting from the last checked position - while (pressed_it != pressed_end && pressed_it->first <= key) { + while (pressed_it != pressed_keys.end() && (pressed_it->first & 0x80000000) == 0) { if (pressed_it->first == key) { key_found = true; @@ -460,6 +576,20 @@ bool IsInputActive(const InputBinding& i) { } ++pressed_it; } + if (!key_found && (key & 0x80000000) != 0) { + // reverse iterate over the analog inputs, as they can't be sorted + auto& rev_it = --pressed_keys.end(); + for (auto rev_it = --pressed_keys.end(); (rev_it->first & 0x80000000) != 0; rev_it--) { + if ((rev_it->first & 0xF00FFFFF) == (key & 0xF00FFFFF)) { + connection.parameter = (u32)((s32)((rev_it->first & 0x0FF00000) >> 20) - 128); + LOG_DEBUG(Input, "Extracted the following param: {:X} from {:X}", + (s32)connection.parameter, rev_it->first); + key_found = true; + flags_to_set.push_back(&rev_it->second); + break; + } + } + } if (!key_found) { return false; } @@ -493,7 +623,8 @@ void ActivateOutputsFromInputs() { it.ResetUpdate(); } for (auto& it : connections) { - it.output->AddUpdate(IsInputActive(it.binding), it.parameter); + bool active = IsInputActive(it); + it.output->AddUpdate(active, it.parameter); } for (auto& it : output_array) { it.FinalizeUpdate(); diff --git a/src/input/input_handler.h b/src/input/input_handler.h index a7ea5514f..c80ec0392 100644 --- a/src/input/input_handler.h +++ b/src/input/input_handler.h @@ -49,12 +49,14 @@ const std::map string_to_cbutton_map = { {"r1", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_R1}, {"l3", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_L3}, {"r3", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_R3}, + {"pad_up", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_UP}, + {"pad_down", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_DOWN}, + {"pad_left", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_LEFT}, + {"pad_right", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_RIGHT}, {"options", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_OPTIONS}, + + // these are outputs only (touchpad can only be bound to itself) {"touchpad", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD}, - {"up", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_UP}, - {"down", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_DOWN}, - {"left", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_LEFT}, - {"right", OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_RIGHT}, {"leftjoystick_halfmode", LEFTJOYSTICK_HALFMODE}, {"rightjoystick_halfmode", RIGHTJOYSTICK_HALFMODE}, }; @@ -67,8 +69,15 @@ const std::map string_to_axis_map = { {"axis_right_x_minus", {Input::Axis::RightX, -127}}, {"axis_right_y_plus", {Input::Axis::RightY, 127}}, {"axis_right_y_minus", {Input::Axis::RightY, -127}}, - {"l2", {Axis::TriggerLeft, 127}}, - {"r2", {Axis::TriggerRight, 127}}, + + {"l2", {Axis::TriggerLeft, 0}}, + {"r2", {Axis::TriggerRight, 0}}, + + // should only use these to bind analog inputs to analog outputs + {"axis_left_x", {Input::Axis::LeftX, 0}}, + {"axis_left_y", {Input::Axis::LeftY, 0}}, + {"axis_right_x", {Input::Axis::RightX, 0}}, + {"axis_right_y", {Input::Axis::RightY, 0}}, }; const std::map string_to_keyboard_key_map = { {"a", SDLK_A}, @@ -248,8 +257,8 @@ public: inline bool IsEmpty() { return key1 == 0 && key2 == 0 && key3 == 0; } - std::string ToString() const { - return fmt::format("({}, {}, {})", key1, key2, key3); + std::string ToString() { + return fmt::format("({:X}, {:X}, {:X})", key1, key2, key3); } // returns a u32 based on the event type (keyboard, mouse buttons, or wheel) diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index a38bf60ad..29727449e 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -116,14 +116,20 @@ void WindowSDL::waitEvent() { case SDL_EVENT_KEY_UP: OnKeyboardMouseInput(&event); break; - case SDL_EVENT_GAMEPAD_BUTTON_DOWN: - case SDL_EVENT_GAMEPAD_BUTTON_UP: - case SDL_EVENT_GAMEPAD_AXIS_MOTION: case SDL_EVENT_GAMEPAD_ADDED: case SDL_EVENT_GAMEPAD_REMOVED: + controller->TryOpenSDLController(); + break; case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: + controller->SetTouchpadState(event.gtouchpad.finger, + event.type != SDL_EVENT_GAMEPAD_TOUCHPAD_UP, + event.gtouchpad.x, event.gtouchpad.y); + break; + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_BUTTON_UP: + case SDL_EVENT_GAMEPAD_AXIS_MOTION: OnGamepadEvent(&event); break; case SDL_EVENT_QUIT: @@ -205,99 +211,17 @@ void WindowSDL::OnKeyboardMouseInput(const SDL_Event* event) { } void WindowSDL::OnGamepadEvent(const SDL_Event* event) { - using Libraries::Pad::OrbisPadButtonDataOffset; - u32 button = 0; - Input::Axis axis = Input::Axis::AxisMax; - switch (event->type) { - case SDL_EVENT_GAMEPAD_ADDED: - case SDL_EVENT_GAMEPAD_REMOVED: - controller->TryOpenSDLController(); - break; - case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: - case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: - case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: - controller->SetTouchpadState(event->gtouchpad.finger, - event->type != SDL_EVENT_GAMEPAD_TOUCHPAD_UP, - event->gtouchpad.x, event->gtouchpad.y); - break; - case SDL_EVENT_GAMEPAD_BUTTON_DOWN: - case SDL_EVENT_GAMEPAD_BUTTON_UP: - button = sdlGamepadToOrbisButton(event->gbutton.button); - if (button != 0) { - if (event->gbutton.button == SDL_GAMEPAD_BUTTON_BACK) { - std::string backButtonBehavior = Config::getBackButtonBehavior(); - if (backButtonBehavior != "none") { - float x = backButtonBehavior == "left" - ? 0.25f - : (backButtonBehavior == "right" ? 0.75f : 0.5f); - // trigger a touchpad event so that the touchpad emulation for back button works - controller->SetTouchpadState(0, true, x, 0.5f); - controller->CheckButton(0, button, - event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); - } - } else { - controller->CheckButton(0, button, event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); - } - } - break; - case SDL_EVENT_GAMEPAD_AXIS_MOTION: - axis = event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFTX ? Input::Axis::LeftX - : event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFTY ? Input::Axis::LeftY - : event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTX ? Input::Axis::RightX - : event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHTY ? Input::Axis::RightY - : event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER ? Input::Axis::TriggerLeft - : event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER ? Input::Axis::TriggerRight - : Input::Axis::AxisMax; - if (axis != Input::Axis::AxisMax) { - if (event->gaxis.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER || - event->gaxis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) { - controller->Axis(0, axis, Input::GetAxis(0, 0x8000, event->gaxis.value)); + bool input_down = event->type == SDL_EVENT_GAMEPAD_AXIS_MOTION || + event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || + event->type == SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN || + event->type == SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION; + u32 input_id = Input::InputBinding::GetInputIDFromEvent(*event); - } else { - controller->Axis(0, axis, Input::GetAxis(-0x8000, 0x8000, event->gaxis.value)); - } - } - break; - } -} + bool inputs_changed = Input::UpdatePressedKeys(input_id, input_down); -int WindowSDL::sdlGamepadToOrbisButton(u8 button) { - using Libraries::Pad::OrbisPadButtonDataOffset; - - switch (button) { - case SDL_GAMEPAD_BUTTON_DPAD_DOWN: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_DOWN; - case SDL_GAMEPAD_BUTTON_DPAD_UP: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_UP; - case SDL_GAMEPAD_BUTTON_DPAD_LEFT: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_LEFT; - case SDL_GAMEPAD_BUTTON_DPAD_RIGHT: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_RIGHT; - case SDL_GAMEPAD_BUTTON_SOUTH: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_CROSS; - case SDL_GAMEPAD_BUTTON_NORTH: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TRIANGLE; - case SDL_GAMEPAD_BUTTON_WEST: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_SQUARE; - case SDL_GAMEPAD_BUTTON_EAST: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_CIRCLE; - case SDL_GAMEPAD_BUTTON_START: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_OPTIONS; - case SDL_GAMEPAD_BUTTON_TOUCHPAD: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD; - case SDL_GAMEPAD_BUTTON_BACK: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD; - case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_L1; - case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_R1; - case SDL_GAMEPAD_BUTTON_LEFT_STICK: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_L3; - case SDL_GAMEPAD_BUTTON_RIGHT_STICK: - return OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_R3; - default: - return 0; + if (inputs_changed) { + Input::ActivateOutputsFromInputs(); } }