From 93c21103aaf8c7a9c100c9385f2daa9b04a6207f Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 13 Aug 2024 02:08:25 +0200 Subject: [PATCH] xinput: allow to map triggers as positive or negative --- rpcs3/Emu/Io/PadHandler.h | 2 ++ rpcs3/Input/xinput_pad_handler.cpp | 41 +++++++++++++++++++++------ rpcs3/Input/xinput_pad_handler.h | 9 ++++-- rpcs3/rpcs3qt/pad_settings_dialog.cpp | 3 ++ rpcs3/rpcs3qt/tooltips.h | 2 +- 5 files changed, 46 insertions(+), 11 deletions(-) diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index b5ac7c6186..ee0b66bd0d 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -121,6 +121,7 @@ protected: usz m_max_devices = 0; u32 m_trigger_threshold = 0; u32 m_thumb_threshold = 0; + bool m_triggers_as_sticks_only = false; bool b_has_led = false; bool b_has_rgb = false; @@ -281,6 +282,7 @@ public: u16 NormalizeStickInput(u16 raw_value, s32 threshold, s32 multiplier, bool ignore_threshold = false) const; void convert_stick_values(u16& x_out, u16& y_out, s32 x_in, s32 y_in, u32 deadzone, u32 anti_deadzone, u32 padsquircling) const; + void set_triggers_as_sticks_only(bool enabled) { m_triggers_as_sticks_only = enabled; } virtual bool Init() { return true; } PadHandlerBase(pad_handler type = pad_handler::null); diff --git a/rpcs3/Input/xinput_pad_handler.cpp b/rpcs3/Input/xinput_pad_handler.cpp index 5850461116..3929d860df 100644 --- a/rpcs3/Input/xinput_pad_handler.cpp +++ b/rpcs3/Input/xinput_pad_handler.cpp @@ -37,6 +37,10 @@ xinput_pad_handler::xinput_pad_handler() : PadHandlerBase(pad_handler::xinput) { XInputKeyCodes::Guide, "Guide" }, { XInputKeyCodes::LT, "LT" }, { XInputKeyCodes::RT, "RT" }, + { XInputKeyCodes::LT_Pos, "LT+" }, + { XInputKeyCodes::LT_Neg, "LT-" }, + { XInputKeyCodes::RT_Pos, "RT+" }, + { XInputKeyCodes::RT_Neg, "RT-" }, { XInputKeyCodes::LSXNeg, "LS X-" }, { XInputKeyCodes::LSXPos, "LS X+" }, { XInputKeyCodes::LSYPos, "LS Y+" }, @@ -207,19 +211,31 @@ std::unordered_map xinput_pad_handler::get_button_values(const std::sh // Try SCP first, if it fails for that pad then try normal XInput if (dev->is_scp_device) { - return get_button_values_scp(dev->state_scp); + return get_button_values_scp(dev->state_scp, m_triggers_as_sticks_only); } - return get_button_values_base(dev->state_base); + return get_button_values_base(dev->state_base, m_triggers_as_sticks_only); } -xinput_pad_handler::PadButtonValues xinput_pad_handler::get_button_values_base(const XINPUT_STATE& state) +xinput_pad_handler::PadButtonValues xinput_pad_handler::get_button_values_base(const XINPUT_STATE& state, bool triggers_as_sticks_only) { PadButtonValues values; // Triggers - values[XInputKeyCodes::LT] = state.Gamepad.bLeftTrigger; - values[XInputKeyCodes::RT] = state.Gamepad.bRightTrigger; + if (!triggers_as_sticks_only) + { + values[XInputKeyCodes::LT] = state.Gamepad.bLeftTrigger; + values[XInputKeyCodes::RT] = state.Gamepad.bRightTrigger; + } + + const float lTrigger = state.Gamepad.bLeftTrigger / 255.0f; + const float rTrigger = state.Gamepad.bRightTrigger / 255.0f; + + values[XInputKeyCodes::LT_Pos] = static_cast(lTrigger > 0.5f ? std::clamp((lTrigger - 0.5f) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f); + values[XInputKeyCodes::LT_Neg] = static_cast(lTrigger < 0.5f ? std::clamp((0.5f - lTrigger) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f); + + values[XInputKeyCodes::RT_Pos] = static_cast(rTrigger > 0.5f ? std::clamp((rTrigger - 0.5f) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f); + values[XInputKeyCodes::RT_Neg] = static_cast(rTrigger < 0.5f ? std::clamp((0.5f - rTrigger) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f); // Sticks const int lx = state.Gamepad.sThumbLX; @@ -272,13 +288,22 @@ xinput_pad_handler::PadButtonValues xinput_pad_handler::get_button_values_base(c return values; } -xinput_pad_handler::PadButtonValues xinput_pad_handler::get_button_values_scp(const SCP_EXTN& state) +xinput_pad_handler::PadButtonValues xinput_pad_handler::get_button_values_scp(const SCP_EXTN& state, bool triggers_as_sticks_only) { PadButtonValues values; // Triggers - values[xinput_pad_handler::XInputKeyCodes::LT] = static_cast(state.SCP_L2 * 255.0f); - values[xinput_pad_handler::XInputKeyCodes::RT] = static_cast(state.SCP_R2 * 255.0f); + if (!triggers_as_sticks_only) + { + values[xinput_pad_handler::XInputKeyCodes::LT] = static_cast(state.SCP_L2 * 255.0f); + values[xinput_pad_handler::XInputKeyCodes::RT] = static_cast(state.SCP_R2 * 255.0f); + } + + values[XInputKeyCodes::LT_Pos] = static_cast(state.SCP_L2 > 0.5f ? std::clamp((state.SCP_L2 - 0.5f) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f); + values[XInputKeyCodes::LT_Neg] = static_cast(state.SCP_L2 < 0.5f ? std::clamp((0.5f - state.SCP_L2) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f); + + values[XInputKeyCodes::RT_Pos] = static_cast(state.SCP_R2 > 0.5f ? std::clamp((state.SCP_R2 - 0.5f) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f); + values[XInputKeyCodes::RT_Neg] = static_cast(state.SCP_R2 < 0.5f ? std::clamp((0.5f - state.SCP_R2) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f); // Sticks const float lx = state.SCP_LX; diff --git a/rpcs3/Input/xinput_pad_handler.h b/rpcs3/Input/xinput_pad_handler.h index 49595f7696..f401090181 100644 --- a/rpcs3/Input/xinput_pad_handler.h +++ b/rpcs3/Input/xinput_pad_handler.h @@ -78,6 +78,11 @@ class xinput_pad_handler final : public PadHandlerBase LT, RT, + LT_Pos, + LT_Neg, + RT_Pos, + RT_Neg, + LSXNeg, LSXPos, LSYNeg, @@ -120,8 +125,8 @@ private: typedef DWORD (WINAPI * PFN_XINPUTGETBATTERYINFORMATION)(DWORD, BYTE, XINPUT_BATTERY_INFORMATION *); int GetDeviceNumber(const std::string& padId); - static PadButtonValues get_button_values_base(const XINPUT_STATE& state); - static PadButtonValues get_button_values_scp(const SCP_EXTN& state); + static PadButtonValues get_button_values_base(const XINPUT_STATE& state, bool triggers_as_sticks_only); + static PadButtonValues get_button_values_scp(const SCP_EXTN& state, bool triggers_as_sticks_only); HMODULE library{ nullptr }; PFN_XINPUTGETEXTENDED xinputGetExtended{ nullptr }; diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.cpp b/rpcs3/rpcs3qt/pad_settings_dialog.cpp index 0015b4fc47..75c8eea9eb 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/pad_settings_dialog.cpp @@ -1311,6 +1311,9 @@ void pad_settings_dialog::OnPadButtonClicked(int id) m_enable_multi_binding = true; } + // On alt+click or alt+space allow to handle triggers as the entire stick axis + m_handler->set_triggers_as_sticks_only(QApplication::keyboardModifiers() & Qt::KeyboardModifier::AltModifier); + for (auto but : m_pad_buttons->buttons()) { but->setFocusPolicy(Qt::ClickFocus); diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index c83360cc67..8a5bd99c93 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -295,7 +295,7 @@ public: const QString mouse_deadzones = tr("The mouse deadzones represent the games' own deadzones on the x and y axes. Games usually enforce their own deadzones to filter out small unwanted stick movements. In consequence, mouse input feels unintuitive since it relies on immediate responsiveness. You can change these values temporarily during gameplay in order to find out the optimal values for your game (Alt+T and Alt+Y for x, Alt+U and Alt+I for y)."); const QString mouse_acceleration = tr("The mouse acceleration can be used to amplify your mouse movements on the x and y axes. Increase these values if your mouse movements feel too slow while playing a game. You can change these values temporarily during gameplay in order to find out the optimal values (Alt+G and Alt+H for x, Alt+J and Alt+K for y). Keep in mind that modern mice usually provide different modes and settings that can be used to change mouse movement speeds as well."); const QString mouse_movement = tr("The mouse movement mode determines how the mouse movement is translated to pad input.
Use the relative mode for traditional mouse movement.
Use the absolute mode to use the mouse's distance to the center of the screen as input value."); - const QString button_assignment = tr("Left-click: remap this button.
Shift + Left-click: add an additional button mapping.
Right-click: clear this button mapping."); + const QString button_assignment = tr("Left-click: remap this button.
Shift + Left-click: add an additional button mapping.
Alt + Left-click: differentiate between trigger press and release (only XInput for now).
Right-click: clear this button mapping."); } gamepad_settings; };