From 694c07865591782887ed4f263de162b60febe755 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Wed, 2 Feb 2022 14:53:15 -0600 Subject: [PATCH] yuzu: config: Vibrate the controller while configuring vibration strength --- src/yuzu/applets/qt_controller.cpp | 2 +- src/yuzu/configuration/configure_input.cpp | 2 +- .../configuration/configure_vibration.cpp | 74 ++++++++++++++++++- src/yuzu/configuration/configure_vibration.h | 18 ++++- src/yuzu/configuration/configure_vibration.ui | 7 ++ 5 files changed, 95 insertions(+), 8 deletions(-) diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index 4239c17f57..4104928d11 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -257,7 +257,7 @@ void QtControllerSelectorDialog::LoadConfiguration() { } void QtControllerSelectorDialog::CallConfigureVibrationDialog() { - ConfigureVibration dialog(this); + ConfigureVibration dialog(this, system.HIDCore()); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint); diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index d53179dbbb..7c57761899 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -164,7 +164,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, }); connect(ui->vibrationButton, &QPushButton::clicked, - [this] { CallConfigureDialog(*this); }); + [this, &hid_core] { CallConfigureDialog(*this, hid_core); }); connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] { CallConfigureDialog(*this, input_subsystem); diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp index adce04b278..779b6401c9 100644 --- a/src/yuzu/configuration/configure_vibration.cpp +++ b/src/yuzu/configuration/configure_vibration.cpp @@ -9,11 +9,14 @@ #include "common/param_package.h" #include "common/settings.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" #include "ui_configure_vibration.h" #include "yuzu/configuration/configure_vibration.h" -ConfigureVibration::ConfigureVibration(QWidget* parent) - : QDialog(parent), ui(std::make_unique()) { +ConfigureVibration::ConfigureVibration(QWidget* parent, Core::HID::HIDCore& hid_core_) + : QDialog(parent), ui(std::make_unique()), hid_core{hid_core_} { ui->setupUi(this); vibration_groupboxes = { @@ -31,6 +34,13 @@ ConfigureVibration::ConfigureVibration(QWidget* parent) const auto& players = Settings::values.players.GetValue(); for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { + auto controller = hid_core.GetEmulatedControllerByIndex(i); + Core::HID::ControllerUpdateCallback engine_callback{ + .on_change = [this, + i](Core::HID::ControllerTriggerType type) { VibrateController(type, i); }, + .is_npad_service = false, + }; + controller_callback_key[i] = controller->SetCallback(engine_callback); vibration_groupboxes[i]->setChecked(players[i].vibration_enabled); vibration_spinboxes[i]->setValue(players[i].vibration_strength); } @@ -45,7 +55,14 @@ ConfigureVibration::ConfigureVibration(QWidget* parent) RetranslateUI(); } -ConfigureVibration::~ConfigureVibration() = default; +ConfigureVibration::~ConfigureVibration() { + StopVibrations(); + + for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { + auto controller = hid_core.GetEmulatedControllerByIndex(i); + controller->DeleteCallback(controller_callback_key[i]); + } +}; void ConfigureVibration::ApplyConfiguration() { auto& players = Settings::values.players.GetValue(); @@ -70,3 +87,54 @@ void ConfigureVibration::changeEvent(QEvent* event) { void ConfigureVibration::RetranslateUI() { ui->retranslateUi(this); } + +void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type, + std::size_t player_index) { + if (type != Core::HID::ControllerTriggerType::Button) { + return; + } + + auto& player = Settings::values.players.GetValue()[player_index]; + auto controller = hid_core.GetEmulatedControllerByIndex(player_index); + const int vibration_strenght = vibration_spinboxes[player_index]->value(); + const auto& buttons = controller->GetButtonsValues(); + + bool button_is_pressed = false; + for (std::size_t i = 0; i < buttons.size(); ++i) { + if (buttons[i].value) { + button_is_pressed = true; + break; + } + } + + if (!button_is_pressed) { + StopVibrations(); + return; + } + + const int old_vibration_enabled = player.vibration_enabled; + const bool old_vibration_strenght = player.vibration_strength; + player.vibration_enabled = true; + player.vibration_strength = vibration_strenght; + + const Core::HID::VibrationValue vibration{ + .low_amplitude = 1.0f, + .low_frequency = 160.0f, + .high_amplitude = 1.0f, + .high_frequency = 320.0f, + }; + controller->SetVibration(0, vibration); + controller->SetVibration(1, vibration); + + // Restore previous values + player.vibration_enabled = old_vibration_enabled; + player.vibration_strength = old_vibration_strenght; +} + +void ConfigureVibration::StopVibrations() { + for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { + auto controller = hid_core.GetEmulatedControllerByIndex(i); + controller->SetVibration(0, Core::HID::DEFAULT_VIBRATION_VALUE); + controller->SetVibration(1, Core::HID::DEFAULT_VIBRATION_VALUE); + } +} diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h index 37bbc26536..50b8195fae 100644 --- a/src/yuzu/configuration/configure_vibration.h +++ b/src/yuzu/configuration/configure_vibration.h @@ -15,11 +15,16 @@ namespace Ui { class ConfigureVibration; } +namespace Core::HID { +enum class ControllerTriggerType; +class HIDCore; +} // namespace Core::HID + class ConfigureVibration : public QDialog { Q_OBJECT public: - explicit ConfigureVibration(QWidget* parent); + explicit ConfigureVibration(QWidget* parent, Core::HID::HIDCore& hid_core_); ~ConfigureVibration() override; void ApplyConfiguration(); @@ -27,14 +32,21 @@ public: private: void changeEvent(QEvent* event) override; void RetranslateUI(); + void VibrateController(Core::HID::ControllerTriggerType type, std::size_t player_index); + void StopVibrations(); std::unique_ptr ui; static constexpr std::size_t NUM_PLAYERS = 8; - // Groupboxes encapsulating the vibration strength spinbox. + /// Groupboxes encapsulating the vibration strength spinbox. std::array vibration_groupboxes; - // Spinboxes representing the vibration strength percentage. + /// Spinboxes representing the vibration strength percentage. std::array vibration_spinboxes; + + /// Callback index to stop the controllers events + std::array controller_callback_key; + + Core::HID::HIDCore& hid_core; }; diff --git a/src/yuzu/configuration/configure_vibration.ui b/src/yuzu/configuration/configure_vibration.ui index efdf317a95..447a18eb12 100644 --- a/src/yuzu/configuration/configure_vibration.ui +++ b/src/yuzu/configuration/configure_vibration.ui @@ -17,6 +17,13 @@ + + + + Press any controller button to vibrate the controller. + + +