input: add vibration multiplier

This commit is contained in:
Megamouse 2025-01-21 02:56:45 +01:00
parent 9c5584956e
commit 1cff5b35d4
12 changed files with 68 additions and 78 deletions

View File

@ -32,6 +32,20 @@ std::string cfg_pad::get_buttons(std::vector<std::string> vec)
return fmt::merge(vec, ","); return fmt::merge(vec, ",");
} }
u8 cfg_pad::get_large_motor_speed(const std::array<VibrateMotor, 2>& motor_speed) const
{
const u8 idx = switch_vibration_motors ? 1 : 0;
const f32 multiplier = multiplier_vibration_motor_large / 100.0f;
return static_cast<u8>(std::clamp(motor_speed[idx].m_value * multiplier, 0.0f, 255.0f));
}
u8 cfg_pad::get_small_motor_speed(const std::array<VibrateMotor, 2>& motor_speed) const
{
const u8 idx = switch_vibration_motors ? 0 : 1;
const f32 multiplier = multiplier_vibration_motor_small / 100.0f;
return static_cast<u8>(std::clamp(motor_speed[idx].m_value * multiplier, 0.0f, 255.0f));
}
bool cfg_input::load(const std::string& title_id, const std::string& config_file, bool strict) bool cfg_input::load(const std::string& title_id, const std::string& config_file, bool strict)
{ {
input_log.notice("Loading pad config (title_id='%s', config_file='%s', strict=%d)", title_id, config_file, strict); input_log.notice("Loading pad config (title_id='%s', config_file='%s', strict=%d)", title_id, config_file, strict);

View File

@ -28,6 +28,9 @@ struct cfg_pad final : cfg::node
static std::vector<std::string> get_buttons(const std::string& str); static std::vector<std::string> get_buttons(const std::string& str);
static std::string get_buttons(std::vector<std::string> vec); static std::string get_buttons(std::vector<std::string> vec);
u8 get_large_motor_speed(const std::array<VibrateMotor, 2>& motor_speed) const;
u8 get_small_motor_speed(const std::array<VibrateMotor, 2>& motor_speed) const;
cfg::string ls_left{ this, "Left Stick Left", "" }; cfg::string ls_left{ this, "Left Stick Left", "" };
cfg::string ls_down{ this, "Left Stick Down", "" }; cfg::string ls_down{ this, "Left Stick Down", "" };
cfg::string ls_right{ this, "Left Stick Right", "" }; cfg::string ls_right{ this, "Left Stick Right", "" };
@ -96,8 +99,8 @@ struct cfg_pad final : cfg::node
cfg::uint<0, 100> led_battery_indicator_brightness{ this, "LED battery indicator brightness", 50 }; cfg::uint<0, 100> led_battery_indicator_brightness{ this, "LED battery indicator brightness", 50 };
cfg::_bool player_led_enabled{ this, "Player LED enabled", true }; cfg::_bool player_led_enabled{ this, "Player LED enabled", true };
cfg::_bool enable_vibration_motor_large{ this, "Enable Large Vibration Motor", true }; cfg::uint<0, 200> multiplier_vibration_motor_large{ this, "Large Vibration Motor Multiplier", 100 };
cfg::_bool enable_vibration_motor_small{ this, "Enable Small Vibration Motor", true }; cfg::uint<0, 200> multiplier_vibration_motor_small{ this, "Small Vibration Motor Multiplier", 100 };
cfg::_bool switch_vibration_motors{ this, "Switch Vibration Motors", false }; cfg::_bool switch_vibration_motors{ this, "Switch Vibration Motors", false };
cfg::_enum<mouse_movement_mode> mouse_move_mode{ this, "Mouse Movement Mode", mouse_movement_mode::relative }; cfg::_enum<mouse_movement_mode> mouse_move_mode{ this, "Mouse Movement Mode", mouse_movement_mode::relative };

View File

@ -551,11 +551,8 @@ void ds3_pad_handler::apply_pad_data(const pad_ensemble& binding)
cfg_pad* config = dev->config; cfg_pad* config = dev->config;
const int idx_l = config->switch_vibration_motors ? 1 : 0; const u8 speed_large = config->get_large_motor_speed(pad->m_vibrateMotors);
const int idx_s = config->switch_vibration_motors ? 0 : 1; const u8 speed_small = config->get_small_motor_speed(pad->m_vibrateMotors);
const u8 speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0;
const u8 speed_small = config->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0;
const bool wireless = dev->cable_state == 0; const bool wireless = dev->cable_state == 0;
const bool low_battery = dev->battery_level < 25; const bool low_battery = dev->battery_level < 25;

View File

@ -920,11 +920,8 @@ void ds4_pad_handler::apply_pad_data(const pad_ensemble& binding)
cfg_pad* config = dev->config; cfg_pad* config = dev->config;
// Attempt to send rumble no matter what // Attempt to send rumble no matter what
const int idx_l = config->switch_vibration_motors ? 1 : 0; const u8 speed_large = config->get_large_motor_speed(pad->m_vibrateMotors);
const int idx_s = config->switch_vibration_motors ? 0 : 1; const u8 speed_small = config->get_small_motor_speed(pad->m_vibrateMotors);
const u8 speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0;
const u8 speed_small = config->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0;
const bool wireless = dev->cable_state == 0; const bool wireless = dev->cable_state == 0;
const bool low_battery = dev->battery_level < 2; const bool low_battery = dev->battery_level < 2;

View File

@ -941,11 +941,8 @@ void dualsense_pad_handler::apply_pad_data(const pad_ensemble& binding)
cfg_pad* config = dev->config; cfg_pad* config = dev->config;
// Attempt to send rumble no matter what // Attempt to send rumble no matter what
const int idx_l = config->switch_vibration_motors ? 1 : 0; const u8 speed_large = config->get_large_motor_speed(pad->m_vibrateMotors);
const int idx_s = config->switch_vibration_motors ? 0 : 1; const u8 speed_small = config->get_small_motor_speed(pad->m_vibrateMotors);
const u8 speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0;
const u8 speed_small = config->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0;
const bool wireless = dev->cable_state == 0; const bool wireless = dev->cable_state == 0;
const bool low_battery = dev->battery_level <= 1; const bool low_battery = dev->battery_level <= 1;

View File

@ -1271,10 +1271,8 @@ void evdev_joystick_handler::apply_pad_data(const pad_ensemble& binding)
return; return;
// Handle vibration // Handle vibration
const int idx_l = cfg->switch_vibration_motors ? 1 : 0; const u8 force_large = cfg->get_large_motor_speed(pad->m_vibrateMotors);
const int idx_s = cfg->switch_vibration_motors ? 0 : 1; const u8 force_small = cfg->get_small_motor_speed(pad->m_vibrateMotors);
const u8 force_large = cfg->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value * 257 : 0;
const u8 force_small = cfg->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value * 257 : 0;
SetRumble(evdev_device, force_large, force_small); SetRumble(evdev_device, force_large, force_small);
} }

