diff --git a/rpcs3/Emu/Io/PadHandler.cpp b/rpcs3/Emu/Io/PadHandler.cpp index ebd591e94b..7a781a000a 100644 --- a/rpcs3/Emu/Io/PadHandler.cpp +++ b/rpcs3/Emu/Io/PadHandler.cpp @@ -82,7 +82,7 @@ f32 PadHandlerBase::ScaledAxisInput(f32 raw_value, f32 minimum, f32 maximum, f32 } // Get normalized trigger value based on the range defined by a threshold -u16 PadHandlerBase::NormalizeTriggerInput(u16 value, s32 threshold) const +u16 PadHandlerBase::NormalizeTriggerInput(u16 value, u32 threshold) const { if (value <= threshold || threshold >= trigger_max) { @@ -116,40 +116,39 @@ u16 PadHandlerBase::NormalizeStickInput(u16 raw_value, s32 threshold, s32 multip return static_cast(ScaledInput(static_cast(scaled_value), 0.0f, static_cast(thumb_max), static_cast(threshold))); } -// This function normalizes stick deadzone based on the DS3's deadzone, which is ~13% +// This function normalizes stick deadzone based on the DS3's deadzone, which is ~13% (default of anti deadzone) // X and Y is expected to be in (-255) to 255 range, deadzone should be in terms of thumb stick range // return is new x and y values in 0-255 range -std::tuple PadHandlerBase::NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone) const +std::tuple PadHandlerBase::NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone, u32 anti_deadzone) const { - const f32 dz_range = deadzone / static_cast(std::abs(thumb_max)); // NOTE: thumb_max should be positive anyway - f32 X = inX / 255.0f; f32 Y = inY / 255.0f; - if (dz_range > 0.f) + const f32 mag = std::min(sqrtf(X * X + Y * Y), 1.f); + + if (mag > 0.f) { - const f32 mag = std::min(sqrtf(X * X + Y * Y), 1.f); + const f32 dz_max = static_cast(thumb_max); + const f32 dz = deadzone / dz_max; + const f32 anti_dz = anti_deadzone / dz_max; - if (mag <= 0) - { - return std::tuple(ConvertAxis(X), ConvertAxis(Y)); - } + f32 pos; - if (mag > dz_range) + if (dz <= 0.f || mag > dz) { - const f32 pos = std::lerp(0.13f, 1.f, (mag - dz_range) / (1 - dz_range)); - const f32 scale = pos / mag; - X = X * scale; - Y = Y * scale; + const f32 range = 1.f - dz; + pos = std::lerp(anti_dz, 1.f, (mag - dz) / range); } else { - const f32 pos = std::lerp(0.f, 0.13f, mag / dz_range); - const f32 scale = pos / mag; - X = X * scale; - Y = Y * scale; + pos = std::lerp(0.f, anti_dz, mag / dz); } + + const f32 scale = pos / mag; + X *= scale; + Y *= scale; } + return std::tuple(ConvertAxis(X), ConvertAxis(Y)); } @@ -175,7 +174,7 @@ u16 PadHandlerBase::ConvertAxis(f32 value) // using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange // this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000 // This function assumes inX and inY is already in 0-255 -std::tuple PadHandlerBase::ConvertToSquirclePoint(u16 inX, u16 inY, int squircle_factor) +std::tuple PadHandlerBase::ConvertToSquirclePoint(u16 inX, u16 inY, u32 squircle_factor) { // convert inX and Y to a (-1, 1) vector; const f32 x = (inX - 127.5f) / 127.5f; @@ -393,10 +392,10 @@ void PadHandlerBase::get_motion_sensors(const std::string& pad_id, const motion_ callback(pad_id, std::move(preview_values)); } -void PadHandlerBase::convert_stick_values(u16& x_out, u16& y_out, const s32& x_in, const s32& y_in, const s32& deadzone, const s32& padsquircling) const +void PadHandlerBase::convert_stick_values(u16& x_out, u16& y_out, s32 x_in, s32 y_in, u32 deadzone, u32 anti_deadzone, u32 padsquircling) const { // Normalize our stick axis based on the deadzone - std::tie(x_out, y_out) = NormalizeStickDeadzone(x_in, y_in, deadzone); + std::tie(x_out, y_out) = NormalizeStickDeadzone(x_in, y_in, deadzone, anti_deadzone); // Apply pad squircling if necessary if (padsquircling != 0) @@ -700,8 +699,8 @@ void PadHandlerBase::get_mapping(const pad_ensemble& binding) u16 lx, ly, rx, ry; // Normalize and apply pad squircling - convert_stick_values(lx, ly, stick_val[0], stick_val[1], cfg->lstickdeadzone, cfg->lpadsquircling); - convert_stick_values(rx, ry, stick_val[2], stick_val[3], cfg->rstickdeadzone, cfg->rpadsquircling); + convert_stick_values(lx, ly, stick_val[0], stick_val[1], cfg->lstickdeadzone, cfg->lstick_anti_deadzone, cfg->lpadsquircling); + convert_stick_values(rx, ry, stick_val[2], stick_val[3], cfg->rstickdeadzone, cfg->rstick_anti_deadzone, cfg->rpadsquircling); if (m_type == pad_handler::ds4) { diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index e0c38f62a8..1a31f043c4 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -214,7 +214,7 @@ protected: static f32 ScaledAxisInput(f32 raw_value, f32 minimum, f32 maximum, f32 deadzone, f32 range = 255.0f); // Get normalized trigger value based on the range defined by a threshold - u16 NormalizeTriggerInput(u16 value, s32 threshold) const; + u16 NormalizeTriggerInput(u16 value, u32 threshold) const; // normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions // the input values must lie in 0+ @@ -223,7 +223,7 @@ protected: // This function normalizes stick deadzone based on the DS3's deadzone, which is ~13% // X and Y is expected to be in (-255) to 255 range, deadzone should be in terms of thumb stick range // return is new x and y values in 0-255 range - std::tuple NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone) const; + std::tuple NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone, u32 anti_deadzone) const; // get clamped value between 0 and 255 static u16 Clamp0To255(f32 input); @@ -237,13 +237,13 @@ protected: // using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange // this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000 // This function assumes inX and inY is already in 0-255 - static std::tuple ConvertToSquirclePoint(u16 inX, u16 inY, int squircle_factor); + static std::tuple ConvertToSquirclePoint(u16 inX, u16 inY, u32 squircle_factor); public: - // s32 thumb_min = 0; // Unused. Make sure all handlers report 0+ values for sticks in get_button_values. - s32 thumb_max = 255; // NOTE: Better keep this positive - s32 trigger_min = 0; - s32 trigger_max = 255; + // u32 thumb_min = 0; // Unused. Make sure all handlers report 0+ values for sticks in get_button_values. + u32 thumb_max = 255; + u32 trigger_min = 0; + u32 trigger_max = 255; u32 connected_devices = 0; pad_handler m_type; @@ -263,7 +263,7 @@ public: bool has_pressure_intensity_button() const; u16 NormalizeStickInput(u16 raw_value, s32 threshold, s32 multiplier, bool ignore_threshold = false) const; - void convert_stick_values(u16& x_out, u16& y_out, const s32& x_in, const s32& y_in, const s32& deadzone, const s32& padsquircling) 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; virtual bool Init() { return true; } PadHandlerBase(pad_handler type = pad_handler::null, bool emulation = false); diff --git a/rpcs3/Emu/Io/pad_config.h b/rpcs3/Emu/Io/pad_config.h index a1e6a14b5a..5e2b94bfd3 100644 --- a/rpcs3/Emu/Io/pad_config.h +++ b/rpcs3/Emu/Io/pad_config.h @@ -75,6 +75,8 @@ struct cfg_pad final : cfg::node cfg::uint<0, 200> rstickmultiplier{ this, "Right Stick Multiplier", 100 }; cfg::uint<0, 1000000> lstickdeadzone{ this, "Left Stick Deadzone", 0 }; cfg::uint<0, 1000000> rstickdeadzone{ this, "Right Stick Deadzone", 0 }; + cfg::uint<0, 1000000> lstick_anti_deadzone{ this, "Left Stick Anti-Deadzone", 0 }; + cfg::uint<0, 1000000> rstick_anti_deadzone{ this, "Right Stick Anti-Deadzone", 0 }; cfg::uint<0, 1000000> ltriggerthreshold{ this, "Left Trigger Threshold", 0 }; cfg::uint<0, 1000000> rtriggerthreshold{ this, "Right Trigger Threshold", 0 }; cfg::uint<0, 1000000> lpadsquircling{ this, "Left Pad Squircling Factor", 0 }; diff --git a/rpcs3/Input/ds3_pad_handler.cpp b/rpcs3/Input/ds3_pad_handler.cpp index c2fd3aa156..7c80b57e0f 100644 --- a/rpcs3/Input/ds3_pad_handler.cpp +++ b/rpcs3/Input/ds3_pad_handler.cpp @@ -223,6 +223,8 @@ void ds3_pad_handler::init_config(cfg_pad* cfg) cfg->pressure_intensity_button.def = ::at32(button_list, DS3KeyCodes::None); // Set default misc variables + cfg->lstick_anti_deadzone.def = 0; + cfg->rstick_anti_deadzone.def = 0; cfg->lstickdeadzone.def = 40; // between 0 and 255 cfg->rstickdeadzone.def = 40; // between 0 and 255 cfg->ltriggerthreshold.def = 0; // between 0 and 255 diff --git a/rpcs3/Input/ds4_pad_handler.cpp b/rpcs3/Input/ds4_pad_handler.cpp index c1f96b9bef..817d07d9b9 100644 --- a/rpcs3/Input/ds4_pad_handler.cpp +++ b/rpcs3/Input/ds4_pad_handler.cpp @@ -164,6 +164,8 @@ void ds4_pad_handler::init_config(cfg_pad* cfg) cfg->pressure_intensity_button.def = ::at32(button_list, DS4KeyCodes::None); // Set default misc variables + cfg->lstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% + cfg->rstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% cfg->lstickdeadzone.def = 40; // between 0 and 255 cfg->rstickdeadzone.def = 40; // between 0 and 255 cfg->ltriggerthreshold.def = 0; // between 0 and 255 diff --git a/rpcs3/Input/dualsense_pad_handler.cpp b/rpcs3/Input/dualsense_pad_handler.cpp index 12e6f46fca..6c1a7aa52e 100644 --- a/rpcs3/Input/dualsense_pad_handler.cpp +++ b/rpcs3/Input/dualsense_pad_handler.cpp @@ -317,6 +317,8 @@ void dualsense_pad_handler::init_config(cfg_pad* cfg) cfg->pressure_intensity_button.def = ::at32(button_list, DualSenseKeyCodes::None); // Set default misc variables + cfg->lstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% + cfg->rstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% cfg->lstickdeadzone.def = 40; // between 0 and 255 cfg->rstickdeadzone.def = 40; // between 0 and 255 cfg->ltriggerthreshold.def = 0; // between 0 and 255 diff --git a/rpcs3/Input/evdev_joystick_handler.cpp b/rpcs3/Input/evdev_joystick_handler.cpp index d486442c93..d392e6bc6a 100644 --- a/rpcs3/Input/evdev_joystick_handler.cpp +++ b/rpcs3/Input/evdev_joystick_handler.cpp @@ -85,6 +85,8 @@ void evdev_joystick_handler::init_config(cfg_pad* cfg) cfg->pressure_intensity_button.def = ::at32(button_list, NO_BUTTON); // Set default misc variables + cfg->lstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% + cfg->rstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% cfg->lstickdeadzone.def = 30; // between 0 and 255 cfg->rstickdeadzone.def = 30; // between 0 and 255 cfg->ltriggerthreshold.def = 0; // between 0 and 255 @@ -1210,8 +1212,8 @@ void evdev_joystick_handler::apply_input_events(const std::shared_ptr& pad) u16 lx, ly, rx, ry; // Normalize and apply pad squircling - convert_stick_values(lx, ly, stick_val[0], stick_val[1], cfg->lstickdeadzone, cfg->lpadsquircling); - convert_stick_values(rx, ry, stick_val[2], stick_val[3], cfg->rstickdeadzone, cfg->rpadsquircling); + convert_stick_values(lx, ly, stick_val[0], stick_val[1], cfg->lstickdeadzone, cfg->lstick_anti_deadzone, cfg->lpadsquircling); + convert_stick_values(rx, ry, stick_val[2], stick_val[3], cfg->rstickdeadzone, cfg->rstick_anti_deadzone, cfg->rpadsquircling); pad->m_sticks[0].m_value = lx; pad->m_sticks[1].m_value = 255 - ly; diff --git a/rpcs3/Input/keyboard_pad_handler.cpp b/rpcs3/Input/keyboard_pad_handler.cpp index aa7283150f..82fc7fae01 100644 --- a/rpcs3/Input/keyboard_pad_handler.cpp +++ b/rpcs3/Input/keyboard_pad_handler.cpp @@ -59,6 +59,15 @@ void keyboard_pad_handler::init_config(cfg_pad* cfg) cfg->pressure_intensity_button.def = GetKeyName(Qt::NoButton); + cfg->lstick_anti_deadzone.def = 0; + cfg->rstick_anti_deadzone.def = 0; + cfg->lstickdeadzone.def = 0; + cfg->rstickdeadzone.def = 0; + cfg->ltriggerthreshold.def = 0; + cfg->rtriggerthreshold.def = 0; + cfg->lpadsquircling.def = 0; + cfg->rpadsquircling.def = 0; + // apply defaults cfg->from_default(); } diff --git a/rpcs3/Input/mm_joystick_handler.cpp b/rpcs3/Input/mm_joystick_handler.cpp index 3223c8079d..69f3da856a 100644 --- a/rpcs3/Input/mm_joystick_handler.cpp +++ b/rpcs3/Input/mm_joystick_handler.cpp @@ -55,6 +55,8 @@ void mm_joystick_handler::init_config(cfg_pad* cfg) cfg->pressure_intensity_button.def = ::at32(button_list, NO_BUTTON); // Set default misc variables + cfg->lstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% + cfg->rstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% cfg->lstickdeadzone.def = 0; // between 0 and 255 cfg->rstickdeadzone.def = 0; // between 0 and 255 cfg->ltriggerthreshold.def = 0; // between 0 and 255 diff --git a/rpcs3/Input/sdl_pad_handler.cpp b/rpcs3/Input/sdl_pad_handler.cpp index 970d4ab352..7617fbca53 100644 --- a/rpcs3/Input/sdl_pad_handler.cpp +++ b/rpcs3/Input/sdl_pad_handler.cpp @@ -131,6 +131,8 @@ void sdl_pad_handler::init_config(cfg_pad* cfg) cfg->pressure_intensity_button.def = ::at32(button_list, SDLKeyCodes::None); // Set default misc variables + cfg->lstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% + cfg->rstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% cfg->lstickdeadzone.def = 8000; // between 0 and SDL_JOYSTICK_AXIS_MAX cfg->rstickdeadzone.def = 8000; // between 0 and SDL_JOYSTICK_AXIS_MAX cfg->ltriggerthreshold.def = 0; // between 0 and SDL_JOYSTICK_AXIS_MAX diff --git a/rpcs3/Input/skateboard_pad_handler.cpp b/rpcs3/Input/skateboard_pad_handler.cpp index f78c3af3c1..83092295b1 100644 --- a/rpcs3/Input/skateboard_pad_handler.cpp +++ b/rpcs3/Input/skateboard_pad_handler.cpp @@ -131,6 +131,8 @@ void skateboard_pad_handler::init_config(cfg_pad* cfg) cfg->tilt_right.def = ::at32(button_list, skateboard_key_codes::tilt_right); // Set default misc variables + cfg->lstick_anti_deadzone.def = 0; + cfg->rstick_anti_deadzone.def = 0; cfg->lstickdeadzone.def = 40; // between 0 and 255 cfg->rstickdeadzone.def = 40; // between 0 and 255 cfg->ltriggerthreshold.def = 0; // between 0 and 255 diff --git a/rpcs3/Input/xinput_pad_handler.cpp b/rpcs3/Input/xinput_pad_handler.cpp index f49345dac9..0fe74eb7fd 100644 --- a/rpcs3/Input/xinput_pad_handler.cpp +++ b/rpcs3/Input/xinput_pad_handler.cpp @@ -115,6 +115,8 @@ void xinput_pad_handler::init_config(cfg_pad* cfg) cfg->pressure_intensity_button.def = ::at32(button_list, XInputKeyCodes::None); // Set default misc variables + cfg->lstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% + cfg->rstick_anti_deadzone.def = static_cast(0.13 * thumb_max); // 13% cfg->lstickdeadzone.def = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE; // between 0 and 32767 cfg->rstickdeadzone.def = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE; // between 0 and 32767 cfg->ltriggerthreshold.def = XINPUT_GAMEPAD_TRIGGER_THRESHOLD; // between 0 and 255 diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.cpp b/rpcs3/rpcs3qt/pad_settings_dialog.cpp index 2864d1a8b4..eaf67869c7 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/pad_settings_dialog.cpp @@ -195,8 +195,8 @@ pad_settings_dialog::pad_settings_dialog(std::shared_ptr gui_setti { m_gui_settings->SetValue(gui::pads_show_emulated, checked); const cfg_pad& cfg = GetPlayerConfig(); - RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->size().width(), m_lx, m_ly, cfg.lpadsquircling, cfg.lstickmultiplier / 100.0); - RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->slider_stick_right->size().width(), m_rx, m_ry, cfg.rpadsquircling, cfg.rstickmultiplier / 100.0); + RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->anti_deadzone_slider_stick_left->value(), ui->slider_stick_left->size().width(), m_lx, m_ly, cfg.lpadsquircling, cfg.lstickmultiplier / 100.0); + RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->anti_deadzone_slider_stick_right->value(), ui->slider_stick_right->size().width(), m_rx, m_ry, cfg.rpadsquircling, cfg.rstickmultiplier / 100.0); }); ui->mouse_movement->addItem(tr("Relative"), static_cast(mouse_movement_mode::relative)); @@ -253,8 +253,8 @@ pad_settings_dialog::~pad_settings_dialog() void pad_settings_dialog::showEvent(QShowEvent* event) { - RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->size().width(), 0, 0, 0, 0); - RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->slider_stick_right->size().width(), 0, 0, 0, 0); + RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->anti_deadzone_slider_stick_left->value(), ui->slider_stick_left->size().width(), 0, 0, 0, 0); + RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->anti_deadzone_slider_stick_right->value(), ui->slider_stick_right->size().width(), 0, 0, 0, 0); // Resize in order to fit into our scroll area if (!restoreGeometry(m_gui_settings->GetValue(gui::pads_geometry).toByteArray())) @@ -379,12 +379,22 @@ void pad_settings_dialog::InitButtons() connect(ui->slider_stick_left, &QSlider::valueChanged, this, [&](int value) { - RepaintPreviewLabel(ui->preview_stick_left, value, ui->slider_stick_left->size().width(), m_lx, m_ly, ui->squircle_left->value(), ui->stick_multi_left->value()); + RepaintPreviewLabel(ui->preview_stick_left, value, ui->anti_deadzone_slider_stick_left->value(), ui->slider_stick_left->size().width(), m_lx, m_ly, ui->squircle_left->value(), ui->stick_multi_left->value()); }); connect(ui->slider_stick_right, &QSlider::valueChanged, this, [&](int value) { - RepaintPreviewLabel(ui->preview_stick_right, value, ui->slider_stick_right->size().width(), m_rx, m_ry, ui->squircle_right->value(), ui->stick_multi_right->value()); + RepaintPreviewLabel(ui->preview_stick_right, value, ui->anti_deadzone_slider_stick_right->value(), ui->slider_stick_right->size().width(), m_rx, m_ry, ui->squircle_right->value(), ui->stick_multi_right->value()); + }); + + connect(ui->anti_deadzone_slider_stick_left, &QSlider::valueChanged, this, [&](int value) + { + RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), value, ui->slider_stick_left->size().width(), m_lx, m_ly, ui->squircle_left->value(), ui->stick_multi_left->value()); + }); + + connect(ui->anti_deadzone_slider_stick_right, &QSlider::valueChanged, this, [&](int value) + { + RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), value, ui->slider_stick_right->size().width(), m_rx, m_ry, ui->squircle_right->value(), ui->stick_multi_right->value()); }); // Open LED settings @@ -455,13 +465,13 @@ void pad_settings_dialog::InitButtons() { m_lx = preview_values[2]; m_ly = preview_values[3]; - RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->size().width(), m_lx, m_ly, ui->squircle_left->value(), ui->stick_multi_left->value()); + RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->anti_deadzone_slider_stick_left->value(), ui->slider_stick_left->size().width(), m_lx, m_ly, ui->squircle_left->value(), ui->stick_multi_left->value()); } if (m_rx != preview_values[4] || m_ry != preview_values[5]) { m_rx = preview_values[4]; m_ry = preview_values[5]; - RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->slider_stick_right->size().width(), m_rx, m_ry, ui->squircle_right->value(), ui->stick_multi_right->value()); + RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->anti_deadzone_slider_stick_right->value(), ui->slider_stick_right->size().width(), m_rx, m_ry, ui->squircle_right->value(), ui->stick_multi_right->value()); } } @@ -502,13 +512,13 @@ void pad_settings_dialog::InitButtons() { m_lx = 0; m_ly = 0; - RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->size().width(), m_lx, m_ly, ui->squircle_left->value(), ui->stick_multi_left->value()); + RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->anti_deadzone_slider_stick_left->value(), ui->slider_stick_left->size().width(), m_lx, m_ly, ui->squircle_left->value(), ui->stick_multi_left->value()); } if (m_rx != 0 || m_ry != 0) { m_rx = 0; m_ry = 0; - RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->slider_stick_right->size().width(), m_rx, m_ry, ui->squircle_right->value(), ui->stick_multi_right->value()); + RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->anti_deadzone_slider_stick_right->value(), ui->slider_stick_right->size().width(), m_rx, m_ry, ui->squircle_right->value(), ui->stick_multi_right->value()); } } }; @@ -764,19 +774,21 @@ void pad_settings_dialog::ReactivateButtons() ui->chooseProduct->setFocusPolicy(Qt::WheelFocus); } -void pad_settings_dialog::RepaintPreviewLabel(QLabel* l, int deadzone, int desired_width, int x, int y, int squircle, double multiplier) const +void pad_settings_dialog::RepaintPreviewLabel(QLabel* l, int deadzone, int anti_deadzone, int desired_width, int x, int y, int squircle, double multiplier) const { desired_width = 100; // Let's keep a fixed size for these labels for now - const int deadzone_max = m_handler ? m_handler->thumb_max : 255; // 255 used as fallback. The deadzone circle shall be small. + const qreal deadzone_max = m_handler ? m_handler->thumb_max : 255; // 255 used as fallback. The deadzone circle shall be small. constexpr qreal relative_size = 0.9; const qreal device_pixel_ratio = devicePixelRatioF(); const qreal scaled_width = desired_width * device_pixel_ratio; const qreal origin = desired_width / 2.0; const qreal outer_circle_diameter = relative_size * desired_width; - const qreal inner_circle_diameter = outer_circle_diameter * deadzone / deadzone_max; + const qreal deadzone_circle_diameter = outer_circle_diameter * deadzone / deadzone_max; + const qreal anti_deadzone_circle_diameter = outer_circle_diameter * anti_deadzone / deadzone_max; const qreal outer_circle_radius = outer_circle_diameter / 2.0; - const qreal inner_circle_radius = inner_circle_diameter / 2.0; + const qreal deadzone_circle_radius = deadzone_circle_diameter / 2.0; + const qreal anti_deadzone_circle_radius = anti_deadzone_circle_diameter / 2.0; const qreal stick_x = std::clamp(outer_circle_radius * x * multiplier / deadzone_max, -outer_circle_radius, outer_circle_radius); const qreal stick_y = std::clamp(outer_circle_radius * -y * multiplier / deadzone_max, -outer_circle_radius, outer_circle_radius); @@ -809,7 +821,7 @@ void pad_settings_dialog::RepaintPreviewLabel(QLabel* l, int deadzone, int desir const u16 normal_y = m_handler->NormalizeStickInput(static_cast(std::abs(y)), deadzone, m_in, true); const s32 x_in = x >= 0 ? normal_x : 0 - normal_x; const s32 y_in = y >= 0 ? normal_y : 0 - normal_y; - m_handler->convert_stick_values(real_x, real_y, x_in, y_in, deadzone, squircle); + m_handler->convert_stick_values(real_x, real_y, x_in, y_in, deadzone, anti_deadzone, squircle); } constexpr qreal real_max = 126; @@ -827,9 +839,15 @@ void pad_settings_dialog::RepaintPreviewLabel(QLabel* l, int deadzone, int desir painter.setPen(QPen(Qt::black, 1.0)); painter.drawEllipse(QRectF(-outer_circle_radius, -outer_circle_radius, outer_circle_diameter, outer_circle_diameter)); + painter.setBrush(QBrush(Qt::transparent)); + // Draw a red inner circle that represents the current deadzone painter.setPen(QPen(Qt::red, 1.0)); - painter.drawEllipse(QRectF(-inner_circle_radius, -inner_circle_radius, inner_circle_diameter, inner_circle_diameter)); + painter.drawEllipse(QRectF(-deadzone_circle_radius, -deadzone_circle_radius, deadzone_circle_diameter, deadzone_circle_diameter)); + + // Draw a green inner circle that represents the current anti-deadzone + painter.setPen(QPen(Qt::green, 1.0)); + painter.drawEllipse(QRectF(-anti_deadzone_circle_radius, -anti_deadzone_circle_radius, anti_deadzone_circle_diameter, anti_deadzone_circle_diameter)); // Draw a blue dot that represents the current stick orientation painter.setPen(QPen(Qt::blue, 2.0)); @@ -1122,6 +1140,12 @@ void pad_settings_dialog::UpdateLabels(bool is_reset) ui->slider_stick_right->setRange(0, m_handler->thumb_max); ui->slider_stick_right->setValue(cfg.rstickdeadzone); + ui->anti_deadzone_slider_stick_left->setRange(0, m_handler->thumb_max); + ui->anti_deadzone_slider_stick_left->setValue(cfg.lstick_anti_deadzone); + + ui->anti_deadzone_slider_stick_right->setRange(0, m_handler->thumb_max); + ui->anti_deadzone_slider_stick_right->setValue(cfg.rstick_anti_deadzone); + std::vector range; // Update Mouse Movement Mode @@ -1178,8 +1202,8 @@ void pad_settings_dialog::UpdateLabels(bool is_reset) ui->squircle_right->setRange(std::stoi(range.front()), std::stoi(range.back())); ui->squircle_right->setValue(cfg.rpadsquircling); - RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->size().width(), m_lx, m_ly, cfg.lpadsquircling, cfg.lstickmultiplier / 100.0); - RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->slider_stick_right->size().width(), m_rx, m_ry, cfg.rpadsquircling, cfg.rstickmultiplier / 100.0); + RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->anti_deadzone_slider_stick_left->value(), ui->slider_stick_left->size().width(), m_lx, m_ly, cfg.lpadsquircling, cfg.lstickmultiplier / 100.0); + RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->anti_deadzone_slider_stick_right->value(), ui->slider_stick_right->size().width(), m_rx, m_ry, cfg.rpadsquircling, cfg.rstickmultiplier / 100.0); // Update pressure sensitivity factors range = cfg.pressure_intensity.to_list(); @@ -1234,7 +1258,8 @@ void pad_settings_dialog::SwitchButtons(bool is_enabled) ui->gb_pressure_intensity->setEnabled(is_enabled && m_enable_pressure_intensity_button); ui->gb_vibration->setEnabled(is_enabled && m_enable_rumble); ui->gb_motion_controls->setEnabled(is_enabled && m_enable_motion); - ui->gb_sticks->setEnabled(is_enabled && m_enable_deadzones); + ui->gb_stick_deadzones->setEnabled(is_enabled && m_enable_deadzones); + ui->gb_stick_anti_deadzones->setEnabled(is_enabled && m_enable_deadzones); ui->gb_triggers->setEnabled(is_enabled && m_enable_deadzones); ui->gb_battery->setEnabled(is_enabled && (m_enable_battery || m_enable_led)); ui->pb_battery->setEnabled(is_enabled && m_enable_battery); @@ -1837,6 +1862,8 @@ void pad_settings_dialog::ApplyCurrentPlayerConfig(int new_player_id) cfg.rtriggerthreshold.set(ui->slider_trigger_right->value()); cfg.lstickdeadzone.set(ui->slider_stick_left->value()); cfg.rstickdeadzone.set(ui->slider_stick_right->value()); + cfg.lstick_anti_deadzone.set(ui->anti_deadzone_slider_stick_left->value()); + cfg.rstick_anti_deadzone.set(ui->anti_deadzone_slider_stick_right->value()); } if (m_handler->has_pressure_intensity_button()) @@ -2041,7 +2068,8 @@ void pad_settings_dialog::SubscribeTooltips() SubscribeTooltip(ui->gb_kb_stick_multi, tooltips.gamepad_settings.stick_multiplier); SubscribeTooltip(ui->gb_vibration, tooltips.gamepad_settings.vibration); SubscribeTooltip(ui->gb_motion_controls, tooltips.gamepad_settings.motion_controls); - SubscribeTooltip(ui->gb_sticks, tooltips.gamepad_settings.stick_deadzones); + SubscribeTooltip(ui->gb_stick_deadzones, tooltips.gamepad_settings.stick_deadzones); + SubscribeTooltip(ui->gb_stick_anti_deadzones, tooltips.gamepad_settings.stick_deadzones); SubscribeTooltip(ui->gb_stick_preview, tooltips.gamepad_settings.emulated_preview); SubscribeTooltip(ui->gb_triggers, tooltips.gamepad_settings.trigger_deadzones); SubscribeTooltip(ui->gb_stick_lerp, tooltips.gamepad_settings.stick_lerp); diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.h b/rpcs3/rpcs3qt/pad_settings_dialog.h index a795e0d0a9..83f1161402 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.h +++ b/rpcs3/rpcs3qt/pad_settings_dialog.h @@ -203,7 +203,7 @@ private: void ReloadButtons(); /** Repaints a stick deadzone preview label */ - void RepaintPreviewLabel(QLabel* l, int deadzone, int desired_width, int x, int y, int squircle, double multiplier) const; + void RepaintPreviewLabel(QLabel* l, int deadzone, int anti_deadzone, int desired_width, int x, int y, int squircle, double multiplier) const; QString GetLocalizedPadHandler(const QString& original, pad_handler handler); QString GetLocalizedPadName(pad_handler handler, const QString& original, usz index); diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.ui b/rpcs3/rpcs3qt/pad_settings_dialog.ui index bac66e50e4..e7cf852fd7 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.ui +++ b/rpcs3/rpcs3qt/pad_settings_dialog.ui @@ -3,7 +3,7 @@ pad_settings_dialog - Qt::WindowModal + Qt::WindowModality::WindowModal @@ -24,7 +24,7 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame 0 @@ -36,9 +36,9 @@ 0 - 0 - 1304 - 837 + -71 + 1290 + 907 @@ -231,7 +231,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -275,7 +275,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -372,7 +372,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -416,7 +416,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -468,7 +468,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -512,7 +512,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -609,7 +609,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -653,7 +653,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -726,7 +726,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -784,14 +784,14 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - Qt::Horizontal + Qt::Orientation::Horizontal @@ -802,14 +802,14 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - Qt::Horizontal + Qt::Orientation::Horizontal @@ -869,7 +869,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -930,10 +930,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -960,10 +960,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -1007,10 +1007,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -1033,10 +1033,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -1076,10 +1076,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -1096,10 +1096,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -1197,7 +1197,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1272,7 +1272,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1305,7 +1305,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1349,7 +1349,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1468,7 +1468,7 @@ true - Qt::AlignBottom|Qt::AlignHCenter + Qt::AlignmentFlag::AlignBottom|Qt::AlignmentFlag::AlignHCenter @@ -1483,7 +1483,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1558,7 +1558,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1663,10 +1663,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -1688,10 +1688,10 @@ This text should be replaced by an actual description.<br/><br/> - Qt::RichText + Qt::TextFormat::RichText - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop true @@ -1747,7 +1747,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1791,7 +1791,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1888,7 +1888,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1932,7 +1932,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1984,7 +1984,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2028,7 +2028,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2125,7 +2125,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2169,7 +2169,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2239,7 +2239,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2266,7 +2266,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2317,7 +2317,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2344,7 +2344,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2357,6 +2357,76 @@ + + + + Analog Stick Deadzones + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + Qt::Orientation::Horizontal + + + + + + + Qt::Orientation::Horizontal + + + + + + + + + + Analog Stick Anti-Deadzones + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + Qt::Orientation::Horizontal + + + + + + + Qt::Orientation::Horizontal + + + + + + @@ -2382,54 +2452,27 @@ - - - - - - - Analog Stick Deadzones - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - Qt::Horizontal - - - + + + 5 + + + 5 + + + 5 + + + 5 + - Qt::AlignCenter - - - - - - - - - - - Qt::Horizontal + Qt::AlignmentFlag::AlignCenter @@ -2439,7 +2482,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -2499,7 +2542,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2526,7 +2569,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2574,10 +2617,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -2604,10 +2647,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -2623,10 +2666,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -2643,10 +2686,10 @@ - Qt::Vertical + Qt::Orientation::Vertical - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -2668,7 +2711,7 @@ - QDialogButtonBox::Cancel|QDialogButtonBox::Reset|QDialogButtonBox::RestoreDefaults|QDialogButtonBox::Save + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Reset|QDialogButtonBox::StandardButton::RestoreDefaults|QDialogButtonBox::StandardButton::Save false diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index b6e24bba7b..e03a0aeff4 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -282,7 +282,7 @@ public: const QString pressure_deadzone = tr("Controls the deadzone of pressure sensitive buttons. It determines how far the button has to be pressed until it is recognized by the game. The resulting range will be projected onto the full button sensitivity range."); const QString squircle_factor = tr("The actual DualShock 3's stick range is not circular but formed like a rounded square (or squircle) which represents the maximum range of the emulated sticks. You can use the squircle values to modify the stick input if your sticks can't reach the corners of that range. A value of 0 does not apply any so called squircling. A value of 8000 is usually recommended."); const QString stick_multiplier = tr("The stick multipliers can be used to change the sensitivity of your stick movements.
The default setting is 1 and represents normal input."); - const QString stick_deadzones = tr("A stick's deadzone determines how far the stick has to be moved until it is fully recognized by the game. The resulting range will be projected onto the full input range in order to give you a smooth experience. Movement inside the deadzone is actually simulated as a real DualShock 3's deadzone of ~13%, so don't worry if there is still movement shown in the emulated stick preview."); + const QString stick_deadzones = tr("A stick's deadzone determines how far the stick has to be moved until it is fully recognized by the game. The resulting range will be projected onto the full input range in order to give you a smooth experience. Movement inside the deadzone is simulated using the anti-deadzone slider (default is 13%), so don't worry if there is still movement shown in the emulated stick preview."); const QString vibration = tr("The PS3 activates two motors (large and small) to handle controller vibrations.
You can enable, disable or even switch these signals for the currently selected pad here."); const QString motion_controls = tr("Use this to configure the gamepad motion controls."); const QString emulated_preview = tr("The emulated stick values (red dots) in the stick preview represent the actual stick positions as they will be visible to the game. The actual DualShock 3's stick range is not circular but formed like a rounded square (or squircle) which represents the maximum range of the emulated sticks. The blue regular dots represent the raw stick values (including stick multipliers) before they are converted for ingame usage.");