summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dist/qt_themes/qdarkstyle/style.qss11
-rw-r--r--dist/qt_themes/qdarkstyle_midnight_blue/style.qss12
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp13
-rw-r--r--src/core/settings.h1
-rw-r--r--src/input_common/settings.h3
-rw-r--r--src/yuzu/CMakeLists.txt3
-rw-r--r--src/yuzu/applets/controller.cpp16
-rw-r--r--src/yuzu/applets/controller.h3
-rw-r--r--src/yuzu/applets/controller.ui18
-rw-r--r--src/yuzu/configuration/config.cpp16
-rw-r--r--src/yuzu/configuration/configure_input.cpp4
-rw-r--r--src/yuzu/configuration/configure_input.ui22
-rw-r--r--src/yuzu/configuration/configure_vibration.cpp66
-rw-r--r--src/yuzu/configuration/configure_vibration.h40
-rw-r--r--src/yuzu/configuration/configure_vibration.ui546
-rw-r--r--src/yuzu_cmd/config.cpp2
-rw-r--r--src/yuzu_cmd/default_ini.h4
-rw-r--r--src/yuzu_tester/config.cpp1
18 files changed, 751 insertions, 30 deletions
diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss
index aca6531ac..2a1e8ddeb 100644
--- a/dist/qt_themes/qdarkstyle/style.qss
+++ b/dist/qt_themes/qdarkstyle/style.qss
@@ -1293,15 +1293,24 @@ QPushButton#buttonRefreshDevices {
1293 1293
1294QSpinBox#spinboxLStickRange, 1294QSpinBox#spinboxLStickRange,
1295QSpinBox#spinboxRStickRange, 1295QSpinBox#spinboxRStickRange,
1296QSpinBox#vibrationSpin { 1296QSpinBox#vibrationSpinPlayer1,
1297QSpinBox#vibrationSpinPlayer2,
1298QSpinBox#vibrationSpinPlayer3,
1299QSpinBox#vibrationSpinPlayer4,
1300QSpinBox#vibrationSpinPlayer5,
1301QSpinBox#vibrationSpinPlayer6,
1302QSpinBox#vibrationSpinPlayer7,
1303QSpinBox#vibrationSpinPlayer8 {
1297 min-width: 68px; 1304 min-width: 68px;
1298} 1305}
1299 1306
1307QDialog#ConfigureVibration QGroupBox::indicator,
1300QGroupBox#motionGroup::indicator, 1308QGroupBox#motionGroup::indicator,
1301QGroupBox#vibrationGroup::indicator { 1309QGroupBox#vibrationGroup::indicator {
1302 margin-left: 0px; 1310 margin-left: 0px;
1303} 1311}
1304 1312
1313QDialog#ConfigureVibration QGroupBox::title,
1305QGroupBox#motionGroup::title, 1314QGroupBox#motionGroup::title,
1306QGroupBox#vibrationGroup::title { 1315QGroupBox#vibrationGroup::title {
1307 spacing: 2px; 1316 spacing: 2px;
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
index ad032a966..70e540b06 100644
--- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
+++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss
@@ -2200,21 +2200,31 @@ QPushButton#buttonRefreshDevices {
2200 2200
2201QSpinBox#spinboxLStickRange, 2201QSpinBox#spinboxLStickRange,
2202QSpinBox#spinboxRStickRange, 2202QSpinBox#spinboxRStickRange,
2203QSpinBox#vibrationSpin { 2203QSpinBox#vibrationSpinPlayer1,
2204QSpinBox#vibrationSpinPlayer2,
2205QSpinBox#vibrationSpinPlayer3,
2206QSpinBox#vibrationSpinPlayer4,
2207QSpinBox#vibrationSpinPlayer5,
2208QSpinBox#vibrationSpinPlayer6,
2209QSpinBox#vibrationSpinPlayer7,
2210QSpinBox#vibrationSpinPlayer8 {
2204 min-width: 68px; 2211 min-width: 68px;
2205} 2212}
2206 2213
2214QDialog#ConfigureVibration QGroupBox::indicator,
2207QGroupBox#motionGroup::indicator, 2215QGroupBox#motionGroup::indicator,
2208QGroupBox#vibrationGroup::indicator { 2216QGroupBox#vibrationGroup::indicator {
2209 margin-left: 0px; 2217 margin-left: 0px;
2210} 2218}
2211 2219
2220QDialog#ConfigureVibration QGroupBox,
2212QWidget#bottomPerGameInput QGroupBox#motionGroup, 2221QWidget#bottomPerGameInput QGroupBox#motionGroup,
2213QWidget#bottomPerGameInput QGroupBox#vibrationGroup, 2222QWidget#bottomPerGameInput QGroupBox#vibrationGroup,
2214QWidget#bottomPerGameInput QGroupBox#inputConfigGroup { 2223QWidget#bottomPerGameInput QGroupBox#inputConfigGroup {
2215 padding: 0px; 2224 padding: 0px;
2216} 2225}
2217 2226
2227QDialog#ConfigureVibration QGroupBox::title,
2218QGroupBox#motionGroup::title, 2228QGroupBox#motionGroup::title,
2219QGroupBox#vibrationGroup::title { 2229QGroupBox#vibrationGroup::title {
2220 spacing: 2px; 2230 spacing: 2px;
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index ba20d3f59..dc9954377 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -680,11 +680,19 @@ bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index,
680 return false; 680 return false;
681 } 681 }
682 682
683 const auto& player = Settings::values.players.GetValue()[npad_index];
684
685 if (!player.vibration_enabled) {
686 return false;
687 }
688
683 using namespace Settings::NativeButton; 689 using namespace Settings::NativeButton;
684 const auto& button_state = buttons[npad_index]; 690 const auto& button_state = buttons[npad_index];
685 691
686 return button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( 692 return button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay(
687 vibration_value.amp_low, vibration_value.freq_low, vibration_value.amp_high, 693 std::min(vibration_value.amp_low * player.vibration_strength / 100.0f, 1.0f),
694 vibration_value.freq_low,
695 std::min(vibration_value.amp_high * player.vibration_strength / 100.0f, 1.0f),
688 vibration_value.freq_high); 696 vibration_value.freq_high);
689} 697}
690 698
@@ -728,7 +736,8 @@ void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibrat
728 } 736 }
729 737
730 // Filter out non-zero vibrations that are within 0.015625 absolute amplitude of each other. 738 // Filter out non-zero vibrations that are within 0.015625 absolute amplitude of each other.
731 if ((vibration_values[i].amp_low != 0.0f || vibration_values[i].amp_high != 0.0f) && 739 if (!Settings::values.enable_accurate_vibrations.GetValue() &&
740 (vibration_values[i].amp_low != 0.0f || vibration_values[i].amp_high != 0.0f) &&
732 (latest_vibration_values[npad_index][device_index].amp_low != 0.0f || 741 (latest_vibration_values[npad_index][device_index].amp_low != 0.0f ||
733 latest_vibration_values[npad_index][device_index].amp_high != 0.0f) && 742 latest_vibration_values[npad_index][device_index].amp_high != 0.0f) &&
734 (abs(vibration_values[i].amp_low - 743 (abs(vibration_values[i].amp_low -
diff --git a/src/core/settings.h b/src/core/settings.h
index edd2a00ca..476c3fdf3 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -170,6 +170,7 @@ struct Values {
170 Setting<bool> use_docked_mode; 170 Setting<bool> use_docked_mode;
171 171
172 Setting<bool> vibration_enabled; 172 Setting<bool> vibration_enabled;
173 Setting<bool> enable_accurate_vibrations;
173 174
174 Setting<bool> motion_enabled; 175 Setting<bool> motion_enabled;
175 std::string motion_device; 176 std::string motion_device;
diff --git a/src/input_common/settings.h b/src/input_common/settings.h
index f52d28540..2763ed991 100644
--- a/src/input_common/settings.h
+++ b/src/input_common/settings.h
@@ -332,6 +332,9 @@ struct PlayerInput {
332 AnalogsRaw analogs; 332 AnalogsRaw analogs;
333 MotionRaw motions; 333 MotionRaw motions;
334 334
335 bool vibration_enabled;
336 int vibration_strength;
337
335 u32 body_color_left; 338 u32 body_color_left;
336 u32 body_color_right; 339 u32 body_color_right;
337 u32 button_color_left; 340 u32 button_color_left;
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 22fe0a2a6..bf1fae9fa 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -105,6 +105,9 @@ add_executable(yuzu
105 configuration/configure_ui.cpp 105 configuration/configure_ui.cpp
106 configuration/configure_ui.h 106 configuration/configure_ui.h
107 configuration/configure_ui.ui 107 configuration/configure_ui.ui
108 configuration/configure_vibration.cpp
109 configuration/configure_vibration.h
110 configuration/configure_vibration.ui
108 configuration/configure_web.cpp 111 configuration/configure_web.cpp
109 configuration/configure_web.h 112 configuration/configure_web.h
110 configuration/configure_web.ui 113 configuration/configure_web.ui
diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp
index 0fc713a6e..c5e671309 100644
--- a/src/yuzu/applets/controller.cpp
+++ b/src/yuzu/applets/controller.cpp
@@ -14,6 +14,7 @@
14#include "ui_controller.h" 14#include "ui_controller.h"
15#include "yuzu/applets/controller.h" 15#include "yuzu/applets/controller.h"
16#include "yuzu/configuration/configure_input_dialog.h" 16#include "yuzu/configuration/configure_input_dialog.h"
17#include "yuzu/configuration/configure_vibration.h"
17#include "yuzu/main.h" 18#include "yuzu/main.h"
18 19
19namespace { 20namespace {
@@ -223,6 +224,9 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
223 } 224 }
224 } 225 }
225 226
227 connect(ui->vibrationButton, &QPushButton::clicked, this,
228 &QtControllerSelectorDialog::CallConfigureVibrationDialog);
229
226 connect(ui->inputConfigButton, &QPushButton::clicked, this, 230 connect(ui->inputConfigButton, &QPushButton::clicked, this,
227 &QtControllerSelectorDialog::CallConfigureInputDialog); 231 &QtControllerSelectorDialog::CallConfigureInputDialog);
228 232
@@ -285,6 +289,18 @@ void QtControllerSelectorDialog::LoadConfiguration() {
285 ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue()); 289 ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
286} 290}
287 291
292void QtControllerSelectorDialog::CallConfigureVibrationDialog() {
293 ConfigureVibration dialog(this);
294
295 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
296 Qt::WindowSystemMenuHint);
297 dialog.setWindowModality(Qt::WindowModal);
298
299 if (dialog.exec() == QDialog::Accepted) {
300 dialog.ApplyConfiguration();
301 }
302}
303
288void QtControllerSelectorDialog::CallConfigureInputDialog() { 304void QtControllerSelectorDialog::CallConfigureInputDialog() {
289 const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; 305 const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
290 306
diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h
index 8fefecf05..a2ce03c8f 100644
--- a/src/yuzu/applets/controller.h
+++ b/src/yuzu/applets/controller.h
@@ -42,6 +42,9 @@ private:
42 // Loads the current input configuration into the frontend applet. 42 // Loads the current input configuration into the frontend applet.
43 void LoadConfiguration(); 43 void LoadConfiguration();
44 44
45 // Initializes the "Configure Vibration" Dialog.
46 void CallConfigureVibrationDialog();
47
45 // Initializes the "Configure Input" Dialog. 48 // Initializes the "Configure Input" Dialog.
46 void CallConfigureInputDialog(); 49 void CallConfigureInputDialog();
47 50
diff --git a/src/yuzu/applets/controller.ui b/src/yuzu/applets/controller.ui
index cc27b8ef4..8e571ba8f 100644
--- a/src/yuzu/applets/controller.ui
+++ b/src/yuzu/applets/controller.ui
@@ -2329,11 +2329,11 @@
2329 <number>3</number> 2329 <number>3</number>
2330 </property> 2330 </property>
2331 <item> 2331 <item>
2332 <widget class="QSpinBox" name="vibrationSpin"> 2332 <widget class="QPushButton" name="vibrationButton">
2333 <property name="minimumSize"> 2333 <property name="minimumSize">
2334 <size> 2334 <size>
2335 <width>68</width> 2335 <width>68</width>
2336 <height>21</height> 2336 <height>0</height>
2337 </size> 2337 </size>
2338 </property> 2338 </property>
2339 <property name="maximumSize"> 2339 <property name="maximumSize">
@@ -2342,17 +2342,11 @@
2342 <height>16777215</height> 2342 <height>16777215</height>
2343 </size> 2343 </size>
2344 </property> 2344 </property>
2345 <property name="suffix"> 2345 <property name="styleSheet">
2346 <string>%</string> 2346 <string notr="true">min-width: 68px;</string>
2347 </property>
2348 <property name="minimum">
2349 <number>1</number>
2350 </property>
2351 <property name="maximum">
2352 <number>100</number>
2353 </property> 2347 </property>
2354 <property name="value"> 2348 <property name="text">
2355 <number>100</number> 2349 <string>Configure</string>
2356 </property> 2350 </property>
2357 </widget> 2351 </widget>
2358 </item> 2352 </item>
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 296c58f58..7f66f29aa 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -300,6 +300,14 @@ void Config::ReadPlayerValue(std::size_t player_index) {
300 static_cast<u8>(Settings::ControllerType::ProController)) 300 static_cast<u8>(Settings::ControllerType::ProController))
301 .toUInt()); 301 .toUInt());
302 302
303 player.vibration_enabled =
304 qt_config->value(QStringLiteral("%1vibration_enabled").arg(player_prefix), true)
305 .toBool();
306
307 player.vibration_strength =
308 qt_config->value(QStringLiteral("%1vibration_strength").arg(player_prefix), 100)
309 .toInt();
310
303 player.body_color_left = qt_config 311 player.body_color_left = qt_config
304 ->value(QStringLiteral("%1body_color_left").arg(player_prefix), 312 ->value(QStringLiteral("%1body_color_left").arg(player_prefix),
305 Settings::JOYCON_BODY_NEON_BLUE) 313 Settings::JOYCON_BODY_NEON_BLUE)
@@ -493,6 +501,8 @@ void Config::ReadControlValues() {
493 ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), false); 501 ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), false);
494 ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"), 502 ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"),
495 true); 503 true);
504 ReadSettingGlobal(Settings::values.enable_accurate_vibrations,
505 QStringLiteral("enable_accurate_vibrations"), false);
496 ReadSettingGlobal(Settings::values.motion_enabled, QStringLiteral("motion_enabled"), true); 506 ReadSettingGlobal(Settings::values.motion_enabled, QStringLiteral("motion_enabled"), true);
497 507
498 qt_config->endGroup(); 508 qt_config->endGroup();
@@ -983,6 +993,10 @@ void Config::SavePlayerValue(std::size_t player_index) {
983 993
984 if (!player_prefix.isEmpty()) { 994 if (!player_prefix.isEmpty()) {
985 WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, false); 995 WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, false);
996 WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix),
997 player.vibration_enabled, true);
998 WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix),
999 player.vibration_strength, 100);
986 WriteSetting(QStringLiteral("%1body_color_left").arg(player_prefix), player.body_color_left, 1000 WriteSetting(QStringLiteral("%1body_color_left").arg(player_prefix), player.body_color_left,
987 Settings::JOYCON_BODY_NEON_BLUE); 1001 Settings::JOYCON_BODY_NEON_BLUE);
988 WriteSetting(QStringLiteral("%1body_color_right").arg(player_prefix), 1002 WriteSetting(QStringLiteral("%1body_color_right").arg(player_prefix),
@@ -1150,6 +1164,8 @@ void Config::SaveControlValues() {
1150 WriteSettingGlobal(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); 1164 WriteSettingGlobal(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
1151 WriteSettingGlobal(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, 1165 WriteSettingGlobal(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled,
1152 true); 1166 true);
1167 WriteSettingGlobal(QStringLiteral("enable_accurate_vibrations"),
1168 Settings::values.enable_accurate_vibrations, false);
1153 WriteSettingGlobal(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true); 1169 WriteSettingGlobal(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true);
1154 WriteSetting(QStringLiteral("motion_device"), 1170 WriteSetting(QStringLiteral("motion_device"),
1155 QString::fromStdString(Settings::values.motion_device), 1171 QString::fromStdString(Settings::values.motion_device),
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 9a4de4c5d..600cc03ae 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -23,6 +23,7 @@
23#include "yuzu/configuration/configure_motion_touch.h" 23#include "yuzu/configuration/configure_motion_touch.h"
24#include "yuzu/configuration/configure_mouse_advanced.h" 24#include "yuzu/configuration/configure_mouse_advanced.h"
25#include "yuzu/configuration/configure_touchscreen_advanced.h" 25#include "yuzu/configuration/configure_touchscreen_advanced.h"
26#include "yuzu/configuration/configure_vibration.h"
26#include "yuzu/configuration/input_profiles.h" 27#include "yuzu/configuration/input_profiles.h"
27 28
28namespace { 29namespace {
@@ -156,6 +157,9 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
156 CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); 157 CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem);
157 }); 158 });
158 159
160 connect(ui->vibrationButton, &QPushButton::clicked,
161 [this] { CallConfigureDialog<ConfigureVibration>(*this); });
162
159 connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] { 163 connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] {
160 CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); 164 CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem);
161 }); 165 });
diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui
index cbd67d4c7..2707025e7 100644
--- a/src/yuzu/configuration/configure_input.ui
+++ b/src/yuzu/configuration/configure_input.ui
@@ -6,7 +6,7 @@
6 <rect> 6 <rect>
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>700</width> 9 <width>680</width>
10 <height>540</height> 10 <height>540</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
@@ -195,11 +195,11 @@
195 <number>3</number> 195 <number>3</number>
196 </property> 196 </property>
197 <item> 197 <item>
198 <widget class="QSpinBox" name="vibrationSpin"> 198 <widget class="QPushButton" name="vibrationButton">
199 <property name="minimumSize"> 199 <property name="minimumSize">
200 <size> 200 <size>
201 <width>68</width> 201 <width>68</width>
202 <height>21</height> 202 <height>0</height>
203 </size> 203 </size>
204 </property> 204 </property>
205 <property name="maximumSize"> 205 <property name="maximumSize">
@@ -208,17 +208,11 @@
208 <height>16777215</height> 208 <height>16777215</height>
209 </size> 209 </size>
210 </property> 210 </property>
211 <property name="suffix"> 211 <property name="styleSheet">
212 <string>%</string> 212 <string notr="true">min-width: 68px;</string>
213 </property>
214 <property name="minimum">
215 <number>1</number>
216 </property>
217 <property name="maximum">
218 <number>100</number>
219 </property> 213 </property>
220 <property name="value"> 214 <property name="text">
221 <number>100</number> 215 <string>Configure</string>
222 </property> 216 </property>
223 </widget> 217 </widget>
224 </item> 218 </item>
@@ -272,7 +266,7 @@
272 </widget> 266 </widget>
273 </item> 267 </item>
274 <item alignment="Qt::AlignVCenter"> 268 <item alignment="Qt::AlignVCenter">
275 <widget class="QWidget" name="widget" native="true"> 269 <widget class="QWidget" name="connectedControllers" native="true">
276 <layout class="QGridLayout" name="gridLayout_2"> 270 <layout class="QGridLayout" name="gridLayout_2">
277 <property name="leftMargin"> 271 <property name="leftMargin">
278 <number>5</number> 272 <number>5</number>
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp
new file mode 100644
index 000000000..1c68f28f3
--- /dev/null
+++ b/src/yuzu/configuration/configure_vibration.cpp
@@ -0,0 +1,66 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/settings.h"
6#include "ui_configure_vibration.h"
7#include "yuzu/configuration/configure_vibration.h"
8
9ConfigureVibration::ConfigureVibration(QWidget* parent)
10 : QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()) {
11 ui->setupUi(this);
12
13 vibration_groupboxes = {
14 ui->vibrationGroupPlayer1, ui->vibrationGroupPlayer2, ui->vibrationGroupPlayer3,
15 ui->vibrationGroupPlayer4, ui->vibrationGroupPlayer5, ui->vibrationGroupPlayer6,
16 ui->vibrationGroupPlayer7, ui->vibrationGroupPlayer8,
17 };
18
19 vibration_spinboxes = {
20 ui->vibrationSpinPlayer1, ui->vibrationSpinPlayer2, ui->vibrationSpinPlayer3,
21 ui->vibrationSpinPlayer4, ui->vibrationSpinPlayer5, ui->vibrationSpinPlayer6,
22 ui->vibrationSpinPlayer7, ui->vibrationSpinPlayer8,
23 };
24
25 const auto& players = Settings::values.players.GetValue();
26
27 for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
28 vibration_groupboxes[i]->setChecked(players[i].vibration_enabled);
29 vibration_spinboxes[i]->setValue(players[i].vibration_strength);
30 }
31
32 ui->checkBoxAccurateVibration->setChecked(
33 Settings::values.enable_accurate_vibrations.GetValue());
34
35 if (!Settings::IsConfiguringGlobal()) {
36 ui->checkBoxAccurateVibration->setDisabled(true);
37 }
38
39 RetranslateUI();
40}
41
42ConfigureVibration::~ConfigureVibration() = default;
43
44void ConfigureVibration::ApplyConfiguration() {
45 auto& players = Settings::values.players.GetValue();
46
47 for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
48 players[i].vibration_enabled = vibration_groupboxes[i]->isChecked();
49 players[i].vibration_strength = vibration_spinboxes[i]->value();
50 }
51
52 Settings::values.enable_accurate_vibrations.SetValue(
53 ui->checkBoxAccurateVibration->isChecked());
54}
55
56void ConfigureVibration::changeEvent(QEvent* event) {
57 if (event->type() == QEvent::LanguageChange) {
58 RetranslateUI();
59 }
60
61 QDialog::changeEvent(event);
62}
63
64void ConfigureVibration::RetranslateUI() {
65 ui->retranslateUi(this);
66}
diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h
new file mode 100644
index 000000000..37bbc2653
--- /dev/null
+++ b/src/yuzu/configuration/configure_vibration.h
@@ -0,0 +1,40 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <memory>
9#include <QDialog>
10
11class QGroupBox;
12class QSpinBox;
13
14namespace Ui {
15class ConfigureVibration;
16}
17
18class ConfigureVibration : public QDialog {
19 Q_OBJECT
20
21public:
22 explicit ConfigureVibration(QWidget* parent);
23 ~ConfigureVibration() override;
24
25 void ApplyConfiguration();
26
27private:
28 void changeEvent(QEvent* event) override;
29 void RetranslateUI();
30
31 std::unique_ptr<Ui::ConfigureVibration> ui;
32
33 static constexpr std::size_t NUM_PLAYERS = 8;
34
35 // Groupboxes encapsulating the vibration strength spinbox.
36 std::array<QGroupBox*, NUM_PLAYERS> vibration_groupboxes;
37
38 // Spinboxes representing the vibration strength percentage.
39 std::array<QSpinBox*, NUM_PLAYERS> vibration_spinboxes;
40};
diff --git a/src/yuzu/configuration/configure_vibration.ui b/src/yuzu/configuration/configure_vibration.ui
new file mode 100644
index 000000000..efdf317a9
--- /dev/null
+++ b/src/yuzu/configuration/configure_vibration.ui
@@ -0,0 +1,546 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>ConfigureVibration</class>
4 <widget class="QDialog" name="ConfigureVibration">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>364</width>
10 <height>242</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Configure Vibration</string>
15 </property>
16 <property name="styleSheet">
17 <string notr="true"/>
18 </property>
19 <layout class="QVBoxLayout">
20 <item>
21 <widget class="QGroupBox" name="vibrationStrengthGroup">
22 <property name="title">
23 <string>Vibration</string>
24 </property>
25 <layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,0">
26 <property name="leftMargin">
27 <number>9</number>
28 </property>
29 <property name="topMargin">
30 <number>9</number>
31 </property>
32 <property name="rightMargin">
33 <number>9</number>
34 </property>
35 <property name="bottomMargin">
36 <number>9</number>
37 </property>
38 <item>
39 <widget class="QWidget" name="player14Widget" native="true">
40 <layout class="QHBoxLayout" name="horizontalLayout_4">
41 <property name="leftMargin">
42 <number>0</number>
43 </property>
44 <property name="topMargin">
45 <number>0</number>
46 </property>
47 <property name="rightMargin">
48 <number>0</number>
49 </property>
50 <property name="bottomMargin">
51 <number>0</number>
52 </property>
53 <item>
54 <widget class="QGroupBox" name="vibrationGroupPlayer1">
55 <property name="title">
56 <string>Player 1</string>
57 </property>
58 <property name="checkable">
59 <bool>true</bool>
60 </property>
61 <layout class="QHBoxLayout" name="horizontalLayout_8">
62 <property name="leftMargin">
63 <number>3</number>
64 </property>
65 <property name="topMargin">
66 <number>3</number>
67 </property>
68 <property name="rightMargin">
69 <number>3</number>
70 </property>
71 <property name="bottomMargin">
72 <number>3</number>
73 </property>
74 <item>
75 <widget class="QSpinBox" name="vibrationSpinPlayer1">
76 <property name="minimumSize">
77 <size>
78 <width>68</width>
79 <height>21</height>
80 </size>
81 </property>
82 <property name="maximumSize">
83 <size>
84 <width>68</width>
85 <height>16777215</height>
86 </size>
87 </property>
88 <property name="suffix">
89 <string>%</string>
90 </property>
91 <property name="minimum">
92 <number>1</number>
93 </property>
94 <property name="maximum">
95 <number>150</number>
96 </property>
97 <property name="value">
98 <number>100</number>
99 </property>
100 </widget>
101 </item>
102 </layout>
103 </widget>
104 </item>
105 <item>
106 <widget class="QGroupBox" name="vibrationGroupPlayer2">
107 <property name="title">
108 <string>Player 2</string>
109 </property>
110 <property name="checkable">
111 <bool>true</bool>
112 </property>
113 <layout class="QHBoxLayout" name="horizontalLayout_9">
114 <property name="leftMargin">
115 <number>3</number>
116 </property>
117 <property name="topMargin">
118 <number>3</number>
119 </property>
120 <property name="rightMargin">
121 <number>3</number>
122 </property>
123 <property name="bottomMargin">
124 <number>3</number>
125 </property>
126 <item>
127 <widget class="QSpinBox" name="vibrationSpinPlayer2">
128 <property name="minimumSize">
129 <size>
130 <width>68</width>
131 <height>21</height>
132 </size>
133 </property>
134 <property name="maximumSize">
135 <size>
136 <width>68</width>
137 <height>16777215</height>
138 </size>
139 </property>
140 <property name="suffix">
141 <string>%</string>
142 </property>
143 <property name="minimum">
144 <number>1</number>
145 </property>
146 <property name="maximum">
147 <number>150</number>
148 </property>
149 <property name="value">
150 <number>100</number>
151 </property>
152 </widget>
153 </item>
154 </layout>
155 </widget>
156 </item>
157 <item>
158 <widget class="QGroupBox" name="vibrationGroupPlayer3">
159 <property name="title">
160 <string>Player 3</string>
161 </property>
162 <property name="checkable">
163 <bool>true</bool>
164 </property>
165 <layout class="QHBoxLayout" name="horizontalLayout_10">
166 <property name="leftMargin">
167 <number>3</number>
168 </property>
169 <property name="topMargin">
170 <number>3</number>
171 </property>
172 <property name="rightMargin">
173 <number>3</number>
174 </property>
175 <property name="bottomMargin">
176 <number>3</number>
177 </property>
178 <item>
179 <widget class="QSpinBox" name="vibrationSpinPlayer3">
180 <property name="minimumSize">
181 <size>
182 <width>68</width>
183 <height>21</height>
184 </size>
185 </property>
186 <property name="maximumSize">
187 <size>
188 <width>68</width>
189 <height>16777215</height>
190 </size>
191 </property>
192 <property name="suffix">
193 <string>%</string>
194 </property>
195 <property name="minimum">
196 <number>1</number>
197 </property>
198 <property name="maximum">
199 <number>150</number>
200 </property>
201 <property name="value">
202 <number>100</number>
203 </property>
204 </widget>
205 </item>
206 </layout>
207 </widget>
208 </item>
209 <item>
210 <widget class="QGroupBox" name="vibrationGroupPlayer4">
211 <property name="title">
212 <string>Player 4</string>
213 </property>
214 <property name="checkable">
215 <bool>true</bool>
216 </property>
217 <layout class="QHBoxLayout" name="horizontalLayout_11">
218 <property name="leftMargin">
219 <number>3</number>
220 </property>
221 <property name="topMargin">
222 <number>3</number>
223 </property>
224 <property name="rightMargin">
225 <number>3</number>
226 </property>
227 <property name="bottomMargin">
228 <number>3</number>
229 </property>
230 <item>
231 <widget class="QSpinBox" name="vibrationSpinPlayer4">
232 <property name="minimumSize">
233 <size>
234 <width>68</width>
235 <height>21</height>
236 </size>
237 </property>
238 <property name="maximumSize">
239 <size>
240 <width>68</width>
241 <height>16777215</height>
242 </size>
243 </property>
244 <property name="suffix">
245 <string>%</string>
246 </property>
247 <property name="minimum">
248 <number>1</number>
249 </property>
250 <property name="maximum">
251 <number>150</number>
252 </property>
253 <property name="value">
254 <number>100</number>
255 </property>
256 </widget>
257 </item>
258 </layout>
259 </widget>
260 </item>
261 </layout>
262 </widget>
263 </item>
264 <item>
265 <widget class="QWidget" name="player58Widget" native="true">
266 <layout class="QHBoxLayout" name="horizontalLayout_6">
267 <property name="leftMargin">
268 <number>0</number>
269 </property>
270 <property name="topMargin">
271 <number>0</number>
272 </property>
273 <property name="rightMargin">
274 <number>0</number>
275 </property>
276 <property name="bottomMargin">
277 <number>0</number>
278 </property>
279 <item>
280 <widget class="QGroupBox" name="vibrationGroupPlayer7">
281 <property name="title">
282 <string>Player 5</string>
283 </property>
284 <property name="checkable">
285 <bool>true</bool>
286 </property>
287 <layout class="QHBoxLayout" name="horizontalLayout_14">
288 <property name="leftMargin">
289 <number>3</number>
290 </property>
291 <property name="topMargin">
292 <number>3</number>
293 </property>
294 <property name="rightMargin">
295 <number>3</number>
296 </property>
297 <property name="bottomMargin">
298 <number>3</number>
299 </property>
300 <item>
301 <widget class="QSpinBox" name="vibrationSpinPlayer7">
302 <property name="minimumSize">
303 <size>
304 <width>68</width>
305 <height>21</height>
306 </size>
307 </property>
308 <property name="maximumSize">
309 <size>
310 <width>68</width>
311 <height>16777215</height>
312 </size>
313 </property>
314 <property name="suffix">
315 <string>%</string>
316 </property>
317 <property name="minimum">
318 <number>1</number>
319 </property>
320 <property name="maximum">
321 <number>150</number>
322 </property>
323 <property name="value">
324 <number>100</number>
325 </property>
326 </widget>
327 </item>
328 </layout>
329 </widget>
330 </item>
331 <item>
332 <widget class="QGroupBox" name="vibrationGroupPlayer8">
333 <property name="title">
334 <string>Player 6</string>
335 </property>
336 <property name="checkable">
337 <bool>true</bool>
338 </property>
339 <layout class="QHBoxLayout" name="horizontalLayout_15">
340 <property name="leftMargin">
341 <number>3</number>
342 </property>
343 <property name="topMargin">
344 <number>3</number>
345 </property>
346 <property name="rightMargin">
347 <number>3</number>
348 </property>
349 <property name="bottomMargin">
350 <number>3</number>
351 </property>
352 <item>
353 <widget class="QSpinBox" name="vibrationSpinPlayer8">
354 <property name="minimumSize">
355 <size>
356 <width>68</width>
357 <height>21</height>
358 </size>
359 </property>
360 <property name="maximumSize">
361 <size>
362 <width>68</width>
363 <height>16777215</height>
364 </size>
365 </property>
366 <property name="suffix">
367 <string>%</string>
368 </property>
369 <property name="minimum">
370 <number>1</number>
371 </property>
372 <property name="maximum">
373 <number>150</number>
374 </property>
375 <property name="value">
376 <number>100</number>
377 </property>
378 </widget>
379 </item>
380 </layout>
381 </widget>
382 </item>
383 <item>
384 <widget class="QGroupBox" name="vibrationGroupPlayer5">
385 <property name="title">
386 <string>Player 7</string>
387 </property>
388 <property name="checkable">
389 <bool>true</bool>
390 </property>
391 <layout class="QHBoxLayout" name="horizontalLayout_12">
392 <property name="leftMargin">
393 <number>3</number>
394 </property>
395 <property name="topMargin">
396 <number>3</number>
397 </property>
398 <property name="rightMargin">
399 <number>3</number>
400 </property>
401 <property name="bottomMargin">
402 <number>3</number>
403 </property>
404 <item>
405 <widget class="QSpinBox" name="vibrationSpinPlayer5">
406 <property name="minimumSize">
407 <size>
408 <width>68</width>
409 <height>21</height>
410 </size>
411 </property>
412 <property name="maximumSize">
413 <size>
414 <width>68</width>
415 <height>16777215</height>
416 </size>
417 </property>
418 <property name="suffix">
419 <string>%</string>
420 </property>
421 <property name="minimum">
422 <number>1</number>
423 </property>
424 <property name="maximum">
425 <number>150</number>
426 </property>
427 <property name="value">
428 <number>100</number>
429 </property>
430 </widget>
431 </item>
432 </layout>
433 </widget>
434 </item>
435 <item>
436 <widget class="QGroupBox" name="vibrationGroupPlayer6">
437 <property name="title">
438 <string>Player 8</string>
439 </property>
440 <property name="checkable">
441 <bool>true</bool>
442 </property>
443 <layout class="QHBoxLayout" name="horizontalLayout_13">
444 <property name="leftMargin">
445 <number>3</number>
446 </property>
447 <property name="topMargin">
448 <number>3</number>
449 </property>
450 <property name="rightMargin">
451 <number>3</number>
452 </property>
453 <property name="bottomMargin">
454 <number>3</number>
455 </property>
456 <item>
457 <widget class="QSpinBox" name="vibrationSpinPlayer6">
458 <property name="minimumSize">
459 <size>
460 <width>68</width>
461 <height>21</height>
462 </size>
463 </property>
464 <property name="maximumSize">
465 <size>
466 <width>68</width>
467 <height>16777215</height>
468 </size>
469 </property>
470 <property name="suffix">
471 <string>%</string>
472 </property>
473 <property name="minimum">
474 <number>1</number>
475 </property>
476 <property name="maximum">
477 <number>150</number>
478 </property>
479 <property name="value">
480 <number>100</number>
481 </property>
482 </widget>
483 </item>
484 </layout>
485 </widget>
486 </item>
487 </layout>
488 </widget>
489 </item>
490 </layout>
491 </widget>
492 </item>
493 <item>
494 <widget class="QGroupBox" name="vibrationSettingsGroup">
495 <property name="title">
496 <string>Settings</string>
497 </property>
498 <layout class="QVBoxLayout" name="verticalLayout">
499 <item>
500 <widget class="QCheckBox" name="checkBoxAccurateVibration">
501 <property name="text">
502 <string>Enable Accurate Vibration</string>
503 </property>
504 </widget>
505 </item>
506 </layout>
507 </widget>
508 </item>
509 <item>
510 <spacer name="spacerVibration">
511 <property name="orientation">
512 <enum>Qt::Vertical</enum>
513 </property>
514 <property name="sizeHint" stdset="0">
515 <size>
516 <width>167</width>
517 <height>55</height>
518 </size>
519 </property>
520 </spacer>
521 </item>
522 <item>
523 <widget class="QDialogButtonBox" name="buttonBoxVibration">
524 <property name="standardButtons">
525 <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
526 </property>
527 </widget>
528 </item>
529 </layout>
530 </widget>
531 <resources/>
532 <connections>
533 <connection>
534 <sender>buttonBoxVibration</sender>
535 <signal>accepted()</signal>
536 <receiver>ConfigureVibration</receiver>
537 <slot>accept()</slot>
538 </connection>
539 <connection>
540 <sender>buttonBoxVibration</sender>
541 <signal>rejected()</signal>
542 <receiver>ConfigureVibration</receiver>
543 <slot>reject()</slot>
544 </connection>
545 </connections>
546</ui>
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index feee02fcd..e1adbbf2b 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -290,6 +290,8 @@ void Config::ReadValues() {
290 290
291 Settings::values.vibration_enabled.SetValue( 291 Settings::values.vibration_enabled.SetValue(
292 sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true)); 292 sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true));
293 Settings::values.enable_accurate_vibrations.SetValue(
294 sdl2_config->GetBoolean("ControlsGeneral", "enable_accurate_vibrations", false));
293 Settings::values.motion_enabled.SetValue( 295 Settings::values.motion_enabled.SetValue(
294 sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true)); 296 sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true));
295 Settings::values.touchscreen.enabled = 297 Settings::values.touchscreen.enabled =
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index b6f6a3bb0..bcbbcd4ca 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -69,6 +69,10 @@ rstick=
69# 0: Disabled, 1 (default): Enabled 69# 0: Disabled, 1 (default): Enabled
70vibration_enabled= 70vibration_enabled=
71 71
72# Whether to enable or disable accurate vibrations
73# 0 (default): Disabled, 1: Enabled
74enable_accurate_vibrations=
75
72# for motion input, the following devices are available: 76# for motion input, the following devices are available:
73# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: 77# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters:
74# - "update_period": update period in milliseconds (default to 100) 78# - "update_period": update period in milliseconds (default to 100)
diff --git a/src/yuzu_tester/config.cpp b/src/yuzu_tester/config.cpp
index 3a8a333f0..b6cdc7c1c 100644
--- a/src/yuzu_tester/config.cpp
+++ b/src/yuzu_tester/config.cpp
@@ -76,6 +76,7 @@ void Config::ReadValues() {
76 } 76 }
77 77
78 Settings::values.vibration_enabled.SetValue(true); 78 Settings::values.vibration_enabled.SetValue(true);
79 Settings::values.enable_accurate_vibrations.SetValue(false);
79 Settings::values.motion_enabled.SetValue(true); 80 Settings::values.motion_enabled.SetValue(true);
80 Settings::values.touchscreen.enabled = ""; 81 Settings::values.touchscreen.enabled = "";
81 Settings::values.touchscreen.device = ""; 82 Settings::values.touchscreen.device = "";