summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hid/input_converter.cpp2
-rw-r--r--src/input_common/drivers/sdl_driver.cpp5
-rw-r--r--src/input_common/helpers/touch_from_buttons.cpp1
-rw-r--r--src/yuzu/applets/qt_controller.cpp2
-rw-r--r--src/yuzu/configuration/configure_input.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp89
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.h2
-rw-r--r--src/yuzu/configuration/configure_vibration.cpp74
-rw-r--r--src/yuzu/configuration/configure_vibration.h18
-rw-r--r--src/yuzu/configuration/configure_vibration.ui7
-rw-r--r--src/yuzu/main.cpp2
-rw-r--r--src/yuzu_cmd/config.cpp36
12 files changed, 184 insertions, 56 deletions
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index 860aab400..cd41607a7 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -28,7 +28,7 @@ Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackSta
28 if (value > 0.8f) { 28 if (value > 0.8f) {
29 battery = Common::Input::BatteryLevel::Full; 29 battery = Common::Input::BatteryLevel::Full;
30 } 30 }
31 if (value >= 1.0f) { 31 if (value >= 0.95f) {
32 battery = Common::Input::BatteryLevel::Charging; 32 battery = Common::Input::BatteryLevel::Charging;
33 } 33 }
34 break; 34 break;
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 577bf5c31..b031a8523 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -181,11 +181,10 @@ public:
181 case SDL_JOYSTICK_POWER_EMPTY: 181 case SDL_JOYSTICK_POWER_EMPTY:
182 return BatteryLevel::Empty; 182 return BatteryLevel::Empty;
183 case SDL_JOYSTICK_POWER_LOW: 183 case SDL_JOYSTICK_POWER_LOW:
184 return BatteryLevel::Critical;
185 case SDL_JOYSTICK_POWER_MEDIUM:
186 return BatteryLevel::Low; 184 return BatteryLevel::Low;
187 case SDL_JOYSTICK_POWER_FULL: 185 case SDL_JOYSTICK_POWER_MEDIUM:
188 return BatteryLevel::Medium; 186 return BatteryLevel::Medium;
187 case SDL_JOYSTICK_POWER_FULL:
189 case SDL_JOYSTICK_POWER_MAX: 188 case SDL_JOYSTICK_POWER_MAX:
190 return BatteryLevel::Full; 189 return BatteryLevel::Full;
191 case SDL_JOYSTICK_POWER_UNKNOWN: 190 case SDL_JOYSTICK_POWER_UNKNOWN:
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp
index ece1e3b32..f1b57d03a 100644
--- a/src/input_common/helpers/touch_from_buttons.cpp
+++ b/src/input_common/helpers/touch_from_buttons.cpp
@@ -4,7 +4,6 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include "common/settings.h" 6#include "common/settings.h"
7#include "core/frontend/framebuffer_layout.h"
8#include "input_common/helpers/touch_from_buttons.h" 7#include "input_common/helpers/touch_from_buttons.h"
9 8
10namespace InputCommon { 9namespace InputCommon {
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 4239c17f5..4104928d1 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -257,7 +257,7 @@ void QtControllerSelectorDialog::LoadConfiguration() {
257} 257}
258 258
259void QtControllerSelectorDialog::CallConfigureVibrationDialog() { 259void QtControllerSelectorDialog::CallConfigureVibrationDialog() {
260 ConfigureVibration dialog(this); 260 ConfigureVibration dialog(this, system.HIDCore());
261 261
262 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | 262 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
263 Qt::WindowSystemMenuHint); 263 Qt::WindowSystemMenuHint);
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index d53179dbb..7c5776189 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,
164 }); 164 });
165 165
166 connect(ui->vibrationButton, &QPushButton::clicked, 166 connect(ui->vibrationButton, &QPushButton::clicked,
167 [this] { CallConfigureDialog<ConfigureVibration>(*this); }); 167 [this, &hid_core] { CallConfigureDialog<ConfigureVibration>(*this, hid_core); });
168 168
169 connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] { 169 connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] {
170 CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); 170 CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem);
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 6630321cb..fb168b2ca 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -70,7 +70,6 @@ void PlayerControlPreview::UpdateColors() {
70 colors.slider_arrow = QColor(14, 15, 18); 70 colors.slider_arrow = QColor(14, 15, 18);
71 colors.font2 = QColor(255, 255, 255); 71 colors.font2 = QColor(255, 255, 255);
72 colors.indicator = QColor(170, 238, 255); 72 colors.indicator = QColor(170, 238, 255);
73 colors.indicator2 = QColor(100, 255, 100);
74 colors.deadzone = QColor(204, 136, 136); 73 colors.deadzone = QColor(204, 136, 136);
75 colors.slider_button = colors.button; 74 colors.slider_button = colors.button;
76 } 75 }
@@ -88,7 +87,6 @@ void PlayerControlPreview::UpdateColors() {
88 colors.slider_arrow = QColor(65, 68, 73); 87 colors.slider_arrow = QColor(65, 68, 73);
89 colors.font2 = QColor(0, 0, 0); 88 colors.font2 = QColor(0, 0, 0);
90 colors.indicator = QColor(0, 0, 200); 89 colors.indicator = QColor(0, 0, 200);
91 colors.indicator2 = QColor(0, 150, 0);
92 colors.deadzone = QColor(170, 0, 0); 90 colors.deadzone = QColor(170, 0, 0);
93 colors.slider_button = QColor(153, 149, 149); 91 colors.slider_button = QColor(153, 149, 149);
94 } 92 }
@@ -101,6 +99,8 @@ void PlayerControlPreview::UpdateColors() {
101 colors.font = QColor(255, 255, 255); 99 colors.font = QColor(255, 255, 255);
102 colors.led_on = QColor(255, 255, 0); 100 colors.led_on = QColor(255, 255, 0);
103 colors.led_off = QColor(170, 238, 255); 101 colors.led_off = QColor(170, 238, 255);
102 colors.indicator2 = QColor(59, 165, 93);
103 colors.charging = QColor(250, 168, 26);
104 104
105 colors.left = colors.primary; 105 colors.left = colors.primary;
106 colors.right = colors.primary; 106 colors.right = colors.primary;
@@ -357,7 +357,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
357 DrawCircle(p, center + QPoint(26, 71), 5); 357 DrawCircle(p, center + QPoint(26, 71), 5);
358 358
359 // Draw battery 359 // Draw battery
360 DrawBattery(p, center + QPoint(-170, -140), 360 DrawBattery(p, center + QPoint(-160, -140),
361 battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); 361 battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
362} 362}
363 363
@@ -484,7 +484,7 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
484 DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5); 484 DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5);
485 485
486 // Draw battery 486 // Draw battery
487 DrawBattery(p, center + QPoint(110, -140), 487 DrawBattery(p, center + QPoint(120, -140),
488 battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]); 488 battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
489} 489}
490 490
@@ -621,9 +621,9 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
621 DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f); 621 DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f);
622 622
623 // Draw battery 623 // Draw battery
624 DrawBattery(p, center + QPoint(-100, -160), 624 DrawBattery(p, center + QPoint(-200, -10),
625 battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); 625 battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
626 DrawBattery(p, center + QPoint(40, -160), 626 DrawBattery(p, center + QPoint(160, -10),
627 battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]); 627 battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
628} 628}
629 629
@@ -694,12 +694,12 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
694 694
695 // ZL and ZR buttons 695 // ZL and ZR buttons
696 p.setPen(colors.outline); 696 p.setPen(colors.outline);
697 DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]); 697 DrawTriggerButton(p, center + QPoint(-210, -120), Direction::Left, button_values[ZL]);
698 DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]); 698 DrawTriggerButton(p, center + QPoint(210, -120), Direction::Right, button_values[ZR]);
699 p.setPen(colors.transparent); 699 p.setPen(colors.transparent);
700 p.setBrush(colors.font); 700 p.setBrush(colors.font);
701 DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f); 701 DrawSymbol(p, center + QPoint(-210, -120), Symbol::ZL, 1.5f);
702 DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f); 702 DrawSymbol(p, center + QPoint(210, -120), Symbol::ZR, 1.5f);
703 703
704 // Minus and Plus button 704 // Minus and Plus button
705 p.setPen(colors.outline); 705 p.setPen(colors.outline);
@@ -725,9 +725,9 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
725 DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f); 725 DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f);
726 726
727 // Draw battery 727 // Draw battery
728 DrawBattery(p, center + QPoint(-200, 110), 728 DrawBattery(p, center + QPoint(-188, 95),
729 battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); 729 battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
730 DrawBattery(p, center + QPoint(130, 110), 730 DrawBattery(p, center + QPoint(150, 95),
731 battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]); 731 battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
732} 732}
733 733
@@ -781,12 +781,12 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
781 781
782 // ZL and ZR buttons 782 // ZL and ZR buttons
783 p.setPen(colors.outline); 783 p.setPen(colors.outline);
784 DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]); 784 DrawTriggerButton(p, center + QPoint(-210, -120), Direction::Left, button_values[ZL]);
785 DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]); 785 DrawTriggerButton(p, center + QPoint(210, -120), Direction::Right, button_values[ZR]);
786 p.setPen(colors.transparent); 786 p.setPen(colors.transparent);
787 p.setBrush(colors.font); 787 p.setBrush(colors.font);
788 DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f); 788 DrawSymbol(p, center + QPoint(-210, -120), Symbol::ZL, 1.5f);
789 DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f); 789 DrawSymbol(p, center + QPoint(210, -120), Symbol::ZR, 1.5f);
790 790
791 // Minus and Plus buttons 791 // Minus and Plus buttons
792 p.setPen(colors.outline); 792 p.setPen(colors.outline);
@@ -818,7 +818,7 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
818 DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f); 818 DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);
819 819
820 // Draw battery 820 // Draw battery
821 DrawBattery(p, center + QPoint(-30, -160), 821 DrawBattery(p, center + QPoint(-20, -160),
822 battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); 822 battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
823} 823}
824 824
@@ -875,7 +875,7 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
875 DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8); 875 DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8);
876 876
877 // Draw battery 877 // Draw battery
878 DrawBattery(p, center + QPoint(-30, -165), 878 DrawBattery(p, center + QPoint(-20, 110),
879 battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); 879 battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
880} 880}
881 881
@@ -1030,6 +1030,10 @@ constexpr std::array<float, 30 * 2> symbol_c = {
1030 -2.37f, 5.64f, -0.65f, 6.44f, 1.25f, 6.47f, 3.06f, 5.89f, 4.63f, 4.92f, 4.63f, 6.83f, 1030 -2.37f, 5.64f, -0.65f, 6.44f, 1.25f, 6.47f, 3.06f, 5.89f, 4.63f, 4.92f, 4.63f, 6.83f,
1031}; 1031};
1032 1032
1033constexpr std::array<float, 6 * 2> symbol_charging = {
1034 6.5f, -1.0f, 1.0f, -1.0f, 1.0f, -3.0f, -6.5f, 1.0f, -1.0f, 1.0f, -1.0f, 3.0f,
1035};
1036
1033constexpr std::array<float, 12 * 2> house = { 1037constexpr std::array<float, 12 * 2> house = {
1034 -1.3f, 0.0f, -0.93f, 0.0f, -0.93f, 1.15f, 0.93f, 1.15f, 0.93f, 0.0f, 1.3f, 0.0f, 1038 -1.3f, 0.0f, -0.93f, 0.0f, -0.93f, 1.15f, 0.93f, 1.15f, 0.93f, 0.0f, 1.3f, 0.0f,
1035 0.0f, -1.2f, -1.3f, 0.0f, -0.43f, 0.0f, -0.43f, .73f, 0.43f, .73f, 0.43f, 0.0f, 1039 0.0f, -1.2f, -1.3f, 0.0f, -0.43f, 0.0f, -0.43f, .73f, 0.43f, .73f, 0.43f, 0.0f,
@@ -2674,36 +2678,43 @@ void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center,
2674 if (battery == Common::Input::BatteryLevel::None) { 2678 if (battery == Common::Input::BatteryLevel::None) {
2675 return; 2679 return;
2676 } 2680 }
2677 p.setPen(colors.outline); 2681 // Draw outline
2682 p.setPen(QPen(colors.button, 5));
2683 p.setBrush(colors.transparent);
2684 p.drawRoundedRect(center.x(), center.y(), 34, 16, 2, 2);
2685
2686 p.setPen(QPen(colors.button, 3));
2687 p.drawRect(center.x() + 35, center.y() + 4.5f, 4, 7);
2688
2689 // Draw Battery shape
2690 p.setPen(QPen(colors.indicator2, 3));
2678 p.setBrush(colors.transparent); 2691 p.setBrush(colors.transparent);
2679 p.drawRect(center.x(), center.y(), 56, 20); 2692 p.drawRoundedRect(center.x(), center.y(), 34, 16, 2, 2);
2680 p.drawRect(center.x() + 56, center.y() + 6, 3, 8); 2693
2681 p.setBrush(colors.deadzone); 2694 p.setPen(QPen(colors.indicator2, 1));
2695 p.setBrush(colors.indicator2);
2696 p.drawRect(center.x() + 35, center.y() + 4.5f, 4, 7);
2682 switch (battery) { 2697 switch (battery) {
2683 case Common::Input::BatteryLevel::Charging: 2698 case Common::Input::BatteryLevel::Charging:
2684 p.setBrush(colors.indicator2); 2699 p.drawRect(center.x(), center.y(), 34, 16);
2685 p.drawText(center + QPoint(2, 14), tr("Charging")); 2700 p.setPen(colors.slider);
2701 p.setBrush(colors.charging);
2702 DrawSymbol(p, center + QPointF(17.0f, 8.0f), Symbol::Charging, 2.1f);
2686 break; 2703 break;
2687 case Common::Input::BatteryLevel::Full: 2704 case Common::Input::BatteryLevel::Full:
2688 p.drawRect(center.x() + 42, center.y(), 14, 20); 2705 p.drawRect(center.x(), center.y(), 34, 16);
2689 p.drawRect(center.x() + 28, center.y(), 14, 20);
2690 p.drawRect(center.x() + 14, center.y(), 14, 20);
2691 p.drawRect(center.x(), center.y(), 14, 20);
2692 break; 2706 break;
2693 case Common::Input::BatteryLevel::Medium: 2707 case Common::Input::BatteryLevel::Medium:
2694 p.drawRect(center.x() + 28, center.y(), 14, 20); 2708 p.drawRect(center.x(), center.y(), 25, 16);
2695 p.drawRect(center.x() + 14, center.y(), 14, 20);
2696 p.drawRect(center.x(), center.y(), 14, 20);
2697 break; 2709 break;
2698 case Common::Input::BatteryLevel::Low: 2710 case Common::Input::BatteryLevel::Low:
2699 p.drawRect(center.x() + 14, center.y(), 14, 20); 2711 p.drawRect(center.x(), center.y(), 17, 16);
2700 p.drawRect(center.x(), center.y(), 14, 20);
2701 break; 2712 break;
2702 case Common::Input::BatteryLevel::Critical: 2713 case Common::Input::BatteryLevel::Critical:
2703 p.drawRect(center.x(), center.y(), 14, 20); 2714 p.drawRect(center.x(), center.y(), 6, 16);
2704 break; 2715 break;
2705 case Common::Input::BatteryLevel::Empty: 2716 case Common::Input::BatteryLevel::Empty:
2706 p.drawRect(center.x(), center.y(), 5, 20); 2717 p.drawRect(center.x(), center.y(), 3, 16);
2707 break; 2718 break;
2708 default: 2719 default:
2709 break; 2720 break;
@@ -2724,6 +2735,7 @@ void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol
2724 std::array<QPointF, symbol_sl.size() / 2> sl_icon; 2735 std::array<QPointF, symbol_sl.size() / 2> sl_icon;
2725 std::array<QPointF, symbol_zr.size() / 2> zr_icon; 2736 std::array<QPointF, symbol_zr.size() / 2> zr_icon;
2726 std::array<QPointF, symbol_sr.size() / 2> sr_icon; 2737 std::array<QPointF, symbol_sr.size() / 2> sr_icon;
2738 std::array<QPointF, symbol_charging.size() / 2> charging_icon;
2727 switch (symbol) { 2739 switch (symbol) {
2728 case Symbol::House: 2740 case Symbol::House:
2729 for (std::size_t point = 0; point < house.size() / 2; ++point) { 2741 for (std::size_t point = 0; point < house.size() / 2; ++point) {
@@ -2809,6 +2821,13 @@ void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol
2809 } 2821 }
2810 p.drawPolygon(sr_icon.data(), static_cast<int>(sr_icon.size())); 2822 p.drawPolygon(sr_icon.data(), static_cast<int>(sr_icon.size()));
2811 break; 2823 break;
2824 case Symbol::Charging:
2825 for (std::size_t point = 0; point < symbol_charging.size() / 2; ++point) {
2826 charging_icon[point] = center + QPointF(symbol_charging[point * 2] * icon_size,
2827 symbol_charging[point * 2 + 1] * icon_size);
2828 }
2829 p.drawPolygon(charging_icon.data(), static_cast<int>(charging_icon.size()));
2830 break;
2812 } 2831 }
2813} 2832}
2814 2833
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index 4cd5c3be0..3582ef77a 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -72,6 +72,7 @@ private:
72 ZL, 72 ZL,
73 ZR, 73 ZR,
74 SR, 74 SR,
75 Charging,
75 }; 76 };
76 77
77 struct ColorMapping { 78 struct ColorMapping {
@@ -94,6 +95,7 @@ private:
94 QColor slider_button{}; 95 QColor slider_button{};
95 QColor slider_arrow{}; 96 QColor slider_arrow{};
96 QColor deadzone{}; 97 QColor deadzone{};
98 QColor charging{};
97 }; 99 };
98 100
99 void UpdateColors(); 101 void UpdateColors();
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp
index adce04b27..779b6401c 100644
--- a/src/yuzu/configuration/configure_vibration.cpp
+++ b/src/yuzu/configuration/configure_vibration.cpp
@@ -9,11 +9,14 @@
9 9
10#include "common/param_package.h" 10#include "common/param_package.h"
11#include "common/settings.h" 11#include "common/settings.h"
12#include "core/hid/emulated_controller.h"
13#include "core/hid/hid_core.h"
14#include "core/hid/hid_types.h"
12#include "ui_configure_vibration.h" 15#include "ui_configure_vibration.h"
13#include "yuzu/configuration/configure_vibration.h" 16#include "yuzu/configuration/configure_vibration.h"
14 17
15ConfigureVibration::ConfigureVibration(QWidget* parent) 18ConfigureVibration::ConfigureVibration(QWidget* parent, Core::HID::HIDCore& hid_core_)
16 : QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()) { 19 : QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()), hid_core{hid_core_} {
17 ui->setupUi(this); 20 ui->setupUi(this);
18 21
19 vibration_groupboxes = { 22 vibration_groupboxes = {
@@ -31,6 +34,13 @@ ConfigureVibration::ConfigureVibration(QWidget* parent)
31 const auto& players = Settings::values.players.GetValue(); 34 const auto& players = Settings::values.players.GetValue();
32 35
33 for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { 36 for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
37 auto controller = hid_core.GetEmulatedControllerByIndex(i);
38 Core::HID::ControllerUpdateCallback engine_callback{
39 .on_change = [this,
40 i](Core::HID::ControllerTriggerType type) { VibrateController(type, i); },
41 .is_npad_service = false,
42 };
43 controller_callback_key[i] = controller->SetCallback(engine_callback);
34 vibration_groupboxes[i]->setChecked(players[i].vibration_enabled); 44 vibration_groupboxes[i]->setChecked(players[i].vibration_enabled);
35 vibration_spinboxes[i]->setValue(players[i].vibration_strength); 45 vibration_spinboxes[i]->setValue(players[i].vibration_strength);
36 } 46 }
@@ -45,7 +55,14 @@ ConfigureVibration::ConfigureVibration(QWidget* parent)
45 RetranslateUI(); 55 RetranslateUI();
46} 56}
47 57
48ConfigureVibration::~ConfigureVibration() = default; 58ConfigureVibration::~ConfigureVibration() {
59 StopVibrations();
60
61 for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
62 auto controller = hid_core.GetEmulatedControllerByIndex(i);
63 controller->DeleteCallback(controller_callback_key[i]);
64 }
65};
49 66
50void ConfigureVibration::ApplyConfiguration() { 67void ConfigureVibration::ApplyConfiguration() {
51 auto& players = Settings::values.players.GetValue(); 68 auto& players = Settings::values.players.GetValue();
@@ -70,3 +87,54 @@ void ConfigureVibration::changeEvent(QEvent* event) {
70void ConfigureVibration::RetranslateUI() { 87void ConfigureVibration::RetranslateUI() {
71 ui->retranslateUi(this); 88 ui->retranslateUi(this);
72} 89}
90
91void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type,
92 std::size_t player_index) {
93 if (type != Core::HID::ControllerTriggerType::Button) {
94 return;
95 }
96
97 auto& player = Settings::values.players.GetValue()[player_index];
98 auto controller = hid_core.GetEmulatedControllerByIndex(player_index);
99 const int vibration_strenght = vibration_spinboxes[player_index]->value();
100 const auto& buttons = controller->GetButtonsValues();
101
102 bool button_is_pressed = false;
103 for (std::size_t i = 0; i < buttons.size(); ++i) {
104 if (buttons[i].value) {
105 button_is_pressed = true;
106 break;
107 }
108 }
109
110 if (!button_is_pressed) {
111 StopVibrations();
112 return;
113 }
114
115 const int old_vibration_enabled = player.vibration_enabled;
116 const bool old_vibration_strenght = player.vibration_strength;
117 player.vibration_enabled = true;
118 player.vibration_strength = vibration_strenght;
119
120 const Core::HID::VibrationValue vibration{
121 .low_amplitude = 1.0f,
122 .low_frequency = 160.0f,
123 .high_amplitude = 1.0f,
124 .high_frequency = 320.0f,
125 };
126 controller->SetVibration(0, vibration);
127 controller->SetVibration(1, vibration);
128
129 // Restore previous values
130 player.vibration_enabled = old_vibration_enabled;
131 player.vibration_strength = old_vibration_strenght;
132}
133
134void ConfigureVibration::StopVibrations() {
135 for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
136 auto controller = hid_core.GetEmulatedControllerByIndex(i);
137 controller->SetVibration(0, Core::HID::DEFAULT_VIBRATION_VALUE);
138 controller->SetVibration(1, Core::HID::DEFAULT_VIBRATION_VALUE);
139 }
140}
diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h
index 37bbc2653..50b8195fa 100644
--- a/src/yuzu/configuration/configure_vibration.h
+++ b/src/yuzu/configuration/configure_vibration.h
@@ -15,11 +15,16 @@ namespace Ui {
15class ConfigureVibration; 15class ConfigureVibration;
16} 16}
17 17
18namespace Core::HID {
19enum class ControllerTriggerType;
20class HIDCore;
21} // namespace Core::HID
22
18class ConfigureVibration : public QDialog { 23class ConfigureVibration : public QDialog {
19 Q_OBJECT 24 Q_OBJECT
20 25
21public: 26public:
22 explicit ConfigureVibration(QWidget* parent); 27 explicit ConfigureVibration(QWidget* parent, Core::HID::HIDCore& hid_core_);
23 ~ConfigureVibration() override; 28 ~ConfigureVibration() override;
24 29
25 void ApplyConfiguration(); 30 void ApplyConfiguration();
@@ -27,14 +32,21 @@ public:
27private: 32private:
28 void changeEvent(QEvent* event) override; 33 void changeEvent(QEvent* event) override;
29 void RetranslateUI(); 34 void RetranslateUI();
35 void VibrateController(Core::HID::ControllerTriggerType type, std::size_t player_index);
36 void StopVibrations();
30 37
31 std::unique_ptr<Ui::ConfigureVibration> ui; 38 std::unique_ptr<Ui::ConfigureVibration> ui;
32 39
33 static constexpr std::size_t NUM_PLAYERS = 8; 40 static constexpr std::size_t NUM_PLAYERS = 8;
34 41
35 // Groupboxes encapsulating the vibration strength spinbox. 42 /// Groupboxes encapsulating the vibration strength spinbox.
36 std::array<QGroupBox*, NUM_PLAYERS> vibration_groupboxes; 43 std::array<QGroupBox*, NUM_PLAYERS> vibration_groupboxes;
37 44
38 // Spinboxes representing the vibration strength percentage. 45 /// Spinboxes representing the vibration strength percentage.
39 std::array<QSpinBox*, NUM_PLAYERS> vibration_spinboxes; 46 std::array<QSpinBox*, NUM_PLAYERS> vibration_spinboxes;
47
48 /// Callback index to stop the controllers events
49 std::array<int, NUM_PLAYERS> controller_callback_key;
50
51 Core::HID::HIDCore& hid_core;
40}; 52};
diff --git a/src/yuzu/configuration/configure_vibration.ui b/src/yuzu/configuration/configure_vibration.ui
index efdf317a9..447a18eb1 100644
--- a/src/yuzu/configuration/configure_vibration.ui
+++ b/src/yuzu/configuration/configure_vibration.ui
@@ -17,6 +17,13 @@
17 <string notr="true"/> 17 <string notr="true"/>
18 </property> 18 </property>
19 <layout class="QVBoxLayout"> 19 <layout class="QVBoxLayout">
20 <item row="0" column="0" colspan="4">
21 <widget class="QLabel" name="label_1">
22 <property name="text">
23 <string>Press any controller button to vibrate the controller.</string>
24 </property>
25 </widget>
26 </item>
20 <item> 27 <item>
21 <widget class="QGroupBox" name="vibrationStrengthGroup"> 28 <widget class="QGroupBox" name="vibrationStrengthGroup">
22 <property name="title"> 29 <property name="title">
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 556d2cdb3..c788db12d 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1052,8 +1052,10 @@ void GMainWindow::SetDefaultUIGeometry() {
1052} 1052}
1053 1053
1054void GMainWindow::RestoreUIState() { 1054void GMainWindow::RestoreUIState() {
1055 setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint);
1055 restoreGeometry(UISettings::values.geometry); 1056 restoreGeometry(UISettings::values.geometry);
1056 restoreState(UISettings::values.state); 1057 restoreState(UISettings::values.state);
1058 render_window->setWindowFlags(render_window->windowFlags() & ~Qt::FramelessWindowHint);
1057 render_window->restoreGeometry(UISettings::values.renderwindow_geometry); 1059 render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
1058#if MICROPROFILE_ENABLED 1060#if MICROPROFILE_ENABLED
1059 microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); 1061 microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry);
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 8e9c7d211..ff616da70 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -66,6 +66,11 @@ static const std::array<int, Settings::NativeButton::NumButtons> default_buttons
66 SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B, 66 SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B,
67}; 67};
68 68
69static const std::array<int, Settings::NativeMotion::NumMotions> default_motions = {
70 SDL_SCANCODE_7,
71 SDL_SCANCODE_8,
72};
73
69static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs{{ 74static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs{{
70 { 75 {
71 SDL_SCANCODE_UP, 76 SDL_SCANCODE_UP,
@@ -102,27 +107,42 @@ void Config::ReadSetting(const std::string& group, Settings::BasicSetting<Type>&
102void Config::ReadValues() { 107void Config::ReadValues() {
103 // Controls 108 // Controls
104 for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { 109 for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
110 auto& player = Settings::values.players.GetValue()[p];
111
105 const auto group = fmt::format("ControlsP{}", p); 112 const auto group = fmt::format("ControlsP{}", p);
106 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { 113 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
107 std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); 114 std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
108 Settings::values.players.GetValue()[p].buttons[i] = 115 player.buttons[i] =
109 sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param); 116 sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param);
110 if (Settings::values.players.GetValue()[p].buttons[i].empty()) 117 if (player.buttons[i].empty()) {
111 Settings::values.players.GetValue()[p].buttons[i] = default_param; 118 player.buttons[i] = default_param;
119 }
112 } 120 }
113 121
114 for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { 122 for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
115 std::string default_param = InputCommon::GenerateAnalogParamFromKeys( 123 std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
116 default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], 124 default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
117 default_analogs[i][3], default_analogs[i][4], 0.5f); 125 default_analogs[i][3], default_analogs[i][4], 0.5f);
118 Settings::values.players.GetValue()[p].analogs[i] = 126 player.analogs[i] =
119 sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param); 127 sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param);
120 if (Settings::values.players.GetValue()[p].analogs[i].empty()) 128 if (player.analogs[i].empty()) {
121 Settings::values.players.GetValue()[p].analogs[i] = default_param; 129 player.analogs[i] = default_param;
130 }
131 }
132
133 for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
134 const std::string default_param =
135 InputCommon::GenerateKeyboardParam(default_motions[i]);
136 auto& player_motions = player.motions[i];
137
138 player_motions =
139 sdl2_config->Get(group, Settings::NativeMotion::mapping[i], default_param);
140 if (player_motions.empty()) {
141 player_motions = default_param;
142 }
122 } 143 }
123 144
124 Settings::values.players.GetValue()[p].connected = 145 player.connected = sdl2_config->GetBoolean(group, "connected", false);
125 sdl2_config->GetBoolean(group, "connected", false);
126 } 146 }
127 147
128 ReadSetting("ControlsGeneral", Settings::values.mouse_enabled); 148 ReadSetting("ControlsGeneral", Settings::values.mouse_enabled);