View File

@ -820,9 +820,7 @@ void ps_move_handler::apply_pad_data(const pad_ensemble& binding)
cfg_pad* config = dev->config; cfg_pad* config = dev->config;
const int idx_l = config->switch_vibration_motors ? 1 : 0; const u8 speed_large = config->get_large_motor_speed(pad->m_vibrateMotors);
const u8 speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0;
dev->new_output_data |= dev->large_motor != speed_large; dev->new_output_data |= dev->large_motor != speed_large;
dev->large_motor = speed_large; dev->large_motor = speed_large;

View File

@ -800,13 +800,10 @@ void sdl_pad_handler::apply_pad_data(const pad_ensemble& binding)
// The left motor is the low-frequency rumble motor. The right motor is the high-frequency rumble motor. // The left motor is the low-frequency rumble motor. The right motor is the high-frequency rumble motor.
// The two motors are not the same, and they create different vibration effects. Values range between 0 to 65535. // The two motors are not the same, and they create different vibration effects. Values range between 0 to 65535.
const usz idx_l = cfg->switch_vibration_motors ? 1 : 0;
const usz idx_s = cfg->switch_vibration_motors ? 0 : 1;
if (dev->sdl.has_rumble || dev->sdl.has_rumble_triggers) if (dev->sdl.has_rumble || dev->sdl.has_rumble_triggers)
{ {
const u8 speed_large = cfg->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0; const u8 speed_large = cfg->get_large_motor_speed(pad->m_vibrateMotors);
const u8 speed_small = cfg->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0; const u8 speed_small = cfg->get_small_motor_speed(pad->m_vibrateMotors);
dev->new_output_data |= dev->large_motor != speed_large || dev->small_motor != speed_small; dev->new_output_data |= dev->large_motor != speed_large || dev->small_motor != speed_small;

View File

@ -575,11 +575,8 @@ void xinput_pad_handler::apply_pad_data(const pad_ensemble& binding)
// The left motor is the low-frequency rumble motor. The right motor is the high-frequency rumble motor. // The left motor is the low-frequency rumble motor. The right motor is the high-frequency rumble motor.
// The two motors are not the same, and they create different vibration effects. Values range between 0 to 65535. // The two motors are not the same, and they create different vibration effects. Values range between 0 to 65535.
const usz idx_l = cfg->switch_vibration_motors ? 1 : 0; const u8 speed_large = cfg->get_large_motor_speed(pad->m_vibrateMotors);
const usz idx_s = cfg->switch_vibration_motors ? 0 : 1; const u8 speed_small = cfg->get_small_motor_speed(pad->m_vibrateMotors);
const u8 speed_large = cfg->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0;
const u8 speed_small = cfg->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : 0;
dev->new_output_data |= dev->large_motor != speed_large || dev->small_motor != speed_small; dev->new_output_data |= dev->large_motor != speed_large || dev->small_motor != speed_small;

View File

@ -332,33 +332,25 @@ void pad_settings_dialog::InitButtons()
} }
}); });
connect(ui->chb_vibration_large, &QCheckBox::clicked, this, [this](bool checked) connect(ui->sb_vibration_large, &QSpinBox::valueChanged, this, [this](int value)
{ {
if (!checked) const u8 force = static_cast<u8>(std::clamp(m_max_force * (value / 100.0f), 0.0f, 255.0f));
{ ui->chb_vibration_switch->isChecked() ? SetPadData(m_min_force, force)
return; : SetPadData(force, m_min_force);
}
ui->chb_vibration_switch->isChecked() ? SetPadData(m_min_force, m_max_force) QTimer::singleShot(300, this, [this]()
: SetPadData(m_max_force, m_min_force);
QTimer::singleShot(300, [this]()
{ {
SetPadData(m_min_force, m_min_force); SetPadData(m_min_force, m_min_force);
}); });
}); });
connect(ui->chb_vibration_small, &QCheckBox::clicked, this, [this](bool checked) connect(ui->sb_vibration_small, &QSpinBox::valueChanged, this, [this](int value)
{ {
if (!checked) const u8 force = static_cast<u8>(std::clamp(m_max_force * (value / 100.0f), 0.0f, 255.0f));
{ ui->chb_vibration_switch->isChecked() ? SetPadData(force, m_min_force)
return; : SetPadData(m_min_force, force);
}
ui->chb_vibration_switch->isChecked() ? SetPadData(m_max_force, m_min_force) QTimer::singleShot(300, this, [this]()
: SetPadData(m_min_force, m_max_force);
QTimer::singleShot(300, [this]()
{ {
SetPadData(m_min_force, m_min_force); SetPadData(m_min_force, m_min_force);
}); });
@ -369,12 +361,12 @@ void pad_settings_dialog::InitButtons()
checked ? SetPadData(m_min_force, m_max_force) checked ? SetPadData(m_min_force, m_max_force)
: SetPadData(m_max_force, m_min_force); : SetPadData(m_max_force, m_min_force);
QTimer::singleShot(200, [this, checked]() QTimer::singleShot(200, this, [this, checked]()
{ {
checked ? SetPadData(m_max_force, m_min_force) checked ? SetPadData(m_max_force, m_min_force)
: SetPadData(m_min_force, m_max_force); : SetPadData(m_min_force, m_max_force);
QTimer::singleShot(200, [this]() QTimer::singleShot(200, this, [this]()
{ {
SetPadData(m_min_force, m_min_force); SetPadData(m_min_force, m_min_force);
}); });
@ -618,12 +610,12 @@ void pad_settings_dialog::RefreshPads()
} }
} }
void pad_settings_dialog::SetPadData(u32 large_motor, u32 small_motor, bool led_battery_indicator) void pad_settings_dialog::SetPadData(u8 large_motor, u8 small_motor, bool led_battery_indicator)
{ {
ensure(m_handler);
const cfg_pad& cfg = GetPlayerConfig(); const cfg_pad& cfg = GetPlayerConfig();
std::lock_guard lock(m_handler_mutex); std::lock_guard lock(m_handler_mutex);
ensure(m_handler);
m_handler->SetPadData(m_device_name, GetPlayerIndex(), large_motor, small_motor, cfg.colorR, cfg.colorG, cfg.colorB, cfg.player_led_enabled.get(), led_battery_indicator, cfg.led_battery_indicator_brightness); m_handler->SetPadData(m_device_name, GetPlayerIndex(), large_motor, small_motor, cfg.colorR, cfg.colorG, cfg.colorB, cfg.player_led_enabled.get(), led_battery_indicator, cfg.led_battery_indicator_brightness);
} }
@ -1116,8 +1108,12 @@ void pad_settings_dialog::UpdateLabels(bool is_reset)
} }
} }
ui->chb_vibration_large->setChecked(cfg.enable_vibration_motor_large.get()); ui->sb_vibration_large->setRange(cfg.multiplier_vibration_motor_large.min, cfg.multiplier_vibration_motor_large.max);
ui->chb_vibration_small->setChecked(cfg.enable_vibration_motor_small.get()); ui->sb_vibration_large->setValue(cfg.multiplier_vibration_motor_large.get());
ui->sb_vibration_small->setRange(cfg.multiplier_vibration_motor_small.min, cfg.multiplier_vibration_motor_small.max);
ui->sb_vibration_small->setValue(cfg.multiplier_vibration_motor_small.get());
ui->chb_vibration_switch->setChecked(cfg.switch_vibration_motors.get()); ui->chb_vibration_switch->setChecked(cfg.switch_vibration_motors.get());
// Update Trigger Thresholds // Update Trigger Thresholds
@ -1448,10 +1444,6 @@ void pad_settings_dialog::ChangeHandler()
} }
ui->l_description->setText(m_description); ui->l_description->setText(m_description);
// Update parameters
m_min_force = 0;
m_max_force = 255;
// Reset parameters // Reset parameters
m_lx = 0; m_lx = 0;
m_ly = 0; m_ly = 0;
@ -1873,8 +1865,8 @@ void pad_settings_dialog::ApplyCurrentPlayerConfig(int new_player_id)
if (m_handler->has_rumble()) if (m_handler->has_rumble())
{ {
cfg.enable_vibration_motor_large.set(ui->chb_vibration_large->isChecked()); cfg.multiplier_vibration_motor_large.set(ui->sb_vibration_large->value());
cfg.enable_vibration_motor_small.set(ui->chb_vibration_small->isChecked()); cfg.multiplier_vibration_motor_small.set(ui->sb_vibration_small->value());
cfg.switch_vibration_motors.set(ui->chb_vibration_switch->isChecked()); cfg.switch_vibration_motors.set(ui->chb_vibration_switch->isChecked());
} }

