From e415251f30391f7e618ab79f8b227b9b2e321b45 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 18 Jun 2022 19:29:57 +1000 Subject: [PATCH] Qt: Add pad deadzone --- .../ControllerBindingWidget_DualShock2.ui | 32 +++++++++++++++-- .../Settings/ControllerBindingWidgets.cpp | 20 +++++++++-- pcsx2/PAD/Host/KeyStatus.cpp | 13 ++++--- pcsx2/PAD/Host/KeyStatus.h | 8 +++-- pcsx2/PAD/Host/PAD.cpp | 35 +++++++++++++------ pcsx2/PAD/Host/PAD.h | 5 +++ 6 files changed, 91 insertions(+), 22 deletions(-) diff --git a/pcsx2-qt/Settings/ControllerBindingWidget_DualShock2.ui b/pcsx2-qt/Settings/ControllerBindingWidget_DualShock2.ui index f0f203b8e6..607f7516d9 100644 --- a/pcsx2-qt/Settings/ControllerBindingWidget_DualShock2.ui +++ b/pcsx2-qt/Settings/ControllerBindingWidget_DualShock2.ui @@ -623,10 +623,10 @@ - + - Axis Scale + Analog Sensitivity @@ -642,7 +642,33 @@ - 1.0x + 100% + + + + + + + + + + Analog Deadzone + + + + + + 100 + + + Qt::Horizontal + + + + + + + 0% diff --git a/pcsx2-qt/Settings/ControllerBindingWidgets.cpp b/pcsx2-qt/Settings/ControllerBindingWidgets.cpp index 29cbbebfd0..15a88c04b0 100644 --- a/pcsx2-qt/Settings/ControllerBindingWidgets.cpp +++ b/pcsx2-qt/Settings/ControllerBindingWidgets.cpp @@ -238,6 +238,21 @@ void ControllerBindingWidget_Base::initBindingWidgets() break; } + if (QSlider* widget = findChild(QStringLiteral("Deadzone")); widget) + { + const float range = static_cast(widget->maximum()); + QLabel* label = findChild(QStringLiteral("DeadzoneLabel")); + if (label) + { + connect(widget, &QSlider::valueChanged, this, [range, label](int value) { + label->setText(tr("%1%").arg((static_cast(value) / range) * 100.0f, 0, 'f', 0)); + }); + } + + ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(sif, widget, config_section, "Deadzone", range, + PAD::DEFAULT_STICK_DEADZONE); + } + if (QSlider* widget = findChild(QStringLiteral("AxisScale")); widget) { // position 1.0f at the halfway point @@ -246,11 +261,12 @@ void ControllerBindingWidget_Base::initBindingWidgets() if (label) { connect(widget, &QSlider::valueChanged, this, [range, label](int value) { - label->setText(tr("%1x").arg(static_cast(value) / range, 0, 'f', 2)); + label->setText(tr("%1%").arg((static_cast(value) / range) * 100.0f, 0, 'f', 0)); }); } - ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(sif, widget, config_section, "AxisScale", range, 1.0f); + ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(sif, widget, config_section, "AxisScale", range, + PAD::DEFAULT_STICK_SCALE); } if (QDoubleSpinBox* widget = findChild(QStringLiteral("SmallMotorScale")); widget) diff --git a/pcsx2/PAD/Host/KeyStatus.cpp b/pcsx2/PAD/Host/KeyStatus.cpp index d07e5f148f..ec8536be2b 100644 --- a/pcsx2/PAD/Host/KeyStatus.cpp +++ b/pcsx2/PAD/Host/KeyStatus.cpp @@ -28,7 +28,8 @@ KeyStatus::KeyStatus() for (u32 pad = 0; pad < NUM_CONTROLLER_PORTS; pad++) { - m_axis_scale[pad] = 1.0f; + m_axis_scale[pad][0] = 0.0f; + m_axis_scale[pad][1] = 1.0f; } } @@ -50,10 +51,10 @@ void KeyStatus::Init() void KeyStatus::Set(u32 pad, u32 index, float value) { - m_button_pressure[pad][index] = static_cast(std::clamp(value * m_axis_scale[pad] * 255.0f, 0.0f, 255.0f)); - if (IsAnalogKey(index)) { + m_button_pressure[pad][index] = static_cast(std::clamp(((value < m_axis_scale[pad][0]) ? 0.0f : value) * m_axis_scale[pad][1] * 255.0f, 0.0f, 255.0f)); + // Left -> -- -> Right // Value range : FFFF8002 -> 0 -> 7FFE // Force range : 80 -> 0 -> 7F @@ -94,8 +95,10 @@ void KeyStatus::Set(u32 pad, u32 index, float value) } else { + m_button_pressure[pad][index] = static_cast(std::clamp(value * 255.0f, 0.0f, 255.0f)); + // Since we reordered the buttons for better UI, we need to remap them here. - static constexpr std::array bitmask_mapping = { { + static constexpr std::array bitmask_mapping = {{ 12, // PAD_UP 13, // PAD_RIGHT 14, // PAD_DOWN @@ -114,7 +117,7 @@ void KeyStatus::Set(u32 pad, u32 index, float value) 10, // PAD_R3 16, // Analog // remainder are analogs and not used here - } }; + }}; // TODO: Deadzone here? if (value > 0.0f) diff --git a/pcsx2/PAD/Host/KeyStatus.h b/pcsx2/PAD/Host/KeyStatus.h index 4cbac52955..ca25a82c82 100644 --- a/pcsx2/PAD/Host/KeyStatus.h +++ b/pcsx2/PAD/Host/KeyStatus.h @@ -36,7 +36,7 @@ namespace PAD u32 m_button[NUM_CONTROLLER_PORTS]; u8 m_button_pressure[NUM_CONTROLLER_PORTS][MAX_KEYS]; PADAnalog m_analog[NUM_CONTROLLER_PORTS]; - float m_axis_scale[NUM_CONTROLLER_PORTS]; + float m_axis_scale[NUM_CONTROLLER_PORTS][2]; float m_vibration_scale[NUM_CONTROLLER_PORTS][2]; public: @@ -48,7 +48,11 @@ namespace PAD __fi PAD::ControllerType GetType(u32 pad) { return m_type[pad]; } __fi void SetType(u32 pad, PAD::ControllerType type) { m_type[pad] = type; } - __fi void SetAxisScale(u32 pad, float scale) { m_axis_scale[pad] = scale; } + __fi void SetAxisScale(u32 pad, float deadzone, float scale) + { + m_axis_scale[pad][0] = deadzone; + m_axis_scale[pad][1] = scale; + } __fi float GetVibrationScale(u32 pad, u32 motor) const { return m_vibration_scale[pad][motor]; } __fi void SetVibrationScale(u32 pad, u32 motor, float scale) { m_vibration_scale[pad][motor] = scale; } diff --git a/pcsx2/PAD/Host/PAD.cpp b/pcsx2/PAD/Host/PAD.cpp index f87eed43d7..af04fefdac 100644 --- a/pcsx2/PAD/Host/PAD.cpp +++ b/pcsx2/PAD/Host/PAD.cpp @@ -47,6 +47,7 @@ namespace PAD bool trigger_state; ///< Whether the macro button is active. }; + static std::string GetConfigSection(u32 pad_index); static void LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, const std::string_view& type, const std::string& section); static void ApplyMacroButton(u32 pad, const MacroButton& mb); static void UpdateMacroButtons(); @@ -182,6 +183,11 @@ u8 PADpoll(u8 value) return pad_poll(value); } +std::string PAD::GetConfigSection(u32 pad_index) +{ + return fmt::format("Pad{}", pad_index + 1); +} + void PAD::LoadConfig(const SettingsInterface& si) { PAD::s_macro_buttons = {}; @@ -192,7 +198,7 @@ void PAD::LoadConfig(const SettingsInterface& si) // This is where we would load controller types, if onepad supported them. for (u32 i = 0; i < NUM_CONTROLLER_PORTS; i++) { - const std::string section(StringUtil::StdStringFromFormat("Pad%u", i + 1u)); + const std::string section(GetConfigSection(i)); const std::string type(si.GetStringValue(section.c_str(), "Type", GetDefaultPadType(i))); const ControllerInfo* ci = GetControllerInfo(type); @@ -204,13 +210,14 @@ void PAD::LoadConfig(const SettingsInterface& si) g_key_status.SetType(i, ci->type); - const float axis_scale = si.GetFloatValue(section.c_str(), "AxisScale", 1.0f); - g_key_status.SetAxisScale(i, axis_scale); + const float axis_deadzone = si.GetFloatValue(section.c_str(), "Deadzone", DEFAULT_STICK_DEADZONE); + const float axis_scale = si.GetFloatValue(section.c_str(), "AxisScale", DEFAULT_STICK_SCALE); + g_key_status.SetAxisScale(i, axis_deadzone, axis_scale); if (ci->vibration_caps != VibrationCapabilities::NoVibration) { - const float large_motor_scale = si.GetFloatValue(section.c_str(), "LargeMotorScale", 1.0f); - const float small_motor_scale = si.GetFloatValue(section.c_str(), "SmallMotorScale", 1.0f); + const float large_motor_scale = si.GetFloatValue(section.c_str(), "LargeMotorScale", DEFAULT_MOTOR_SCALE); + const float small_motor_scale = si.GetFloatValue(section.c_str(), "SmallMotorScale", DEFAULT_MOTOR_SCALE); g_key_status.SetVibrationScale(i, 0, large_motor_scale); g_key_status.SetVibrationScale(i, 1, small_motor_scale); } @@ -227,11 +234,8 @@ const char* PAD::GetDefaultPadType(u32 pad) void PAD::SetDefaultConfig(SettingsInterface& si) { si.ClearSection("InputSources"); - - for (u32 i = 0; i < NUM_CONTROLLER_PORTS; i++) - si.ClearSection(StringUtil::StdStringFromFormat("Pad%u", i + 1).c_str()); - si.ClearSection("Hotkeys"); + si.ClearSection("Pad"); // PCSX2 Controller Settings - Global Settings si.SetBoolValue("InputSources", "SDL", true); @@ -245,9 +249,20 @@ void PAD::SetDefaultConfig(SettingsInterface& si) si.SetBoolValue("Pad", "PointerXInvert", false); si.SetBoolValue("Pad", "PointerYInvert", false); + // PCSX2 Controller Settings - Default pad types and parameters. + for (u32 i = 0; i < NUM_CONTROLLER_PORTS; i++) + { + const std::string section(GetConfigSection(i)); + si.ClearSection(section.c_str()); + si.SetStringValue(section.c_str(), "Type", GetDefaultPadType(i)); + si.SetFloatValue(section.c_str(), "Deadzone", DEFAULT_STICK_DEADZONE); + si.SetFloatValue(section.c_str(), "AxisScale", DEFAULT_STICK_SCALE); + si.SetFloatValue(section.c_str(), "LargeMotorScale", DEFAULT_MOTOR_SCALE); + si.SetFloatValue(section.c_str(), "SmallMotorScale", DEFAULT_MOTOR_SCALE); + } + // PCSX2 Controller Settings - Controller 1 / Controller 2 / ... // Use the automapper to set this up. - si.SetStringValue("Pad1", "Type", GetDefaultPadType(0)); MapController(si, 0, InputManager::GetGenericBindingMapping("Keyboard")); // PCSX2 Controller Settings - Hotkeys diff --git a/pcsx2/PAD/Host/PAD.h b/pcsx2/PAD/Host/PAD.h index 53d5ff3a98..29256ee5c1 100644 --- a/pcsx2/PAD/Host/PAD.h +++ b/pcsx2/PAD/Host/PAD.h @@ -87,6 +87,11 @@ namespace PAD /// Number of macro buttons per controller. static constexpr u32 NUM_MACRO_BUTTONS_PER_CONTROLLER = 4; + /// Default stick deadzone/sensitivity. + static constexpr float DEFAULT_STICK_DEADZONE = 0.0f; + static constexpr float DEFAULT_STICK_SCALE = 1.33f; + static constexpr float DEFAULT_MOTOR_SCALE = 1.0f; + /// Returns the default type for the specified port. const char* GetDefaultPadType(u32 pad);