From 1ecd8596475cbe3b7cc0143104424d1ef9026390 Mon Sep 17 00:00:00 2001 From: TheLastRar Date: Sun, 9 Mar 2025 20:17:29 +0000 Subject: [PATCH] SDLInputSource: Support auto mapping pressure sense buttons Also provide UI strings and icons --- pcsx2/Input/SDLInputSource.cpp | 142 ++++++++++++++++++++++++++++++--- pcsx2/Input/SDLInputSource.h | 2 + 2 files changed, 132 insertions(+), 12 deletions(-) diff --git a/pcsx2/Input/SDLInputSource.cpp b/pcsx2/Input/SDLInputSource.cpp index c6b6c7e105..69e78f7a02 100644 --- a/pcsx2/Input/SDLInputSource.cpp +++ b/pcsx2/Input/SDLInputSource.cpp @@ -58,6 +58,25 @@ static const char* const* s_sdl_trigger_names_list[] = { // Switch }; +static constexpr const char* s_sdl_ps3_sxs_pressure_names[] = { + nullptr, // JoyAxis0 + nullptr, // JoyAxis1 + nullptr, // JoyAxis2 + nullptr, // JoyAxis3 + nullptr, // JoyAxis4 + nullptr, // JoyAxis5 + "Cross (Pressure)", // JoyAxis6 + "Circle (Pressure)", // JoyAxis7 + "Square (Pressure)", // JoyAxis8 + "Triangle (Pressure)", // JoyAxis9 + "L1 (Pressure)", // JoyAxis10 + "R1 (Pressure)", // JoyAxis11 + "D-Pad Up (Pressure)", // JoyAxis12 + "D-Pad Down (Pressure)", // JoyAxis13 + "D-Pad Left (Pressure)", // JoyAxis14 + "D-Pad Right (Pressure)", // JoyAxis15 +}; + static constexpr const char* s_sdl_axis_icons[][2] = { {ICON_PF_LEFT_ANALOG_LEFT, ICON_PF_LEFT_ANALOG_RIGHT}, // SDL_GAMEPAD_AXIS_LEFTX {ICON_PF_LEFT_ANALOG_UP, ICON_PF_LEFT_ANALOG_DOWN}, // SDL_GAMEPAD_AXIS_LEFTY @@ -85,6 +104,25 @@ static const char* const* s_sdl_trigger_icons_list[] = { // Switch }; +static constexpr const char* s_sdl_ps3_pressure_icons[] = { + nullptr, // JoyAxis0 + nullptr, // JoyAxis1 + nullptr, // JoyAxis2 + nullptr, // JoyAxis3 + nullptr, // JoyAxis4 + nullptr, // JoyAxis5 + "P" ICON_PF_BUTTON_CROSS, // JoyAxis6 + "P" ICON_PF_BUTTON_CIRCLE, // JoyAxis7 + "P" ICON_PF_BUTTON_SQUARE, // JoyAxis8 + "P" ICON_PF_BUTTON_TRIANGLE, // JoyAxis9 + "P" ICON_PF_LEFT_SHOULDER_L1, // JoyAxis10 + "P" ICON_PF_RIGHT_SHOULDER_R1, // JoyAxis11 + "P" ICON_PF_DPAD_UP, // JoyAxis12 + "P" ICON_PF_DPAD_DOWN, // JoyAxis13 + "P" ICON_PF_DPAD_LEFT, // JoyAxis14 + "P" ICON_PF_DPAD_RIGHT, // JoyAxis15 +}; + static constexpr const GenericInputBinding s_sdl_generic_binding_axis_mapping[][2] = { {GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // SDL_GAMEPAD_AXIS_LEFTX {GenericInputBinding::LeftStickUp, GenericInputBinding::LeftStickDown}, // SDL_GAMEPAD_AXIS_LEFTY @@ -93,6 +131,24 @@ static constexpr const GenericInputBinding s_sdl_generic_binding_axis_mapping[][ {GenericInputBinding::Unknown, GenericInputBinding::L2}, // SDL_GAMEPAD_AXIS_LEFT_TRIGGER {GenericInputBinding::Unknown, GenericInputBinding::R2}, // SDL_GAMEPAD_AXIS_RIGHT_TRIGGER }; +static constexpr const GenericInputBinding s_sdl_ps3_binding_pressure_mapping[] = { + GenericInputBinding::Unknown, // JoyAxis0 + GenericInputBinding::Unknown, // JoyAxis1 + GenericInputBinding::Unknown, // JoyAxis2 + GenericInputBinding::Unknown, // JoyAxis3 + GenericInputBinding::Unknown, // JoyAxis4 + GenericInputBinding::Unknown, // JoyAxis5 + GenericInputBinding::Cross, // JoyAxis6 + GenericInputBinding::Circle, // JoyAxis7 + GenericInputBinding::Square, // JoyAxis8 + GenericInputBinding::Triangle, // JoyAxis9 + GenericInputBinding::L1, // JoyAxis10 + GenericInputBinding::R1, // JoyAxis11 + GenericInputBinding::DPadUp, // JoyAxis12 + GenericInputBinding::DPadDown, // JoyAxis13 + GenericInputBinding::DPadLeft, // JoyAxis14 + GenericInputBinding::DPadRight, // JoyAxis15 +}; static constexpr const char* s_sdl_button_setting_names[] = { "FaceSouth", // SDL_GAMEPAD_BUTTON_SOUTH @@ -263,7 +319,7 @@ static constexpr const char* s_sdl_button_ps3_icons[] = { ICON_PF_BUTTON_SQUARE, // SDL_GAMEPAD_BUTTON_WEST ICON_PF_BUTTON_TRIANGLE, // SDL_GAMEPAD_BUTTON_NORTH ICON_PF_SELECT_SHARE, // SDL_GAMEPAD_BUTTON_BACK - ICON_PF_XBOX, // SDL_GAMEPAD_BUTTON_GUIDE + ICON_PF_PLAYSTATION, // SDL_GAMEPAD_BUTTON_GUIDE ICON_PF_START, // SDL_GAMEPAD_BUTTON_START ICON_PF_LEFT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_LEFT_STICK ICON_PF_RIGHT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_RIGHT_STICK @@ -358,12 +414,17 @@ static constexpr const GenericInputBinding s_sdl_generic_binding_button_mapping[ GenericInputBinding::DPadDown, // SDL_GAMEPAD_BUTTON_DPAD_DOWN GenericInputBinding::DPadLeft, // SDL_GAMEPAD_BUTTON_DPAD_LEFT GenericInputBinding::DPadRight, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT - GenericInputBinding::Unknown, // SDL_GAMEPAD_BUTTON_MISC1 - GenericInputBinding::Unknown, // SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1 - GenericInputBinding::Unknown, // SDL_GAMEPAD_BUTTON_LEFT_PADDLE1 - GenericInputBinding::Unknown, // SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2 - GenericInputBinding::Unknown, // SDL_GAMEPAD_BUTTON_LEFT_PADDLE2 - GenericInputBinding::Unknown, // SDL_GAMEPAD_BUTTON_TOUCHPAD +}; +static constexpr const GenericInputBinding s_sdl_ps3_binding_button_mapping[] = { + GenericInputBinding::Unknown, // SDL_GAMEPAD_BUTTON_SOUTH + GenericInputBinding::Unknown, // SDL_GAMEPAD_BUTTON_EAST + GenericInputBinding::Unknown, // SDL_GAMEPAD_BUTTON_WEST + GenericInputBinding::Unknown, // SDL_GAMEPAD_BUTTON_NORTH + GenericInputBinding::Select, // SDL_GAMEPAD_BUTTON_BACK + GenericInputBinding::System, // SDL_GAMEPAD_BUTTON_GUIDE + GenericInputBinding::Start, // SDL_GAMEPAD_BUTTON_START + GenericInputBinding::L3, // SDL_GAMEPAD_BUTTON_LEFT_STICK + GenericInputBinding::R3, // SDL_GAMEPAD_BUTTON_RIGHT_STICK }; static constexpr const char* s_sdl_hat_direction_names[] = { @@ -909,7 +970,21 @@ TinyString SDLInputSource::ConvertKeyToString(InputBindingKey key, bool display, ret.format("SDL-{} {}", static_cast(key.source_index), s_sdl_trigger_names[trigger_index]); } else - ret.format("SDL-{} {}Axis {}{}", static_cast(key.source_index), modifier, key.data - std::size(s_sdl_axis_setting_names) + 1, key.invert ? "~" : ""); + { + bool is_sixaxis = false; + if (it != m_controllers.end()) + is_sixaxis = IsControllerSixaxis(*it); + + const int joy_axis_Index = key.data - std::size(s_sdl_axis_setting_names); + + if (is_sixaxis && key.modifier == InputModifier::FullAxis && key.invert == false && + joy_axis_Index < std::size(s_sdl_ps3_sxs_pressure_names) && s_sdl_ps3_sxs_pressure_names[joy_axis_Index] != nullptr) + { + ret.format("SDL-{} {}", static_cast(key.source_index), s_sdl_ps3_sxs_pressure_names[joy_axis_Index]); + } + else + ret.format("SDL-{} {}Axis {}{}", static_cast(key.source_index), modifier, joy_axis_Index + 1, key.invert ? "~" : ""); + } } else { @@ -1019,6 +1094,13 @@ TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key) ret.format("SDL-{} {}", static_cast(key.source_index), s_sdl_trigger_icons[trigger_index]); } } + else if (it != m_controllers.end() && IsControllerSixaxis(*it) && key.invert == false) + { + const int joy_axis_Index = key.data - std::size(s_sdl_axis_setting_names); + + if (joy_axis_Index < std::size(s_sdl_ps3_pressure_icons) && s_sdl_ps3_pressure_icons[joy_axis_Index] != nullptr) + ret.format("SDL-{} {}", static_cast(key.source_index), s_sdl_ps3_pressure_icons[joy_axis_Index]); + } } else if (key.source_subtype == InputSubclass::ControllerButton) { @@ -1497,11 +1579,34 @@ bool SDLInputSource::GetGenericBindingMapping(const std::string_view device, Inp if (positive != GenericInputBinding::Unknown) mapping->emplace_back(positive, fmt::format("SDL-{}/+{}", pid, s_sdl_axis_setting_names[i])); } - for (u32 i = 0; i < std::size(s_sdl_generic_binding_button_mapping); i++) + + if (IsControllerSixaxis(*it)) { - const GenericInputBinding binding = s_sdl_generic_binding_button_mapping[i]; - if (binding != GenericInputBinding::Unknown) - mapping->emplace_back(binding, fmt::format("SDL-{}/{}", pid, s_sdl_button_setting_names[i])); + // PS3 with pressure sensitive support + for (u32 i = 0; i < std::size(s_sdl_ps3_binding_pressure_mapping); i++) + { + const GenericInputBinding binding = s_sdl_ps3_binding_pressure_mapping[i]; + if (binding != GenericInputBinding::Unknown) + mapping->emplace_back(binding, fmt::format("SDL-{}/FullJoyAxis{}", pid, i)); + } + + // PS3 non pressure sensitive buttons + for (u32 i = 0; i < std::size(s_sdl_ps3_binding_button_mapping); i++) + { + const GenericInputBinding binding = s_sdl_ps3_binding_button_mapping[i]; + if (binding != GenericInputBinding::Unknown) + mapping->emplace_back(binding, fmt::format("SDL-{}/{}", pid, s_sdl_button_setting_names[i])); + } + } + else + { + // Standard buttons + for (u32 i = 0; i < std::size(s_sdl_generic_binding_button_mapping); i++) + { + const GenericInputBinding binding = s_sdl_generic_binding_button_mapping[i]; + if (binding != GenericInputBinding::Unknown) + mapping->emplace_back(binding, fmt::format("SDL-{}/{}", pid, s_sdl_button_setting_names[i])); + } } if (it->use_gamepad_rumble || it->haptic_left_right_effect) @@ -1594,3 +1699,16 @@ void SDLInputSource::SendRumbleUpdate(ControllerData* cd) SDL_StopHapticRumble(cd->haptic); } } + +bool SDLInputSource::IsControllerSixaxis(const ControllerData& cd) +{ + const SDL_GamepadType type = SDL_GetRealGamepadType(cd.gamepad); + + // We check the number of buttons to exclude DsHidMini's SDF mode (which has 17 buttons??) + // SDF's input layout differs from the sixaxis or linux drivers, we only support the latter layout. + // This differing layout also isn't mapped correctly in SDL, I think due to how L2/R2 are exposed. + // Also see SetHints regarding reading the pressure sense from DsHidMini's SDF mode. + return type == SDL_GAMEPAD_TYPE_PS3 && + SDL_GetNumJoystickAxes(cd.joystick) == 16 && + SDL_GetNumJoystickButtons(cd.joystick) == 11; +} diff --git a/pcsx2/Input/SDLInputSource.h b/pcsx2/Input/SDLInputSource.h index 1085327eae..a2d379d2b2 100644 --- a/pcsx2/Input/SDLInputSource.h +++ b/pcsx2/Input/SDLInputSource.h @@ -87,6 +87,8 @@ private: bool HandleJoystickHatEvent(const SDL_JoyHatEvent* ev); void SendRumbleUpdate(ControllerData* cd); + bool IsControllerSixaxis(const ControllerData& cd); + ControllerDataVector m_controllers; // ConvertKeyToString and ConvertKeyToIcon can inspect the