Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Input: Implement pressure sensitivity deadzone #14557

Merged
merged 2 commits into from Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 21 additions & 17 deletions rpcs3/Emu/Io/PadHandler.cpp
Expand Up @@ -55,15 +55,14 @@ u16 PadHandlerBase::NormalizeTriggerInput(u16 value, int threshold) const
{
return static_cast<u16>(0);
}
else if (threshold <= trigger_min)

if (threshold <= trigger_min)
{
return static_cast<u16>(ScaledInput(value, trigger_min, trigger_max));
}
else
{
const s32 val = static_cast<s32>(static_cast<f32>(trigger_max) * (value - threshold) / (trigger_max - threshold));
return static_cast<u16>(ScaledInput(val, trigger_min, trigger_max));
}

const s32 val = static_cast<s32>(static_cast<f32>(trigger_max) * (value - threshold) / (trigger_max - threshold));
return static_cast<u16>(ScaledInput(val, trigger_min, trigger_max));
}

// normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions
Expand All @@ -81,11 +80,9 @@ u16 PadHandlerBase::NormalizeDirectedInput(s32 raw_value, s32 threshold, s32 max
{
return static_cast<u16>(255.0f * val);
}
else
{
const f32 thresh = static_cast<f32>(threshold) / maximum; // threshold converted to [0, 1]
return static_cast<u16>(255.0f * std::min(1.0f, (val - thresh) / (1.0f - thresh)));
}

const f32 thresh = static_cast<f32>(threshold) / maximum; // threshold converted to [0, 1]
return static_cast<u16>(255.0f * std::clamp((val - thresh) / (1.0f - thresh), 0.0f, 1.0f));
}

u16 PadHandlerBase::NormalizeStickInput(u16 raw_value, int threshold, int multiplier, bool ignore_threshold) const
Expand All @@ -96,10 +93,8 @@ u16 PadHandlerBase::NormalizeStickInput(u16 raw_value, int threshold, int multip
{
return static_cast<u16>(ScaledInput(scaled_value, 0, thumb_max));
}
else
{
return NormalizeDirectedInput(scaled_value, threshold, thumb_max);
}

return NormalizeDirectedInput(scaled_value, threshold, thumb_max);
}

// This function normalizes stick deadzone based on the DS3's deadzone, which is ~13%
Expand Down Expand Up @@ -583,7 +578,8 @@ void PadHandlerBase::get_mapping(const pad_ensemble& binding)

// Find out if special buttons are pressed (introduced by RPCS3).
// These buttons will have a delay of one cycle, but whatever.
const bool adjust_pressure = pad->get_pressure_intensity_enabled(cfg->pressure_intensity_toggle_mode.get());
const bool adjust_pressure = pad->get_pressure_intensity_button_active(cfg->pressure_intensity_toggle_mode.get());
const u32 pressure_intensity_deadzone = cfg->pressure_intensity_deadzone.get();

// Translate any corresponding keycodes to our normal DS3 buttons and triggers
for (Button& button : pad->m_buttons)
Expand All @@ -605,9 +601,17 @@ void PadHandlerBase::get_mapping(const pad_ensemble& binding)
{
val = pad->m_pressure_intensity;
}
else if (pressure_intensity_deadzone > 0)
{
// Ignore triggers, since they have their own deadzones
if (!get_is_left_trigger(device, code) && !get_is_right_trigger(device, code))
{
val = NormalizeDirectedInput(val, pressure_intensity_deadzone, 255);
}
}

value = std::max(value, val);
pressed = true;
pressed = value > 0;
}
}

Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Io/pad_config.h
Expand Up @@ -62,6 +62,7 @@ struct cfg_pad final : cfg::node
cfg::string pressure_intensity_button{ this, "Pressure Intensity Button", "" };
cfg::uint<0, 100> pressure_intensity{ this, "Pressure Intensity Percent", 50 };
cfg::_bool pressure_intensity_toggle_mode{ this, "Pressure Intensity Toggle Mode", false };
cfg::uint<0, 255> pressure_intensity_deadzone{ this, "Pressure Intensity Deadzone", 0 };

cfg::uint<0, 200> lstickmultiplier{ this, "Left Stick Multiplier", 100 };
cfg::uint<0, 200> rstickmultiplier{ this, "Right Stick Multiplier", 100 };
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Io/pad_types.cpp
Expand Up @@ -132,7 +132,7 @@ u32 get_axis_keycode(u32 offset, u16 value)
}
}