View File

@ -139,8 +139,8 @@ private:
int m_ry = 0; int m_ry = 0;
// Rumble // Rumble
s32 m_min_force = 0; static constexpr u8 m_min_force = 0;
s32 m_max_force = 0; static constexpr u8 m_max_force = 255;
// Backup for standard button palette // Backup for standard button palette
QPalette m_palette; QPalette m_palette;
@ -190,7 +190,7 @@ private:
void CancelExit(); void CancelExit();
// Set vibrate data while keeping the current color // Set vibrate data while keeping the current color
void SetPadData(u32 large_motor, u32 small_motor, bool led_battery_indicator = false); void SetPadData(u8 large_motor, u8 small_motor, bool led_battery_indicator = false);
/** Update all the Button Labels with current button mapping */ /** Update all the Button Labels with current button mapping */
void UpdateLabels(bool is_reset = false); void UpdateLabels(bool is_reset = false);

View File

@ -937,7 +937,7 @@
<property name="title"> <property name="title">
<string>Enable Vibration</string> <string>Enable Vibration</string>
</property> </property>
<layout class="QHBoxLayout" name="gb_vibration_layout"> <layout class="QHBoxLayout" name="gb_vibration_layout" stretch="1,1,1">
<property name="leftMargin"> <property name="leftMargin">
<number>5</number> <number>5</number>
</property> </property>
@ -951,22 +951,22 @@
<number>5</number> <number>5</number>
</property> </property>
<item> <item>
<widget class="QCheckBox" name="chb_vibration_large"> <widget class="QSpinBox" name="sb_vibration_large">
<property name="text"> <property name="suffix">
<string>Large</string> <string>%</string>
</property> </property>
<property name="checked"> <property name="prefix">
<bool>true</bool> <string>Large </string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="chb_vibration_small"> <widget class="QSpinBox" name="sb_vibration_small">
<property name="text"> <property name="suffix">
<string>Small</string> <string>%</string>
</property> </property>
<property name="checked"> <property name="prefix">
<bool>true</bool> <string>Small </string>
</property> </property>
</widget> </widget>
</item> </item>