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, ",");
}
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)
{
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::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_down{ this, "Left Stick Down", "" };
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::_bool player_led_enabled{ this, "Player LED enabled", true };
cfg::_bool enable_vibration_motor_large{ this, "Enable Large Vibration Motor", true };
cfg::_bool enable_vibration_motor_small{ this, "Enable Small Vibration Motor", true };
cfg::uint<0, 200> multiplier_vibration_motor_large{ this, "Large Vibration Motor Multiplier", 100 };
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::_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;
const int idx_l = config->switch_vibration_motors ? 1 : 0;
const int idx_s = config->switch_vibration_motors ? 0 : 1;
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 u8 speed_large = config->get_large_motor_speed(pad->m_vibrateMotors);
const u8 speed_small = config->get_small_motor_speed(pad->m_vibrateMotors);
const bool wireless = dev->cable_state == 0;
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;
// Attempt to send rumble no matter what
const int idx_l = config->switch_vibration_motors ? 1 : 0;
const int idx_s = config->switch_vibration_motors ? 0 : 1;
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 u8 speed_large = config->get_large_motor_speed(pad->m_vibrateMotors);
const u8 speed_small = config->get_small_motor_speed(pad->m_vibrateMotors);
const bool wireless = dev->cable_state == 0;
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;
// Attempt to send rumble no matter what
const int idx_l = config->switch_vibration_motors ? 1 : 0;
const int idx_s = config->switch_vibration_motors ? 0 : 1;
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 u8 speed_large = config->get_large_motor_speed(pad->m_vibrateMotors);
const u8 speed_small = config->get_small_motor_speed(pad->m_vibrateMotors);
const bool wireless = dev->cable_state == 0;
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;
// Handle vibration
const int idx_l = cfg->switch_vibration_motors ? 1 : 0;
const int idx_s = cfg->switch_vibration_motors ? 0 : 1;
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;
const u8 force_large = cfg->get_large_motor_speed(pad->m_vibrateMotors);
const u8 force_small = cfg->get_small_motor_speed(pad->m_vibrateMotors);
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;
const int idx_l = config->switch_vibration_motors ? 1 : 0;
const u8 speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : 0;
const u8 speed_large = config->get_large_motor_speed(pad->m_vibrateMotors);
dev->new_output_data |= 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 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)
{
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;
const u8 speed_large = cfg->get_large_motor_speed(pad->m_vibrateMotors);
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;

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 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;
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;
const u8 speed_large = cfg->get_large_motor_speed(pad->m_vibrateMotors);
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;

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)
{
return;
}
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)
: SetPadData(force, m_min_force);
ui->chb_vibration_switch->isChecked() ? SetPadData(m_min_force, m_max_force)
: SetPadData(m_max_force, m_min_force);
QTimer::singleShot(300, [this]()
QTimer::singleShot(300, this, [this]()
{
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)
{
return;
}
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)
: SetPadData(m_min_force, force);
ui->chb_vibration_switch->isChecked() ? SetPadData(m_max_force, m_min_force)
: SetPadData(m_min_force, m_max_force);
QTimer::singleShot(300, [this]()
QTimer::singleShot(300, this, [this]()
{
SetPadData(m_min_force, m_min_force);
});
@ -369,12 +361,12 @@ void pad_settings_dialog::InitButtons()
checked ? SetPadData(m_min_force, m_max_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)
: SetPadData(m_min_force, m_max_force);
QTimer::singleShot(200, [this]()
QTimer::singleShot(200, this, [this]()
{
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();
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);
}
@ -1116,8 +1108,12 @@ void pad_settings_dialog::UpdateLabels(bool is_reset)
}
}
ui->chb_vibration_large->setChecked(cfg.enable_vibration_motor_large.get());
ui->chb_vibration_small->setChecked(cfg.enable_vibration_motor_small.get());
ui->sb_vibration_large->setRange(cfg.multiplier_vibration_motor_large.min, cfg.multiplier_vibration_motor_large.max);
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());
// Update Trigger Thresholds
@ -1448,10 +1444,6 @@ void pad_settings_dialog::ChangeHandler()
}
ui->l_description->setText(m_description);
// Update parameters
m_min_force = 0;
m_max_force = 255;
// Reset parameters
m_lx = 0;
m_ly = 0;
@ -1873,8 +1865,8 @@ void pad_settings_dialog::ApplyCurrentPlayerConfig(int new_player_id)
if (m_handler->has_rumble())
{
cfg.enable_vibration_motor_large.set(ui->chb_vibration_large->isChecked());
cfg.enable_vibration_motor_small.set(ui->chb_vibration_small->isChecked());
cfg.multiplier_vibration_motor_large.set(ui->sb_vibration_large->value());
cfg.multiplier_vibration_motor_small.set(ui->sb_vibration_small->value());
cfg.switch_vibration_motors.set(ui->chb_vibration_switch->isChecked());
}

View File

@ -139,8 +139,8 @@ private:
int m_ry = 0;
// Rumble
s32 m_min_force = 0;
s32 m_max_force = 0;
static constexpr u8 m_min_force = 0;
static constexpr u8 m_max_force = 255;
// Backup for standard button palette
QPalette m_palette;
@ -190,7 +190,7 @@ private:
void CancelExit();
// 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 */
void UpdateLabels(bool is_reset = false);

View File

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