bool Pad::get_pressure_intensity_enabled(bool is_toggle_mode)
bool Pad::get_pressure_intensity_button_active(bool is_toggle_mode)
{
if (m_pressure_intensity_button_index < 0)
{
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Io/pad_types.h
Expand Up @@ -430,7 +430,7 @@ struct Pad
bool m_pressure_intensity_toggled{}; // Whether the sensitivity is toggled on or off.
u8 m_pressure_intensity{127}; // 0-255
bool m_adjust_pressure_last{}; // only used in keyboard_pad_handler
bool get_pressure_intensity_enabled(bool is_toggle_mode);
bool get_pressure_intensity_button_active(bool is_toggle_mode);

// Cable State: 0 - 1 plugged in ?
u8 m_cable_state{0};
Expand Down
13 changes: 11 additions & 2 deletions rpcs3/Input/evdev_joystick_handler.cpp
Expand Up @@ -1079,7 +1079,8 @@ void evdev_joystick_handler::apply_input_events(const std::shared_ptr<Pad>& pad)

// Find out if special buttons are pressed (introduced by RPCS3).
// These buttons will have a delay of one cycle, but whatever.
const bool adjust_pressure = pad->get_pressure_intensity_enabled(cfg->pressure_intensity_toggle_mode.get());
const bool adjust_pressure = pad->get_pressure_intensity_button_active(cfg->pressure_intensity_toggle_mode.get());
const u32 pressure_intensity_deadzone = cfg->pressure_intensity_deadzone.get();

const auto update_values = [&](bool& pressed, u16& final_value, bool is_stick_value, u32 code, u16 val)
{
Expand All @@ -1095,10 +1096,18 @@ void evdev_joystick_handler::apply_input_events(const std::shared_ptr<Pad>& pad)
{
val = pad->m_pressure_intensity;
}
else if (pressure_intensity_deadzone > 0)
{
// Ignore triggers, since they have their own deadzones
if (!get_is_left_trigger(m_dev, code) && !get_is_right_trigger(m_dev, code))
{
val = NormalizeDirectedInput(val, pressure_intensity_deadzone, 255);
}
}
}

pressed = true;
final_value = std::max(final_value, val);
pressed = final_value > 0;
}
};

Expand Down
23 changes: 18 additions & 5 deletions rpcs3/Input/keyboard_pad_handler.cpp
Expand Up @@ -112,7 +112,7 @@ void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
}
}

const bool adjust_pressure = pad.get_pressure_intensity_enabled(m_pressure_intensity_toggle_mode);
const bool adjust_pressure = pad.get_pressure_intensity_button_active(m_pressure_intensity_toggle_mode);
const bool adjust_pressure_changed = pad.m_adjust_pressure_last != adjust_pressure;

if (adjust_pressure_changed)
Expand Down Expand Up @@ -153,16 +153,28 @@ void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)

if (update_button)
{
button.m_pressed = button.m_actual_value > 0;

if (button.m_pressed)
if (button.m_actual_value > 0)
{
// Modify pressure if necessary if the button was pressed
button.m_value = adjust_pressure ? pad.m_pressure_intensity : button.m_actual_value;
if (adjust_pressure)
{
button.m_value = pad.m_pressure_intensity;
}
else if (m_pressure_intensity_deadzone > 0)
{
button.m_value = NormalizeDirectedInput(button.m_actual_value, m_pressure_intensity_deadzone, 255);
}
else
{
button.m_value = button.m_actual_value;
}

button.m_pressed = button.m_value > 0;
}
else
{
button.m_value = 0;
button.m_pressed = false;
}
}
}
Expand Down Expand Up @@ -886,6 +898,7 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, u8 player_i
m_l_stick_multiplier = cfg->lstickmultiplier;
m_r_stick_multiplier = cfg->rstickmultiplier;
m_pressure_intensity_toggle_mode = cfg->pressure_intensity_toggle_mode.get();
m_pressure_intensity_deadzone = cfg->pressure_intensity_deadzone.get();

