xinput: allow to map triggers as positive or negative

This commit is contained in:
Megamouse 2024-08-13 02:08:25 +02:00
parent 26a1a4418e
commit 93c21103aa
5 changed files with 46 additions and 11 deletions

View File

@ -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);

View File

@ -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<u64, u16> 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<u16>(lTrigger > 0.5f ? std::clamp((lTrigger - 0.5f) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f);
values[XInputKeyCodes::LT_Neg] = static_cast<u16>(lTrigger < 0.5f ? std::clamp((0.5f - lTrigger) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f);
values[XInputKeyCodes::RT_Pos] = static_cast<u16>(rTrigger > 0.5f ? std::clamp((rTrigger - 0.5f) * 2.0f * 255.0f, 0.0f, 255.0f) : 0.0f);
values[XInputKeyCodes::RT_Neg] = static_cast<u16>(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<u16>(state.SCP_L2 * 255.0f);
values[xinput_pad_handler::XInputKeyCodes::RT] = static_cast<u16>(state.SCP_R2 * 255.0f);
if (!triggers_as_sticks_only)
{
values[xinput_pad_handler::XInputKeyCodes::LT] = static_cast<u16>(state.SCP_L2 * 255.0f);
values[xinput_pad_handler::XInputKeyCodes::RT] = static_cast<u16>(state.SCP_R2 * 255.0f);
}
values[XInputKeyCodes::LT_Pos] = static_cast<u16>(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<u16>(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<u16>(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<u16>(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;

View File

@ -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 };

View File

@ -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);

View File

@ -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.<br>Use the relative mode for traditional mouse movement.<br>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.<br>Shift + Left-click: add an additional button mapping.<br>Right-click: clear this button mapping.");
const QString button_assignment = tr("Left-click: remap this button.<br>Shift + Left-click: add an additional button mapping.<br>Alt + Left-click: differentiate between trigger press and release (only XInput for now).<br>Right-click: clear this button mapping.");
} gamepad_settings;
};