const auto find_keys = [this](const cfg::string& name)
{
Expand Down
3 changes: 2 additions & 1 deletion rpcs3/Input/keyboard_pad_handler.h
Expand Up @@ -116,7 +116,8 @@ class keyboard_pad_handler final : public QObject, public PadHandlerBase
steady_clock::time_point m_button_time;
f32 m_analog_lerp_factor = 1.0f;
f32 m_trigger_lerp_factor = 1.0f;
bool m_pressure_intensity_toggle_mode{};
bool m_pressure_intensity_toggle_mode = false;
u32 m_pressure_intensity_deadzone = 0;

// Stick Movements
steady_clock::time_point m_stick_time;
Expand Down
8 changes: 8 additions & 0 deletions rpcs3/rpcs3qt/pad_settings_dialog.cpp
Expand Up @@ -1178,6 +1178,11 @@ void pad_settings_dialog::UpdateLabels(bool is_reset)
// Update pressure sensitivity toggle mode
ui->cb_pressure_intensity_toggle_mode->setChecked(cfg.pressure_intensity_toggle_mode.get());

// Update pressure sensitivity deadzone
range = cfg.pressure_intensity_deadzone.to_list();
ui->pressure_intensity_deadzone->setRange(std::stoi(range.front()), std::stoi(range.back()));
ui->pressure_intensity_deadzone->setValue(cfg.pressure_intensity_deadzone.get());

// Apply stored/default LED settings to the device
m_enable_led = m_handler->has_led();
SetPadData(0, 0);
Expand Down Expand Up @@ -1813,6 +1818,8 @@ void pad_settings_dialog::ApplyCurrentPlayerConfig(int new_player_id)
cfg.pressure_intensity_toggle_mode.set(ui->cb_pressure_intensity_toggle_mode->isChecked());
}

cfg.pressure_intensity_deadzone.set(ui->pressure_intensity_deadzone->value());

if (m_handler->m_type == pad_handler::keyboard)
{
const int mouse_move_mode = ui->mouse_movement->currentData().toInt();
Expand Down Expand Up @@ -1961,6 +1968,7 @@ void pad_settings_dialog::SubscribeTooltips()
const Tooltips tooltips;

SubscribeTooltip(ui->gb_pressure_intensity, tooltips.gamepad_settings.pressure_intensity);
SubscribeTooltip(ui->gb_pressure_intensity_deadzone, tooltips.gamepad_settings.pressure_deadzone);
SubscribeTooltip(ui->gb_squircle, tooltips.gamepad_settings.squircle_factor);
SubscribeTooltip(ui->gb_stick_multi, tooltips.gamepad_settings.stick_multiplier);
SubscribeTooltip(ui->gb_kb_stick_multi, tooltips.gamepad_settings.stick_multiplier);
Expand Down
72 changes: 44 additions & 28 deletions rpcs3/rpcs3qt/pad_settings_dialog.ui
Expand Up @@ -717,6 +717,22 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_pressure_intensity_deadzone">
<property name="title">
<string>Pressure Sensitivity Deadzone</string>
</property>
<layout class="QHBoxLayout" name="layout_gb_pressure_intensity_deadzone">
<item>
<widget class="QSlider" name="pressure_intensity_deadzone">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="left_stack">
<property name="lineWidth">
Expand Down Expand Up @@ -850,34 +866,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_stick_preview">
<property name="title">
<string>Stick Preview</string>
</property>
<layout class="QVBoxLayout" name="gb_stick_preview_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QCheckBox" name="chb_show_emulated_values">
<property name="text">
<string>Show Emulated Values</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="pad_page_spacer">
<property name="orientation">
Expand Down Expand Up @@ -2369,6 +2357,34 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_stick_preview">
<property name="title">
<string>Stick Preview</string>
</property>
<layout class="QVBoxLayout" name="gb_stick_preview_layout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QCheckBox" name="chb_show_emulated_values">
<property name="text">
<string>Show Emulated Values</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_sticks">
<property name="title">
Expand Down
1 change: 1 addition & 0 deletions rpcs3/rpcs3qt/tooltips.h
Expand Up @@ -270,6 +270,7 @@ class Tooltips : public QObject
const QString sdl = tr("The SDL handler supports a variety of controllers across different platforms.");

const QString pressure_intensity = tr("Controls the intensity of pressure sensitive buttons while this special button is pressed.<br>Enable \"Toggle\" if you want to toggle the intensity on button press instead.<br>Use the percentage to change how hard you want to press a button.");
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.<br>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.");
Expand Down