summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/yuzu/configuration/config.cpp1
-rw-r--r--src/yuzu/configuration/configure_input.cpp16
-rw-r--r--src/yuzu/configuration/configure_input.h3
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp922
-rw-r--r--src/yuzu/configuration/configure_input_player.h49
-rw-r--r--src/yuzu/configuration/configure_input_player.ui10
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp597
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.h133
-rw-r--r--src/yuzu/configuration/configure_motion_touch.cpp4
-rw-r--r--src/yuzu/configuration/configure_mouse_advanced.cpp57
-rw-r--r--src/yuzu/configuration/configure_mouse_advanced.h8
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.cpp27
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.h5
13 files changed, 822 insertions, 1010 deletions
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 2b670ddfd..56af07507 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -11,7 +11,6 @@
11#include "core/hle/service/acc/profile_manager.h" 11#include "core/hle/service/acc/profile_manager.h"
12#include "core/hle/service/hid/controllers/npad.h" 12#include "core/hle/service/hid/controllers/npad.h"
13#include "input_common/main.h" 13#include "input_common/main.h"
14#include "input_common/udp/client.h"
15#include "yuzu/configuration/config.h" 14#include "yuzu/configuration/config.h"
16 15
17namespace FS = Common::FS; 16namespace FS = Common::FS;
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 1599299db..61513865f 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -73,7 +73,7 @@ ConfigureInput::ConfigureInput(Core::System& system_, QWidget* parent)
73 73
74ConfigureInput::~ConfigureInput() = default; 74ConfigureInput::~ConfigureInput() = default;
75 75
76void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, 76void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, Core::System& system,
77 std::size_t max_players) { 77 std::size_t max_players) {
78 player_controllers = { 78 player_controllers = {
79 new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem, profiles.get(), 79 new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem, profiles.get(),
@@ -184,22 +184,8 @@ QList<QWidget*> ConfigureInput::GetSubTabs() const {
184void ConfigureInput::ApplyConfiguration() { 184void ConfigureInput::ApplyConfiguration() {
185 for (auto* controller : player_controllers) { 185 for (auto* controller : player_controllers) {
186 controller->ApplyConfiguration(); 186 controller->ApplyConfiguration();
187 controller->TryDisconnectSelectedController();
188 } 187 }
189 188
190 // This emulates a delay between disconnecting and reconnecting controllers as some games
191 // do not respond to a change in controller type if it was instantaneous.
192 using namespace std::chrono_literals;
193 std::this_thread::sleep_for(150ms);
194
195 for (auto* controller : player_controllers) {
196 controller->TryConnectSelectedController();
197 }
198
199 // This emulates a delay between disconnecting and reconnecting controllers as some games
200 // do not respond to a change in controller type if it was instantaneous.
201 std::this_thread::sleep_for(150ms);
202
203 advanced->ApplyConfiguration(); 189 advanced->ApplyConfiguration();
204 190
205 const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue(); 191 const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h
index 4cafa3dab..6e5edad58 100644
--- a/src/yuzu/configuration/configure_input.h
+++ b/src/yuzu/configuration/configure_input.h
@@ -42,7 +42,8 @@ public:
42 ~ConfigureInput() override; 42 ~ConfigureInput() override;
43 43
44 /// Initializes the input dialog with the given input subsystem. 44 /// Initializes the input dialog with the given input subsystem.
45 void Initialize(InputCommon::InputSubsystem* input_subsystem_, std::size_t max_players = 8); 45 void Initialize(InputCommon::InputSubsystem* input_subsystem_, Core::System& system,
46 std::size_t max_players = 8);
46 47
47 /// Save all button configurations to settings file. 48 /// Save all button configurations to settings file.
48 void ApplyConfiguration(); 49 void ApplyConfiguration();
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 09f0b219b..adc9706f1 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -13,9 +13,11 @@
13#include <QTimer> 13#include <QTimer>
14#include "common/param_package.h" 14#include "common/param_package.h"
15#include "core/core.h" 15#include "core/core.h"
16#include "core/hle/service/hid/controllers/npad.h" 16#include "core/hid/emulated_controller.h"
17#include "core/hle/service/hid/hid.h" 17#include "core/hid/hid_core.h"
18#include "core/hle/service/sm/sm.h" 18#include "core/hid/hid_types.h"
19#include "input_common/drivers/keyboard.h"
20#include "input_common/drivers/mouse.h"
19#include "input_common/main.h" 21#include "input_common/main.h"
20#include "ui_configure_input_player.h" 22#include "ui_configure_input_player.h"
21#include "yuzu/bootmanager.h" 23#include "yuzu/bootmanager.h"
@@ -26,8 +28,6 @@
26#include "yuzu/configuration/input_profiles.h" 28#include "yuzu/configuration/input_profiles.h"
27#include "yuzu/util/limitable_input_dialog.h" 29#include "yuzu/util/limitable_input_dialog.h"
28 30
29using namespace Service::HID;
30
31const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> 31const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
32 ConfigureInputPlayer::analog_sub_buttons{{ 32 ConfigureInputPlayer::analog_sub_buttons{{
33 "up", 33 "up",
@@ -40,31 +40,8 @@ namespace {
40 40
41constexpr std::size_t HANDHELD_INDEX = 8; 41constexpr std::size_t HANDHELD_INDEX = 8;
42 42
43void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index,
44 bool connected, Core::System& system) {
45 if (!system.IsPoweredOn()) {
46 return;
47 }
48 Service::SM::ServiceManager& sm = system.ServiceManager();
49
50 auto& npad = sm.GetService<Hid>("hid")->GetAppletResource()->GetController<Controller_NPad>(
51 HidController::NPad);
52
53 npad.UpdateControllerAt(npad.MapSettingsTypeToNPad(controller_type), npad_index, connected);
54}
55
56QString GetKeyName(int key_code) { 43QString GetKeyName(int key_code) {
57 switch (key_code) { 44 switch (key_code) {
58 case Qt::LeftButton:
59 return QObject::tr("Click 0");
60 case Qt::RightButton:
61 return QObject::tr("Click 1");
62 case Qt::MiddleButton:
63 return QObject::tr("Click 2");
64 case Qt::BackButton:
65 return QObject::tr("Click 3");
66 case Qt::ForwardButton:
67 return QObject::tr("Click 4");
68 case Qt::Key_Shift: 45 case Qt::Key_Shift:
69 return QObject::tr("Shift"); 46 return QObject::tr("Shift");
70 case Qt::Key_Control: 47 case Qt::Key_Control:
@@ -94,95 +71,26 @@ void SetAnalogParam(const Common::ParamPackage& input_param, Common::ParamPackag
94 } 71 }
95 analog_param.Set(button_name, input_param.Serialize()); 72 analog_param.Set(button_name, input_param.Serialize());
96} 73}
74} // namespace
97 75
98QString ButtonToText(const Common::ParamPackage& param) { 76QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
99 if (!param.Has("engine")) { 77 if (!param.Has("engine")) {
100 return QObject::tr("[not set]"); 78 return QObject::tr("[not set]");
101 } 79 }
102 80
81 // Retrieve the names from Qt
103 if (param.Get("engine", "") == "keyboard") { 82 if (param.Get("engine", "") == "keyboard") {
104 const QString button_str = GetKeyName(param.Get("code", 0)); 83 const QString button_str = GetKeyName(param.Get("code", 0));
105 const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); 84 const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
106 return QObject::tr("%1%2").arg(toggle, button_str); 85 return QObject::tr("%1%2").arg(toggle, button_str);
107 } 86 }
108 87
109 if (param.Get("engine", "") == "gcpad") { 88 std::string button_name = input_subsystem->GetButtonName(param);
110 if (param.Has("axis")) { 89 return QString::fromStdString(button_name);
111 const QString axis_str = QString::fromStdString(param.Get("axis", ""));
112 const QString direction_str = QString::fromStdString(param.Get("direction", ""));
113
114 return QObject::tr("GC Axis %1%2").arg(axis_str, direction_str);
115 }
116 if (param.Has("button")) {
117 const QString button_str = QString::number(int(std::log2(param.Get("button", 0))));
118 return QObject::tr("GC Button %1").arg(button_str);
119 }
120 return GetKeyName(param.Get("code", 0));
121 }
122
123 if (param.Get("engine", "") == "tas") {
124 if (param.Has("axis")) {
125 const QString axis_str = QString::fromStdString(param.Get("axis", ""));
126
127 return QObject::tr("TAS Axis %1").arg(axis_str);
128 }
129 if (param.Has("button")) {
130 const QString button_str = QString::number(int(std::log2(param.Get("button", 0))));
131 return QObject::tr("TAS Btn %1").arg(button_str);
132 }
133 return GetKeyName(param.Get("code", 0));
134 }
135
136 if (param.Get("engine", "") == "cemuhookudp") {
137 if (param.Has("pad_index")) {
138 const QString motion_str = QString::fromStdString(param.Get("pad_index", ""));
139 return QObject::tr("Motion %1").arg(motion_str);
140 }
141 return GetKeyName(param.Get("code", 0));
142 }
143
144 if (param.Get("engine", "") == "sdl") {
145 if (param.Has("hat")) {
146 const QString hat_str = QString::fromStdString(param.Get("hat", ""));
147 const QString direction_str = QString::fromStdString(param.Get("direction", ""));
148
149 return QObject::tr("Hat %1 %2").arg(hat_str, direction_str);
150 }
151
152 if (param.Has("axis")) {
153 const QString axis_str = QString::fromStdString(param.Get("axis", ""));
154 const QString direction_str = QString::fromStdString(param.Get("direction", ""));
155
156 return QObject::tr("Axis %1%2").arg(axis_str, direction_str);
157 }
158
159 if (param.Has("button")) {
160 const QString button_str = QString::fromStdString(param.Get("button", ""));
161 const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
162
163 return QObject::tr("%1Button %2").arg(toggle, button_str);
164 }
165
166 if (param.Has("motion")) {
167 return QObject::tr("SDL Motion");
168 }
169
170 return {};
171 }
172
173 if (param.Get("engine", "") == "mouse") {
174 if (param.Has("button")) {
175 const QString button_str = QString::number(int(param.Get("button", 0)));
176 const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
177 return QObject::tr("%1Click %2").arg(toggle, button_str);
178 }
179 return GetKeyName(param.Get("code", 0));
180 }
181
182 return QObject::tr("[unknown]");
183} 90}
184 91
185QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { 92QString ConfigureInputPlayer::AnalogToText(const Common::ParamPackage& param,
93 const std::string& dir) {
186 if (!param.Has("engine")) { 94 if (!param.Has("engine")) {
187 return QObject::tr("[not set]"); 95 return QObject::tr("[not set]");
188 } 96 }
@@ -191,39 +99,39 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir)
191 return ButtonToText(Common::ParamPackage{param.Get(dir, "")}); 99 return ButtonToText(Common::ParamPackage{param.Get(dir, "")});
192 } 100 }
193 101
102 if (!param.Has("axis_x") || !param.Has("axis_y")) {
103 return QObject::tr("[unknown]");
104 }
105
194 const auto engine_str = param.Get("engine", ""); 106 const auto engine_str = param.Get("engine", "");
195 const QString axis_x_str = QString::fromStdString(param.Get("axis_x", "")); 107 const QString axis_x_str = QString::fromStdString(param.Get("axis_x", ""));
196 const QString axis_y_str = QString::fromStdString(param.Get("axis_y", "")); 108 const QString axis_y_str = QString::fromStdString(param.Get("axis_y", ""));
197 const bool invert_x = param.Get("invert_x", "+") == "-"; 109 const bool invert_x = param.Get("invert_x", "+") == "-";
198 const bool invert_y = param.Get("invert_y", "+") == "-"; 110 const bool invert_y = param.Get("invert_y", "+") == "-";
199 if (engine_str == "sdl" || engine_str == "gcpad" || engine_str == "mouse" ||
200 engine_str == "tas") {
201 if (dir == "modifier") {
202 return QObject::tr("[unused]");
203 }
204 111
205 if (dir == "left") { 112 if (dir == "modifier") {
206 const QString invert_x_str = QString::fromStdString(invert_x ? "+" : "-"); 113 return QObject::tr("[unused]");
207 return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str); 114 }
208 }
209 if (dir == "right") {
210 const QString invert_x_str = QString::fromStdString(invert_x ? "-" : "+");
211 return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str);
212 }
213 if (dir == "up") {
214 const QString invert_y_str = QString::fromStdString(invert_y ? "-" : "+");
215 return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str);
216 }
217 if (dir == "down") {
218 const QString invert_y_str = QString::fromStdString(invert_y ? "+" : "-");
219 return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str);
220 }
221 115
222 return {}; 116 if (dir == "left") {
117 const QString invert_x_str = QString::fromStdString(invert_x ? "+" : "-");
118 return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str);
119 }
120 if (dir == "right") {
121 const QString invert_x_str = QString::fromStdString(invert_x ? "-" : "+");
122 return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str);
123 }
124 if (dir == "up") {
125 const QString invert_y_str = QString::fromStdString(invert_y ? "-" : "+");
126 return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str);
223 } 127 }
128 if (dir == "down") {
129 const QString invert_y_str = QString::fromStdString(invert_y ? "+" : "-");
130 return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str);
131 }
132
224 return QObject::tr("[unknown]"); 133 return QObject::tr("[unknown]");
225} 134}
226} // namespace
227 135
228ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, 136ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index,
229 QWidget* bottom_row, 137 QWidget* bottom_row,
@@ -234,6 +142,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
234 debug(debug), input_subsystem{input_subsystem_}, profiles(profiles_), 142 debug(debug), input_subsystem{input_subsystem_}, profiles(profiles_),
235 timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()), 143 timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()),
236 bottom_row(bottom_row), system{system_} { 144 bottom_row(bottom_row), system{system_} {
145
146 emulated_controller = system_.HIDCore().GetEmulatedControllerByIndex(player_index);
147 emulated_controller->EnableConfiguration();
237 ui->setupUi(this); 148 ui->setupUi(this);
238 149
239 setFocusPolicy(Qt::ClickFocus); 150 setFocusPolicy(Qt::ClickFocus);
@@ -275,31 +186,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
275 analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup}; 186 analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup};
276 analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange}; 187 analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange};
277 188
278 const auto ConfigureButtonClick = [&](QPushButton* button, std::size_t button_id, 189 ui->controllerFrame->SetController(emulated_controller);
279 Common::ParamPackage* param, int default_val,
280 InputCommon::Polling::DeviceType type) {
281 connect(button, &QPushButton::clicked, [=, this] {
282 HandleClick(
283 button, button_id,
284 [=, this](Common::ParamPackage params) {
285 // Workaround for ZL & ZR for analog triggers like on XBOX
286 // controllers. Analog triggers (from controllers like the XBOX
287 // controller) would not work due to a different range of their
288 // signals (from 0 to 255 on analog triggers instead of -32768 to
289 // 32768 on analog joysticks). The SDL driver misinterprets analog
290 // triggers as analog joysticks.
291 // TODO: reinterpret the signal range for analog triggers to map the
292 // values correctly. This is required for the correct emulation of
293 // the analog triggers of the GameCube controller.
294 if (button == ui->buttonZL || button == ui->buttonZR) {
295 params.Set("direction", "+");
296 params.Set("threshold", "0.5");
297 }
298 *param = std::move(params);
299 },
300 type);
301 });
302 };
303 190
304 for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { 191 for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
305 auto* const button = button_map[button_id]; 192 auto* const button = button_map[button_id];
@@ -308,34 +195,52 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
308 continue; 195 continue;
309 } 196 }
310 197
311 ConfigureButtonClick(button_map[button_id], button_id, &buttons_param[button_id], 198 connect(button, &QPushButton::clicked, [=, this] {
312 Config::default_buttons[button_id], 199 HandleClick(
313 InputCommon::Polling::DeviceType::Button); 200 button, button_id,
201 [=, this](Common::ParamPackage params) {
202 emulated_controller->SetButtonParam(button_id, params);
203 },
204 InputCommon::Polling::InputType::Button);
205 });
314 206
315 button->setContextMenuPolicy(Qt::CustomContextMenu); 207 button->setContextMenuPolicy(Qt::CustomContextMenu);
316 connect(button, &QPushButton::customContextMenuRequested, 208 connect(button, &QPushButton::customContextMenuRequested,
317 [=, this](const QPoint& menu_location) { 209 [=, this](const QPoint& menu_location) {
318 QMenu context_menu; 210 QMenu context_menu;
211 Common::ParamPackage param = emulated_controller->GetButtonParam(button_id);
319 context_menu.addAction(tr("Clear"), [&] { 212 context_menu.addAction(tr("Clear"), [&] {
320 buttons_param[button_id].Clear(); 213 emulated_controller->SetButtonParam(button_id, {});
321 button_map[button_id]->setText(tr("[not set]")); 214 button_map[button_id]->setText(tr("[not set]"));
322 }); 215 });
323 if (buttons_param[button_id].Has("toggle")) { 216 if (param.Has("button") || param.Has("hat")) {
324 context_menu.addAction(tr("Toggle button"), [&] { 217 context_menu.addAction(tr("Toggle button"), [&] {
325 const bool toggle_value = 218 const bool toggle_value = !param.Get("toggle", false);
326 !buttons_param[button_id].Get("toggle", false); 219 param.Set("toggle", toggle_value);
327 buttons_param[button_id].Set("toggle", toggle_value); 220 button_map[button_id]->setText(ButtonToText(param));
328 button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); 221 emulated_controller->SetButtonParam(button_id, param);
222 });
223 context_menu.addAction(tr("Invert button"), [&] {
224 const bool toggle_value = !param.Get("inverted", false);
225 param.Set("inverted", toggle_value);
226 button_map[button_id]->setText(ButtonToText(param));
227 emulated_controller->SetButtonParam(button_id, param);
329 }); 228 });
330 } 229 }
331 if (buttons_param[button_id].Has("threshold")) { 230 if (param.Has("axis")) {
231 context_menu.addAction(tr("Invert axis"), [&] {
232 const bool toggle_value = !(param.Get("invert", "+") == "-");
233 param.Set("invert", toggle_value ? "-" : "+");
234 button_map[button_id]->setText(ButtonToText(param));
235 emulated_controller->SetButtonParam(button_id, param);
236 });
332 context_menu.addAction(tr("Set threshold"), [&] { 237 context_menu.addAction(tr("Set threshold"), [&] {
333 const int button_threshold = static_cast<int>( 238 const int button_threshold =
334 buttons_param[button_id].Get("threshold", 0.5f) * 100.0f); 239 static_cast<int>(param.Get("threshold", 0.5f) * 100.0f);
335 const int new_threshold = QInputDialog::getInt( 240 const int new_threshold = QInputDialog::getInt(
336 this, tr("Set threshold"), tr("Choose a value between 0% and 100%"), 241 this, tr("Set threshold"), tr("Choose a value between 0% and 100%"),
337 button_threshold, 0, 100); 242 button_threshold, 0, 100);
338 buttons_param[button_id].Set("threshold", new_threshold / 100.0f); 243 param.Set("threshold", new_threshold / 100.0f);
339 244
340 if (button_id == Settings::NativeButton::ZL) { 245 if (button_id == Settings::NativeButton::ZL) {
341 ui->sliderZLThreshold->setValue(new_threshold); 246 ui->sliderZLThreshold->setValue(new_threshold);
@@ -343,11 +248,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
343 if (button_id == Settings::NativeButton::ZR) { 248 if (button_id == Settings::NativeButton::ZR) {
344 ui->sliderZRThreshold->setValue(new_threshold); 249 ui->sliderZRThreshold->setValue(new_threshold);
345 } 250 }
251 emulated_controller->SetButtonParam(button_id, param);
346 }); 252 });
347 } 253 }
348
349 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); 254 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
350 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
351 }); 255 });
352 } 256 }
353 257
@@ -357,9 +261,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
357 continue; 261 continue;
358 } 262 }
359 263
360 ConfigureButtonClick(motion_map[motion_id], motion_id, &motions_param[motion_id], 264 connect(button, &QPushButton::clicked, [=, this] {
361 Config::default_motions[motion_id], 265 HandleClick(
362 InputCommon::Polling::DeviceType::Motion); 266 button, motion_id,
267 [=, this](Common::ParamPackage params) {
268 emulated_controller->SetMotionParam(motion_id, params);
269 },
270 InputCommon::Polling::InputType::Motion);
271 });
363 272
364 button->setContextMenuPolicy(Qt::CustomContextMenu); 273 button->setContextMenuPolicy(Qt::CustomContextMenu);
365 274
@@ -367,7 +276,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
367 [=, this](const QPoint& menu_location) { 276 [=, this](const QPoint& menu_location) {
368 QMenu context_menu; 277 QMenu context_menu;
369 context_menu.addAction(tr("Clear"), [&] { 278 context_menu.addAction(tr("Clear"), [&] {
370 motions_param[motion_id].Clear(); 279 emulated_controller->SetMotionParam(motion_id, {});
371 motion_map[motion_id]->setText(tr("[not set]")); 280 motion_map[motion_id]->setText(tr("[not set]"));
372 }); 281 });
373 context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location)); 282 context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location));
@@ -375,16 +284,22 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
375 } 284 }
376 285
377 connect(ui->sliderZLThreshold, &QSlider::valueChanged, [=, this] { 286 connect(ui->sliderZLThreshold, &QSlider::valueChanged, [=, this] {
378 if (buttons_param[Settings::NativeButton::ZL].Has("threshold")) { 287 Common::ParamPackage param =
288 emulated_controller->GetButtonParam(Settings::NativeButton::ZL);
289 if (param.Has("threshold")) {
379 const auto slider_value = ui->sliderZLThreshold->value(); 290 const auto slider_value = ui->sliderZLThreshold->value();
380 buttons_param[Settings::NativeButton::ZL].Set("threshold", slider_value / 100.0f); 291 param.Set("threshold", slider_value / 100.0f);
292 emulated_controller->SetButtonParam(Settings::NativeButton::ZL, param);
381 } 293 }
382 }); 294 });
383 295
384 connect(ui->sliderZRThreshold, &QSlider::valueChanged, [=, this] { 296 connect(ui->sliderZRThreshold, &QSlider::valueChanged, [=, this] {
385 if (buttons_param[Settings::NativeButton::ZR].Has("threshold")) { 297 Common::ParamPackage param =
298 emulated_controller->GetButtonParam(Settings::NativeButton::ZR);
299 if (param.Has("threshold")) {
386 const auto slider_value = ui->sliderZRThreshold->value(); 300 const auto slider_value = ui->sliderZRThreshold->value();
387 buttons_param[Settings::NativeButton::ZR].Set("threshold", slider_value / 100.0f); 301 param.Set("threshold", slider_value / 100.0f);
302 emulated_controller->SetButtonParam(Settings::NativeButton::ZR, param);
388 } 303 }
389 }); 304 });
390 305
@@ -412,45 +327,45 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
412 HandleClick( 327 HandleClick(
413 analog_map_buttons[analog_id][sub_button_id], analog_id, 328 analog_map_buttons[analog_id][sub_button_id], analog_id,
414 [=, this](const Common::ParamPackage& params) { 329 [=, this](const Common::ParamPackage& params) {
415 SetAnalogParam(params, analogs_param[analog_id], 330 Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
416 analog_sub_buttons[sub_button_id]); 331 SetAnalogParam(params, param, analog_sub_buttons[sub_button_id]);
332 emulated_controller->SetStickParam(analog_id, param);
417 }, 333 },
418 InputCommon::Polling::DeviceType::AnalogPreferred); 334 InputCommon::Polling::InputType::Stick);
419 }); 335 });
420 336
421 analog_button->setContextMenuPolicy(Qt::CustomContextMenu); 337 analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
422 338
423 connect( 339 connect(analog_button, &QPushButton::customContextMenuRequested,
424 analog_button, &QPushButton::customContextMenuRequested, 340 [=, this](const QPoint& menu_location) {
425 [=, this](const QPoint& menu_location) { 341 QMenu context_menu;
426 QMenu context_menu; 342 Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
427 context_menu.addAction(tr("Clear"), [&] { 343 context_menu.addAction(tr("Clear"), [&] {
428 analogs_param[analog_id].Clear(); 344 emulated_controller->SetStickParam(analog_id, {});
429 analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); 345 analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
430 }); 346 });
431 context_menu.addAction(tr("Invert axis"), [&] { 347 context_menu.addAction(tr("Invert axis"), [&] {
432 if (sub_button_id == 2 || sub_button_id == 3) { 348 if (sub_button_id == 2 || sub_button_id == 3) {
433 const bool invert_value = 349 const bool invert_value = param.Get("invert_x", "+") == "-";
434 analogs_param[analog_id].Get("invert_x", "+") == "-"; 350 const std::string invert_str = invert_value ? "+" : "-";
435 const std::string invert_str = invert_value ? "+" : "-"; 351 param.Set("invert_x", invert_str);
436 analogs_param[analog_id].Set("invert_x", invert_str); 352 emulated_controller->SetStickParam(analog_id, param);
437 } 353 }
438 if (sub_button_id == 0 || sub_button_id == 1) { 354 if (sub_button_id == 0 || sub_button_id == 1) {
439 const bool invert_value = 355 const bool invert_value = param.Get("invert_y", "+") == "-";
440 analogs_param[analog_id].Get("invert_y", "+") == "-"; 356 const std::string invert_str = invert_value ? "+" : "-";
441 const std::string invert_str = invert_value ? "+" : "-"; 357 param.Set("invert_y", invert_str);
442 analogs_param[analog_id].Set("invert_y", invert_str); 358 emulated_controller->SetStickParam(analog_id, param);
443 } 359 }
444 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; 360 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM;
445 ++sub_button_id) { 361 ++sub_button_id) {
446 analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( 362 analog_map_buttons[analog_id][sub_button_id]->setText(
447 analogs_param[analog_id], analog_sub_buttons[sub_button_id])); 363 AnalogToText(param, analog_sub_buttons[sub_button_id]));
448 } 364 }
365 });
366 context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(
367 menu_location));
449 }); 368 });
450 context_menu.exec(
451 analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(menu_location));
452 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
453 });
454 } 369 }
455 370
456 // Handle clicks for the modifier buttons as well. 371 // Handle clicks for the modifier buttons as well.
@@ -458,9 +373,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
458 HandleClick( 373 HandleClick(
459 analog_map_modifier_button[analog_id], analog_id, 374 analog_map_modifier_button[analog_id], analog_id,
460 [=, this](const Common::ParamPackage& params) { 375 [=, this](const Common::ParamPackage& params) {
461 analogs_param[analog_id].Set("modifier", params.Serialize()); 376 Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
377 param.Set("modifier", params.Serialize());
378 emulated_controller->SetStickParam(analog_id, param);
462 }, 379 },
463 InputCommon::Polling::DeviceType::Button); 380 InputCommon::Polling::InputType::Button);
464 }); 381 });
465 382
466 analog_map_modifier_button[analog_id]->setContextMenuPolicy(Qt::CustomContextMenu); 383 analog_map_modifier_button[analog_id]->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -468,18 +385,21 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
468 connect(analog_map_modifier_button[analog_id], &QPushButton::customContextMenuRequested, 385 connect(analog_map_modifier_button[analog_id], &QPushButton::customContextMenuRequested,
469 [=, this](const QPoint& menu_location) { 386 [=, this](const QPoint& menu_location) {
470 QMenu context_menu; 387 QMenu context_menu;
388 Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
471 context_menu.addAction(tr("Clear"), [&] { 389 context_menu.addAction(tr("Clear"), [&] {
472 analogs_param[analog_id].Set("modifier", ""); 390 param.Set("modifier", "");
473 analog_map_modifier_button[analog_id]->setText(tr("[not set]")); 391 analog_map_modifier_button[analog_id]->setText(tr("[not set]"));
392 emulated_controller->SetStickParam(analog_id, param);
474 }); 393 });
475 context_menu.addAction(tr("Toggle button"), [&] { 394 context_menu.addAction(tr("Toggle button"), [&] {
476 Common::ParamPackage modifier_param = 395 Common::ParamPackage modifier_param =
477 Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")}; 396 Common::ParamPackage{param.Get("modifier", "")};
478 const bool toggle_value = !modifier_param.Get("toggle", false); 397 const bool toggle_value = !modifier_param.Get("toggle", false);
479 modifier_param.Set("toggle", toggle_value); 398 modifier_param.Set("toggle", toggle_value);
480 analogs_param[analog_id].Set("modifier", modifier_param.Serialize()); 399 param.Set("modifier", modifier_param.Serialize());
481 analog_map_modifier_button[analog_id]->setText( 400 analog_map_modifier_button[analog_id]->setText(
482 ButtonToText(modifier_param)); 401 ButtonToText(modifier_param));
402 emulated_controller->SetStickParam(analog_id, param);
483 }); 403 });
484 context_menu.exec( 404 context_menu.exec(
485 analog_map_modifier_button[analog_id]->mapToGlobal(menu_location)); 405 analog_map_modifier_button[analog_id]->mapToGlobal(menu_location));
@@ -487,37 +407,39 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
487 407
488 connect(analog_map_range_spinbox[analog_id], qOverload<int>(&QSpinBox::valueChanged), 408 connect(analog_map_range_spinbox[analog_id], qOverload<int>(&QSpinBox::valueChanged),
489 [=, this] { 409 [=, this] {
410 Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
490 const auto spinbox_value = analog_map_range_spinbox[analog_id]->value(); 411 const auto spinbox_value = analog_map_range_spinbox[analog_id]->value();
491 analogs_param[analog_id].Set("range", spinbox_value / 100.0f); 412 param.Set("range", spinbox_value / 100.0f);
492 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); 413 emulated_controller->SetStickParam(analog_id, param);
493 }); 414 });
494 415
495 connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] { 416 connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] {
417 Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
496 const auto slider_value = analog_map_deadzone_slider[analog_id]->value(); 418 const auto slider_value = analog_map_deadzone_slider[analog_id]->value();
497 analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value)); 419 analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value));
498 analogs_param[analog_id].Set("deadzone", slider_value / 100.0f); 420 param.Set("deadzone", slider_value / 100.0f);
499 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); 421 emulated_controller->SetStickParam(analog_id, param);
500 }); 422 });
501 423
502 connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] { 424 connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] {
425 Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
503 const auto slider_value = analog_map_modifier_slider[analog_id]->value(); 426 const auto slider_value = analog_map_modifier_slider[analog_id]->value();
504 analog_map_modifier_label[analog_id]->setText( 427 analog_map_modifier_label[analog_id]->setText(
505 tr("Modifier Range: %1%").arg(slider_value)); 428 tr("Modifier Range: %1%").arg(slider_value));
506 analogs_param[analog_id].Set("modifier_scale", slider_value / 100.0f); 429 param.Set("modifier_scale", slider_value / 100.0f);
430 emulated_controller->SetStickParam(analog_id, param);
507 }); 431 });
508 } 432 }
509 433
510 // Player Connected checkbox 434 // Player Connected checkbox
511 connect(ui->groupConnectedController, &QGroupBox::toggled, [this](bool checked) { 435 connect(ui->groupConnectedController, &QGroupBox::toggled,
512 emit Connected(checked); 436 [this](bool checked) { emit Connected(checked); });
513 ui->controllerFrame->SetConnectedStatus(checked);
514 });
515 437
516 if (player_index == 0) { 438 if (player_index == 0) {
517 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), 439 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged),
518 [this](int index) { 440 [this](int index) {
519 emit HandheldStateChanged(GetControllerTypeFromIndex(index) == 441 emit HandheldStateChanged(GetControllerTypeFromIndex(index) ==
520 Settings::ControllerType::Handheld); 442 Core::HID::NpadType::Handheld);
521 }); 443 });
522 } 444 }
523 445
@@ -534,13 +456,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
534 SetConnectableControllers(); 456 SetConnectableControllers();
535 } 457 }
536 458
537 UpdateControllerIcon();
538 UpdateControllerAvailableButtons(); 459 UpdateControllerAvailableButtons();
539 UpdateControllerEnabledButtons(); 460 UpdateControllerEnabledButtons();
540 UpdateControllerButtonNames(); 461 UpdateControllerButtonNames();
541 UpdateMotionButtons(); 462 UpdateMotionButtons();
542 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) { 463 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) {
543 UpdateControllerIcon();
544 UpdateControllerAvailableButtons(); 464 UpdateControllerAvailableButtons();
545 UpdateControllerEnabledButtons(); 465 UpdateControllerEnabledButtons();
546 UpdateControllerButtonNames(); 466 UpdateControllerButtonNames();
@@ -560,13 +480,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
560 connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); 480 connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
561 481
562 connect(poll_timer.get(), &QTimer::timeout, [this] { 482 connect(poll_timer.get(), &QTimer::timeout, [this] {
563 Common::ParamPackage params; 483 const auto& params = input_subsystem->GetNextInput();
564 for (auto& poller : device_pollers) { 484 if (params.Has("engine") && IsInputAcceptable(params)) {
565 params = poller->GetNextInput(); 485 SetPollingResult(params, false);
566 if (params.Has("engine") && IsInputAcceptable(params)) { 486 return;
567 SetPollingResult(params, false);
568 return;
569 }
570 } 487 }
571 }); 488 });
572 489
@@ -582,110 +499,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
582 &ConfigureInputPlayer::SaveProfile); 499 &ConfigureInputPlayer::SaveProfile);
583 500
584 LoadConfiguration(); 501 LoadConfiguration();
585 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
586 ui->controllerFrame->SetConnectedStatus(ui->groupConnectedController->isChecked());
587} 502}
588 503
589ConfigureInputPlayer::~ConfigureInputPlayer() = default; 504ConfigureInputPlayer::~ConfigureInputPlayer() {
505 emulated_controller->DisableConfiguration();
506};
590 507
591void ConfigureInputPlayer::ApplyConfiguration() { 508void ConfigureInputPlayer::ApplyConfiguration() {
592 auto& player = Settings::values.players.GetValue()[player_index]; 509 emulated_controller->SaveCurrentConfig();
593 auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons;
594 auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs;
595
596 std::transform(buttons_param.begin(), buttons_param.end(), buttons.begin(),
597 [](const Common::ParamPackage& param) { return param.Serialize(); });
598 std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(),
599 [](const Common::ParamPackage& param) { return param.Serialize(); });
600
601 if (debug) {
602 return;
603 }
604
605 auto& motions = player.motions;
606
607 std::transform(motions_param.begin(), motions_param.end(), motions.begin(),
608 [](const Common::ParamPackage& param) { return param.Serialize(); });
609
610 // Apply configuration for handheld
611 if (player_index == 0) {
612 auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
613 const auto handheld_connected = handheld.connected;
614 handheld = player;
615 handheld.connected = handheld_connected;
616 }
617}
618
619void ConfigureInputPlayer::TryConnectSelectedController() {
620 auto& player = Settings::values.players.GetValue()[player_index];
621
622 const auto controller_type =
623 GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
624 const auto player_connected = ui->groupConnectedController->isChecked() &&
625 controller_type != Settings::ControllerType::Handheld;
626
627 // Connect Handheld depending on Player 1's controller configuration.
628 if (player_index == 0) {
629 auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
630 const auto handheld_connected = ui->groupConnectedController->isChecked() &&
631 controller_type == Settings::ControllerType::Handheld;
632 // Connect only if handheld is going from disconnected to connected
633 if (!handheld.connected && handheld_connected) {
634 UpdateController(controller_type, HANDHELD_INDEX, true, system);
635 }
636 handheld.connected = handheld_connected;
637 }
638
639 if (player.controller_type == controller_type && player.connected == player_connected) {
640 // Set vibration devices in the event that the input device has changed.
641 ConfigureVibration::SetVibrationDevices(player_index);
642 return;
643 }
644
645 player.controller_type = controller_type;
646 player.connected = player_connected;
647
648 ConfigureVibration::SetVibrationDevices(player_index);
649
650 if (!player.connected) {
651 return;
652 }
653
654 UpdateController(controller_type, player_index, true, system);
655}
656
657void ConfigureInputPlayer::TryDisconnectSelectedController() {
658 const auto& player = Settings::values.players.GetValue()[player_index];
659
660 const auto controller_type =
661 GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
662 const auto player_connected = ui->groupConnectedController->isChecked() &&
663 controller_type != Settings::ControllerType::Handheld;
664
665 // Disconnect Handheld depending on Player 1's controller configuration.
666 if (player_index == 0 && player.controller_type == Settings::ControllerType::Handheld) {
667 const auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
668 const auto handheld_connected = ui->groupConnectedController->isChecked() &&
669 controller_type == Settings::ControllerType::Handheld;
670 // Disconnect only if handheld is going from connected to disconnected
671 if (handheld.connected && !handheld_connected) {
672 UpdateController(controller_type, HANDHELD_INDEX, false, system);
673 }
674 return;
675 }
676
677 // Do not do anything if the controller configuration has not changed.
678 if (player.controller_type == controller_type && player.connected == player_connected) {
679 return;
680 }
681
682 // Do not disconnect if the controller is already disconnected
683 if (!player.connected) {
684 return;
685 }
686
687 // Disconnect the controller first.
688 UpdateController(controller_type, player_index, false, system);
689} 510}
690 511
691void ConfigureInputPlayer::showEvent(QShowEvent* event) { 512void ConfigureInputPlayer::showEvent(QShowEvent* event) {
@@ -710,34 +531,11 @@ void ConfigureInputPlayer::RetranslateUI() {
710} 531}
711 532
712void ConfigureInputPlayer::LoadConfiguration() { 533void ConfigureInputPlayer::LoadConfiguration() {
713 auto& player = Settings::values.players.GetValue()[player_index];
714 if (debug) {
715 std::transform(Settings::values.debug_pad_buttons.begin(),
716 Settings::values.debug_pad_buttons.end(), buttons_param.begin(),
717 [](const std::string& str) { return Common::ParamPackage(str); });
718 std::transform(Settings::values.debug_pad_analogs.begin(),
719 Settings::values.debug_pad_analogs.end(), analogs_param.begin(),
720 [](const std::string& str) { return Common::ParamPackage(str); });
721 } else {
722 std::transform(player.buttons.begin(), player.buttons.end(), buttons_param.begin(),
723 [](const std::string& str) { return Common::ParamPackage(str); });
724 std::transform(player.analogs.begin(), player.analogs.end(), analogs_param.begin(),
725 [](const std::string& str) { return Common::ParamPackage(str); });
726 std::transform(player.motions.begin(), player.motions.end(), motions_param.begin(),
727 [](const std::string& str) { return Common::ParamPackage(str); });
728 }
729
730 UpdateUI(); 534 UpdateUI();
731 UpdateInputDeviceCombobox(); 535 UpdateInputDeviceCombobox();
732 536 const int comboBoxIndex = GetIndexFromControllerType(emulated_controller->GetNpadType());
733 if (debug) { 537 ui->comboControllerType->setCurrentIndex(comboBoxIndex);
734 return; 538 ui->groupConnectedController->setChecked(emulated_controller->IsConnected());
735 }
736
737 ui->comboControllerType->setCurrentIndex(GetIndexFromControllerType(player.controller_type));
738 ui->groupConnectedController->setChecked(
739 player.connected ||
740 (player_index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected));
741} 539}
742 540
743void ConfigureInputPlayer::ConnectPlayer(bool connected) { 541void ConfigureInputPlayer::ConnectPlayer(bool connected) {
@@ -751,48 +549,63 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
751 return; 549 return;
752 } 550 }
753 551
754 // Find the first button that isn't empty. 552 const auto devices = emulated_controller->GetMappedDevices();
755 const auto button_param = 553 UpdateInputDevices();
756 std::find_if(buttons_param.begin(), buttons_param.end(), 554
757 [](const Common::ParamPackage param) { return param.Has("engine"); }); 555 if (devices.empty()) {
758 const bool buttons_empty = button_param == buttons_param.end(); 556 return;
557 }
558
559 if (devices.size() > 2) {
560 ui->comboDevices->setCurrentIndex(0);
561 return;
562 }
563
564 const auto first_engine = devices[0].Get("engine", "");
565 const auto first_guid = devices[0].Get("guid", "");
566 const auto first_port = devices[0].Get("port", "");
759 567
760 const auto current_engine = button_param->Get("engine", ""); 568 if (devices.size() == 1) {
761 const auto current_guid = button_param->Get("guid", ""); 569 const auto devices_it =
762 const auto current_port = button_param->Get("port", ""); 570 std::find_if(input_devices.begin(), input_devices.end(),
571 [first_engine, first_guid, first_port](const Common::ParamPackage param) {
572 return param.Get("engine", "") == first_engine &&
573 param.Get("guid", "") == first_guid &&
574 param.Get("port", "") == first_port;
575 });
576 const int device_index =
577 devices_it != input_devices.end()
578 ? static_cast<int>(std::distance(input_devices.begin(), devices_it))
579 : 0;
580 ui->comboDevices->setCurrentIndex(device_index);
581 return;
582 }
763 583
764 const bool is_keyboard_mouse = current_engine == "keyboard" || current_engine == "mouse"; 584 const auto second_engine = devices[1].Get("engine", "");
585 const auto second_guid = devices[1].Get("guid", "");
586 const auto second_port = devices[1].Get("port", "");
765 587
766 UpdateInputDevices(); 588 const bool is_keyboard_mouse = (first_engine == "keyboard" || first_engine == "mouse") &&
589 (second_engine == "keyboard" || second_engine == "mouse");
767 590
768 if (buttons_empty) { 591 if (is_keyboard_mouse) {
592 ui->comboDevices->setCurrentIndex(2);
769 return; 593 return;
770 } 594 }
771 595
772 const bool all_one_device = 596 const bool is_engine_equal = first_engine == second_engine;
773 std::all_of(buttons_param.begin(), buttons_param.end(), 597 const bool is_port_equal = first_port == second_port;
774 [current_engine, current_guid, current_port,
775 is_keyboard_mouse](const Common::ParamPackage param) {
776 if (is_keyboard_mouse) {
777 return !param.Has("engine") || param.Get("engine", "") == "keyboard" ||
778 param.Get("engine", "") == "mouse";
779 }
780 return !param.Has("engine") || (param.Get("engine", "") == current_engine &&
781 param.Get("guid", "") == current_guid &&
782 param.Get("port", "") == current_port);
783 });
784 598
785 if (all_one_device) { 599 if (is_engine_equal && is_port_equal) {
786 if (is_keyboard_mouse) {
787 ui->comboDevices->setCurrentIndex(1);
788 return;
789 }
790 const auto devices_it = std::find_if( 600 const auto devices_it = std::find_if(
791 input_devices.begin(), input_devices.end(), 601 input_devices.begin(), input_devices.end(),
792 [current_engine, current_guid, current_port](const Common::ParamPackage param) { 602 [first_engine, first_guid, second_guid, first_port](const Common::ParamPackage param) {
793 return param.Get("class", "") == current_engine && 603 const bool is_guid_valid =
794 param.Get("guid", "") == current_guid && 604 (param.Get("guid", "") == first_guid &&
795 param.Get("port", "") == current_port; 605 param.Get("guid2", "") == second_guid) ||
606 (param.Get("guid", "") == second_guid && param.Get("guid2", "") == first_guid);
607 return param.Get("engine", "") == first_engine && is_guid_valid &&
608 param.Get("port", "") == first_port;
796 }); 609 });
797 const int device_index = 610 const int device_index =
798 devices_it != input_devices.end() 611 devices_it != input_devices.end()
@@ -814,8 +627,7 @@ void ConfigureInputPlayer::ClearAll() {
814 if (button == nullptr) { 627 if (button == nullptr) {
815 continue; 628 continue;
816 } 629 }
817 630 emulated_controller->SetButtonParam(button_id, {});
818 buttons_param[button_id].Clear();
819 } 631 }
820 632
821 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { 633 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
@@ -824,8 +636,7 @@ void ConfigureInputPlayer::ClearAll() {
824 if (analog_button == nullptr) { 636 if (analog_button == nullptr) {
825 continue; 637 continue;
826 } 638 }
827 639 emulated_controller->SetStickParam(analog_id, {});
828 analogs_param[analog_id].Clear();
829 } 640 }
830 } 641 }
831 642
@@ -834,8 +645,7 @@ void ConfigureInputPlayer::ClearAll() {
834 if (motion_button == nullptr) { 645 if (motion_button == nullptr) {
835 continue; 646 continue;
836 } 647 }
837 648 emulated_controller->SetMotionParam(motion_id, {});
838 motions_param[motion_id].Clear();
839 } 649 }
840 650
841 UpdateUI(); 651 UpdateUI();
@@ -844,26 +654,31 @@ void ConfigureInputPlayer::ClearAll() {
844 654
845void ConfigureInputPlayer::UpdateUI() { 655void ConfigureInputPlayer::UpdateUI() {
846 for (int button = 0; button < Settings::NativeButton::NumButtons; ++button) { 656 for (int button = 0; button < Settings::NativeButton::NumButtons; ++button) {
847 button_map[button]->setText(ButtonToText(buttons_param[button])); 657 const Common::ParamPackage param = emulated_controller->GetButtonParam(button);
658 button_map[button]->setText(ButtonToText(param));
848 } 659 }
849 660
850 if (buttons_param[Settings::NativeButton::ZL].Has("threshold")) { 661 const Common::ParamPackage ZL_param =
851 const int button_threshold = static_cast<int>( 662 emulated_controller->GetButtonParam(Settings::NativeButton::ZL);
852 buttons_param[Settings::NativeButton::ZL].Get("threshold", 0.5f) * 100.0f); 663 if (ZL_param.Has("threshold")) {
664 const int button_threshold = static_cast<int>(ZL_param.Get("threshold", 0.5f) * 100.0f);
853 ui->sliderZLThreshold->setValue(button_threshold); 665 ui->sliderZLThreshold->setValue(button_threshold);
854 } 666 }
855 667
856 if (buttons_param[Settings::NativeButton::ZR].Has("threshold")) { 668 const Common::ParamPackage ZR_param =
857 const int button_threshold = static_cast<int>( 669 emulated_controller->GetButtonParam(Settings::NativeButton::ZR);
858 buttons_param[Settings::NativeButton::ZR].Get("threshold", 0.5f) * 100.0f); 670 if (ZR_param.Has("threshold")) {
671 const int button_threshold = static_cast<int>(ZR_param.Get("threshold", 0.5f) * 100.0f);
859 ui->sliderZRThreshold->setValue(button_threshold); 672 ui->sliderZRThreshold->setValue(button_threshold);
860 } 673 }
861 674
862 for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { 675 for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
863 motion_map[motion_id]->setText(ButtonToText(motions_param[motion_id])); 676 const Common::ParamPackage param = emulated_controller->GetMotionParam(motion_id);
677 motion_map[motion_id]->setText(ButtonToText(param));
864 } 678 }
865 679
866 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { 680 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
681 const Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
867 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { 682 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
868 auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; 683 auto* const analog_button = analog_map_buttons[analog_id][sub_button_id];
869 684
@@ -871,12 +686,11 @@ void ConfigureInputPlayer::UpdateUI() {
871 continue; 686 continue;
872 } 687 }
873 688
874 analog_button->setText( 689 analog_button->setText(AnalogToText(param, analog_sub_buttons[sub_button_id]));
875 AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
876 } 690 }
877 691
878 analog_map_modifier_button[analog_id]->setText( 692 analog_map_modifier_button[analog_id]->setText(
879 ButtonToText(Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")})); 693 ButtonToText(Common::ParamPackage{param.Get("modifier", "")}));
880 694
881 const auto deadzone_label = analog_map_deadzone_label[analog_id]; 695 const auto deadzone_label = analog_map_deadzone_label[analog_id];
882 const auto deadzone_slider = analog_map_deadzone_slider[analog_id]; 696 const auto deadzone_slider = analog_map_deadzone_slider[analog_id];
@@ -887,26 +701,14 @@ void ConfigureInputPlayer::UpdateUI() {
887 const auto range_spinbox = analog_map_range_spinbox[analog_id]; 701 const auto range_spinbox = analog_map_range_spinbox[analog_id];
888 702
889 int slider_value; 703 int slider_value;
890 auto& param = analogs_param[analog_id]; 704 const bool is_controller = input_subsystem->IsController(param);
891 const bool is_controller =
892 param.Get("engine", "") == "sdl" || param.Get("engine", "") == "gcpad" ||
893 param.Get("engine", "") == "mouse" || param.Get("engine", "") == "tas";
894 705
895 if (is_controller) { 706 if (is_controller) {
896 if (!param.Has("deadzone")) { 707 slider_value = static_cast<int>(param.Get("deadzone", 0.15f) * 100);
897 param.Set("deadzone", 0.1f);
898 }
899 slider_value = static_cast<int>(param.Get("deadzone", 0.1f) * 100);
900 deadzone_label->setText(tr("Deadzone: %1%").arg(slider_value)); 708 deadzone_label->setText(tr("Deadzone: %1%").arg(slider_value));
901 deadzone_slider->setValue(slider_value); 709 deadzone_slider->setValue(slider_value);
902 if (!param.Has("range")) {
903 param.Set("range", 1.0f);
904 }
905 range_spinbox->setValue(static_cast<int>(param.Get("range", 1.0f) * 100)); 710 range_spinbox->setValue(static_cast<int>(param.Get("range", 1.0f) * 100));
906 } else { 711 } else {
907 if (!param.Has("modifier_scale")) {
908 param.Set("modifier_scale", 0.5f);
909 }
910 slider_value = static_cast<int>(param.Get("modifier_scale", 0.5f) * 100); 712 slider_value = static_cast<int>(param.Get("modifier_scale", 0.5f) * 100);
911 modifier_label->setText(tr("Modifier Range: %1%").arg(slider_value)); 713 modifier_label->setText(tr("Modifier Range: %1%").arg(slider_value));
912 modifier_slider->setValue(slider_value); 714 modifier_slider->setValue(slider_value);
@@ -918,49 +720,48 @@ void ConfigureInputPlayer::UpdateUI() {
918 modifier_label->setVisible(!is_controller); 720 modifier_label->setVisible(!is_controller);
919 modifier_slider->setVisible(!is_controller); 721 modifier_slider->setVisible(!is_controller);
920 range_groupbox->setVisible(is_controller); 722 range_groupbox->setVisible(is_controller);
921 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
922 } 723 }
923} 724}
924 725
925void ConfigureInputPlayer::SetConnectableControllers() { 726void ConfigureInputPlayer::SetConnectableControllers() {
926 const auto add_controllers = [this](bool enable_all, 727 const auto add_controllers = [this](bool enable_all,
927 Controller_NPad::NpadStyleSet npad_style_set = {}) { 728 Core::HID::NpadStyleTag npad_style_set = {}) {
928 index_controller_type_pairs.clear(); 729 index_controller_type_pairs.clear();
929 ui->comboControllerType->clear(); 730 ui->comboControllerType->clear();
930 731
931 if (enable_all || npad_style_set.fullkey == 1) { 732 if (enable_all || npad_style_set.fullkey == 1) {
932 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 733 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
933 Settings::ControllerType::ProController); 734 Core::HID::NpadType::ProController);
934 ui->comboControllerType->addItem(tr("Pro Controller")); 735 ui->comboControllerType->addItem(tr("Pro Controller"));
935 } 736 }
936 737
937 if (enable_all || npad_style_set.joycon_dual == 1) { 738 if (enable_all || npad_style_set.joycon_dual == 1) {
938 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 739 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
939 Settings::ControllerType::DualJoyconDetached); 740 Core::HID::NpadType::JoyconDual);
940 ui->comboControllerType->addItem(tr("Dual Joycons")); 741 ui->comboControllerType->addItem(tr("Dual Joycons"));
941 } 742 }
942 743
943 if (enable_all || npad_style_set.joycon_left == 1) { 744 if (enable_all || npad_style_set.joycon_left == 1) {
944 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 745 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
945 Settings::ControllerType::LeftJoycon); 746 Core::HID::NpadType::JoyconLeft);
946 ui->comboControllerType->addItem(tr("Left Joycon")); 747 ui->comboControllerType->addItem(tr("Left Joycon"));
947 } 748 }
948 749
949 if (enable_all || npad_style_set.joycon_right == 1) { 750 if (enable_all || npad_style_set.joycon_right == 1) {
950 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 751 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
951 Settings::ControllerType::RightJoycon); 752 Core::HID::NpadType::JoyconRight);
952 ui->comboControllerType->addItem(tr("Right Joycon")); 753 ui->comboControllerType->addItem(tr("Right Joycon"));
953 } 754 }
954 755
955 if (player_index == 0 && (enable_all || npad_style_set.handheld == 1)) { 756 if (player_index == 0 && (enable_all || npad_style_set.handheld == 1)) {
956 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 757 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
957 Settings::ControllerType::Handheld); 758 Core::HID::NpadType::Handheld);
958 ui->comboControllerType->addItem(tr("Handheld")); 759 ui->comboControllerType->addItem(tr("Handheld"));
959 } 760 }
960 761
961 if (enable_all || npad_style_set.gamecube == 1) { 762 if (enable_all || npad_style_set.gamecube == 1) {
962 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 763 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
963 Settings::ControllerType::GameCube); 764 Core::HID::NpadType::GameCube);
964 ui->comboControllerType->addItem(tr("GameCube Controller")); 765 ui->comboControllerType->addItem(tr("GameCube Controller"));
965 } 766 }
966 }; 767 };
@@ -970,27 +771,22 @@ void ConfigureInputPlayer::SetConnectableControllers() {
970 return; 771 return;
971 } 772 }
972 773
973 Service::SM::ServiceManager& sm = system.ServiceManager(); 774 add_controllers(false, system.HIDCore().GetSupportedStyleTag());
974
975 auto& npad = sm.GetService<Hid>("hid")->GetAppletResource()->GetController<Controller_NPad>(
976 HidController::NPad);
977
978 add_controllers(false, npad.GetSupportedStyleSet());
979} 775}
980 776
981Settings::ControllerType ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const { 777Core::HID::NpadType ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const {
982 const auto it = 778 const auto it =
983 std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), 779 std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(),
984 [index](const auto& pair) { return pair.first == index; }); 780 [index](const auto& pair) { return pair.first == index; });
985 781
986 if (it == index_controller_type_pairs.end()) { 782 if (it == index_controller_type_pairs.end()) {
987 return Settings::ControllerType::ProController; 783 return Core::HID::NpadType::ProController;
988 } 784 }
989 785
990 return it->second; 786 return it->second;
991} 787}
992 788
993int ConfigureInputPlayer::GetIndexFromControllerType(Settings::ControllerType type) const { 789int ConfigureInputPlayer::GetIndexFromControllerType(Core::HID::NpadType type) const {
994 const auto it = 790 const auto it =
995 std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), 791 std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(),
996 [type](const auto& pair) { return pair.second == type; }); 792 [type](const auto& pair) { return pair.second == type; });
@@ -1005,52 +801,15 @@ int ConfigureInputPlayer::GetIndexFromControllerType(Settings::ControllerType ty
1005void ConfigureInputPlayer::UpdateInputDevices() { 801void ConfigureInputPlayer::UpdateInputDevices() {
1006 input_devices = input_subsystem->GetInputDevices(); 802 input_devices = input_subsystem->GetInputDevices();
1007 ui->comboDevices->clear(); 803 ui->comboDevices->clear();
1008 for (auto& device : input_devices) { 804 for (auto device : input_devices) {
1009 const std::string display = device.Get("display", "Unknown"); 805 ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {});
1010 ui->comboDevices->addItem(QString::fromStdString(display), {});
1011 if (display == "TAS") {
1012 device.Set("pad", static_cast<u8>(player_index));
1013 }
1014 } 806 }
1015} 807}
1016 808
1017void ConfigureInputPlayer::UpdateControllerIcon() {
1018 // We aren't using Qt's built in theme support here since we aren't drawing an icon (and its
1019 // "nonstandard" to use an image through the icon support)
1020 const QString stylesheet = [this] {
1021 switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) {
1022 case Settings::ControllerType::ProController:
1023 return QStringLiteral("image: url(:/controller/pro_controller%0)");
1024 case Settings::ControllerType::DualJoyconDetached:
1025 return QStringLiteral("image: url(:/controller/dual_joycon%0)");
1026 case Settings::ControllerType::LeftJoycon:
1027 return QStringLiteral("image: url(:/controller/single_joycon_left_vertical%0)");
1028 case Settings::ControllerType::RightJoycon:
1029 return QStringLiteral("image: url(:/controller/single_joycon_right_vertical%0)");
1030 case Settings::ControllerType::Handheld:
1031 return QStringLiteral("image: url(:/controller/handheld%0)");
1032 default:
1033 return QString{};
1034 }
1035 }();
1036
1037 const QString theme = [] {
1038 if (QIcon::themeName().contains(QStringLiteral("dark"))) {
1039 return QStringLiteral("_dark");
1040 } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
1041 return QStringLiteral("_midnight");
1042 } else {
1043 return QString{};
1044 }
1045 }();
1046 ui->controllerFrame->SetControllerType(
1047 GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()));
1048}
1049
1050void ConfigureInputPlayer::UpdateControllerAvailableButtons() { 809void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
1051 auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); 810 auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
1052 if (debug) { 811 if (debug) {
1053 layout = Settings::ControllerType::ProController; 812 layout = Core::HID::NpadType::ProController;
1054 } 813 }
1055 814
1056 // List of all the widgets that will be hidden by any of the following layouts that need 815 // List of all the widgets that will be hidden by any of the following layouts that need
@@ -1075,15 +834,15 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
1075 834
1076 std::vector<QWidget*> layout_hidden; 835 std::vector<QWidget*> layout_hidden;
1077 switch (layout) { 836 switch (layout) {
1078 case Settings::ControllerType::ProController: 837 case Core::HID::NpadType::ProController:
1079 case Settings::ControllerType::DualJoyconDetached: 838 case Core::HID::NpadType::JoyconDual:
1080 case Settings::ControllerType::Handheld: 839 case Core::HID::NpadType::Handheld:
1081 layout_hidden = { 840 layout_hidden = {
1082 ui->buttonShoulderButtonsSLSR, 841 ui->buttonShoulderButtonsSLSR,
1083 ui->horizontalSpacerShoulderButtonsWidget2, 842 ui->horizontalSpacerShoulderButtonsWidget2,
1084 }; 843 };
1085 break; 844 break;
1086 case Settings::ControllerType::LeftJoycon: 845 case Core::HID::NpadType::JoyconLeft:
1087 layout_hidden = { 846 layout_hidden = {
1088 ui->horizontalSpacerShoulderButtonsWidget2, 847 ui->horizontalSpacerShoulderButtonsWidget2,
1089 ui->buttonShoulderButtonsRight, 848 ui->buttonShoulderButtonsRight,
@@ -1091,7 +850,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
1091 ui->bottomRight, 850 ui->bottomRight,
1092 }; 851 };
1093 break; 852 break;
1094 case Settings::ControllerType::RightJoycon: 853 case Core::HID::NpadType::JoyconRight:
1095 layout_hidden = { 854 layout_hidden = {
1096 ui->horizontalSpacerShoulderButtonsWidget, 855 ui->horizontalSpacerShoulderButtonsWidget,
1097 ui->buttonShoulderButtonsLeft, 856 ui->buttonShoulderButtonsLeft,
@@ -1099,7 +858,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
1099 ui->bottomLeft, 858 ui->bottomLeft,
1100 }; 859 };
1101 break; 860 break;
1102 case Settings::ControllerType::GameCube: 861 case Core::HID::NpadType::GameCube:
1103 layout_hidden = { 862 layout_hidden = {
1104 ui->buttonShoulderButtonsSLSR, 863 ui->buttonShoulderButtonsSLSR,
1105 ui->horizontalSpacerShoulderButtonsWidget2, 864 ui->horizontalSpacerShoulderButtonsWidget2,
@@ -1107,6 +866,8 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
1107 ui->buttonMiscButtonsScreenshotGroup, 866 ui->buttonMiscButtonsScreenshotGroup,
1108 }; 867 };
1109 break; 868 break;
869 default:
870 break;
1110 } 871 }
1111 872
1112 for (auto* widget : layout_hidden) { 873 for (auto* widget : layout_hidden) {
@@ -1117,13 +878,12 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
1117void ConfigureInputPlayer::UpdateControllerEnabledButtons() { 878void ConfigureInputPlayer::UpdateControllerEnabledButtons() {
1118 auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); 879 auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
1119 if (debug) { 880 if (debug) {
1120 layout = Settings::ControllerType::ProController; 881 layout = Core::HID::NpadType::ProController;
1121 } 882 }
1122 883
1123 // List of all the widgets that will be disabled by any of the following layouts that need 884 // List of all the widgets that will be disabled by any of the following layouts that need
1124 // "enabled" after the controller type changes 885 // "enabled" after the controller type changes
1125 const std::array<QWidget*, 4> layout_enable = { 886 const std::array<QWidget*, 3> layout_enable = {
1126 ui->buttonHome,
1127 ui->buttonLStickPressedGroup, 887 ui->buttonLStickPressedGroup,
1128 ui->groupRStickPressed, 888 ui->groupRStickPressed,
1129 ui->buttonShoulderButtonsButtonLGroup, 889 ui->buttonShoulderButtonsButtonLGroup,
@@ -1135,17 +895,13 @@ void ConfigureInputPlayer::UpdateControllerEnabledButtons() {
1135 895
1136 std::vector<QWidget*> layout_disable; 896 std::vector<QWidget*> layout_disable;
1137 switch (layout) { 897 switch (layout) {
1138 case Settings::ControllerType::ProController: 898 case Core::HID::NpadType::ProController:
1139 case Settings::ControllerType::DualJoyconDetached: 899 case Core::HID::NpadType::JoyconDual:
1140 case Settings::ControllerType::Handheld: 900 case Core::HID::NpadType::Handheld:
1141 case Settings::ControllerType::LeftJoycon: 901 case Core::HID::NpadType::JoyconLeft:
1142 case Settings::ControllerType::RightJoycon: 902 case Core::HID::NpadType::JoyconRight:
1143 // TODO(wwylele): enable this when we actually emulate it
1144 layout_disable = {
1145 ui->buttonHome,
1146 };
1147 break; 903 break;
1148 case Settings::ControllerType::GameCube: 904 case Core::HID::NpadType::GameCube:
1149 layout_disable = { 905 layout_disable = {
1150 ui->buttonHome, 906 ui->buttonHome,
1151 ui->buttonLStickPressedGroup, 907 ui->buttonLStickPressedGroup,
@@ -1153,6 +909,8 @@ void ConfigureInputPlayer::UpdateControllerEnabledButtons() {
1153 ui->buttonShoulderButtonsButtonLGroup, 909 ui->buttonShoulderButtonsButtonLGroup,
1154 }; 910 };
1155 break; 911 break;
912 default:
913 break;
1156 } 914 }
1157 915
1158 for (auto* widget : layout_disable) { 916 for (auto* widget : layout_disable) {
@@ -1170,24 +928,24 @@ void ConfigureInputPlayer::UpdateMotionButtons() {
1170 928
1171 // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller. 929 // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller.
1172 switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { 930 switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) {
1173 case Settings::ControllerType::ProController: 931 case Core::HID::NpadType::ProController:
1174 case Settings::ControllerType::LeftJoycon: 932 case Core::HID::NpadType::JoyconLeft:
1175 case Settings::ControllerType::Handheld: 933 case Core::HID::NpadType::Handheld:
1176 // Show "Motion 1" and hide "Motion 2". 934 // Show "Motion 1" and hide "Motion 2".
1177 ui->buttonMotionLeftGroup->show(); 935 ui->buttonMotionLeftGroup->show();
1178 ui->buttonMotionRightGroup->hide(); 936 ui->buttonMotionRightGroup->hide();
1179 break; 937 break;
1180 case Settings::ControllerType::RightJoycon: 938 case Core::HID::NpadType::JoyconRight:
1181 // Show "Motion 2" and hide "Motion 1". 939 // Show "Motion 2" and hide "Motion 1".
1182 ui->buttonMotionLeftGroup->hide(); 940 ui->buttonMotionLeftGroup->hide();
1183 ui->buttonMotionRightGroup->show(); 941 ui->buttonMotionRightGroup->show();
1184 break; 942 break;
1185 case Settings::ControllerType::GameCube: 943 case Core::HID::NpadType::GameCube:
1186 // Hide both "Motion 1/2". 944 // Hide both "Motion 1/2".
1187 ui->buttonMotionLeftGroup->hide(); 945 ui->buttonMotionLeftGroup->hide();
1188 ui->buttonMotionRightGroup->hide(); 946 ui->buttonMotionRightGroup->hide();
1189 break; 947 break;
1190 case Settings::ControllerType::DualJoyconDetached: 948 case Core::HID::NpadType::JoyconDual:
1191 default: 949 default:
1192 // Show both "Motion 1/2". 950 // Show both "Motion 1/2".
1193 ui->buttonMotionLeftGroup->show(); 951 ui->buttonMotionLeftGroup->show();
@@ -1199,15 +957,15 @@ void ConfigureInputPlayer::UpdateMotionButtons() {
1199void ConfigureInputPlayer::UpdateControllerButtonNames() { 957void ConfigureInputPlayer::UpdateControllerButtonNames() {
1200 auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); 958 auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
1201 if (debug) { 959 if (debug) {
1202 layout = Settings::ControllerType::ProController; 960 layout = Core::HID::NpadType::ProController;
1203 } 961 }
1204 962
1205 switch (layout) { 963 switch (layout) {
1206 case Settings::ControllerType::ProController: 964 case Core::HID::NpadType::ProController:
1207 case Settings::ControllerType::DualJoyconDetached: 965 case Core::HID::NpadType::JoyconDual:
1208 case Settings::ControllerType::Handheld: 966 case Core::HID::NpadType::Handheld:
1209 case Settings::ControllerType::LeftJoycon: 967 case Core::HID::NpadType::JoyconLeft:
1210 case Settings::ControllerType::RightJoycon: 968 case Core::HID::NpadType::JoyconRight:
1211 ui->buttonMiscButtonsPlusGroup->setTitle(tr("Plus")); 969 ui->buttonMiscButtonsPlusGroup->setTitle(tr("Plus"));
1212 ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("ZL")); 970 ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("ZL"));
1213 ui->buttonShoulderButtonsZRGroup->setTitle(tr("ZR")); 971 ui->buttonShoulderButtonsZRGroup->setTitle(tr("ZR"));
@@ -1215,7 +973,7 @@ void ConfigureInputPlayer::UpdateControllerButtonNames() {
1215 ui->LStick->setTitle(tr("Left Stick")); 973 ui->LStick->setTitle(tr("Left Stick"));
1216 ui->RStick->setTitle(tr("Right Stick")); 974 ui->RStick->setTitle(tr("Right Stick"));
1217 break; 975 break;
1218 case Settings::ControllerType::GameCube: 976 case Core::HID::NpadType::GameCube:
1219 ui->buttonMiscButtonsPlusGroup->setTitle(tr("Start / Pause")); 977 ui->buttonMiscButtonsPlusGroup->setTitle(tr("Start / Pause"));
1220 ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("L")); 978 ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("L"));
1221 ui->buttonShoulderButtonsZRGroup->setTitle(tr("R")); 979 ui->buttonShoulderButtonsZRGroup->setTitle(tr("R"));
@@ -1223,6 +981,8 @@ void ConfigureInputPlayer::UpdateControllerButtonNames() {
1223 ui->LStick->setTitle(tr("Control Stick")); 981 ui->LStick->setTitle(tr("Control Stick"));
1224 ui->RStick->setTitle(tr("C-Stick")); 982 ui->RStick->setTitle(tr("C-Stick"));
1225 break; 983 break;
984 default:
985 break;
1226 } 986 }
1227} 987}
1228 988
@@ -1231,26 +991,93 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
1231 return; 991 return;
1232 } 992 }
1233 993
994 for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
995 const auto* const button = button_map[button_id];
996 if (button == nullptr) {
997 continue;
998 }
999 emulated_controller->SetButtonParam(button_id, {});
1000 }
1001
1002 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
1003 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
1004 const auto* const analog_button = analog_map_buttons[analog_id][sub_button_id];
1005 if (analog_button == nullptr) {
1006 continue;
1007 }
1008 emulated_controller->SetStickParam(analog_id, {});
1009 }
1010 }
1011
1012 for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
1013 const auto* const motion_button = motion_map[motion_id];
1014 if (motion_button == nullptr) {
1015 continue;
1016 }
1017 emulated_controller->SetMotionParam(motion_id, {});
1018 }
1019
1020 // Reset keyboard bindings
1234 if (ui->comboDevices->currentIndex() == 1) { 1021 if (ui->comboDevices->currentIndex() == 1) {
1235 // Reset keyboard bindings
1236 for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { 1022 for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
1237 buttons_param[button_id] = Common::ParamPackage{ 1023 emulated_controller->SetButtonParam(
1238 InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; 1024 button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
1025 Config::default_buttons[button_id])});
1239 } 1026 }
1240 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { 1027 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
1028 Common::ParamPackage analog_param{};
1241 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { 1029 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
1242 Common::ParamPackage params{InputCommon::GenerateKeyboardParam( 1030 Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
1243 Config::default_analogs[analog_id][sub_button_id])}; 1031 Config::default_analogs[analog_id][sub_button_id])};
1244 SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); 1032 SetAnalogParam(params, analog_param, analog_sub_buttons[sub_button_id]);
1245 } 1033 }
1246 1034
1247 analogs_param[analog_id].Set("modifier", InputCommon::GenerateKeyboardParam( 1035 analog_param.Set("modifier", InputCommon::GenerateKeyboardParam(
1248 Config::default_stick_mod[analog_id])); 1036 Config::default_stick_mod[analog_id]));
1037 emulated_controller->SetStickParam(analog_id, analog_param);
1038 }
1039
1040 for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
1041 emulated_controller->SetMotionParam(
1042 motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
1043 Config::default_motions[motion_id])});
1044 }
1045
1046 UpdateUI();
1047 return;
1048 }
1049
1050 // Reset keyboard with mouse bindings
1051 if (ui->comboDevices->currentIndex() == 2) {
1052 for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
1053 emulated_controller->SetButtonParam(
1054 button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
1055 Config::default_buttons[button_id])});
1056 }
1057
1058 Common::ParamPackage left_analog_param{};
1059 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
1060 Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
1061 Config::default_analogs[Settings::NativeAnalog::LStick][sub_button_id])};
1062 SetAnalogParam(params, left_analog_param, analog_sub_buttons[sub_button_id]);
1249 } 1063 }
1064 left_analog_param.Set("modifier",
1065 InputCommon::GenerateKeyboardParam(
1066 Config::default_stick_mod[Settings::NativeAnalog::LStick]));
1067 emulated_controller->SetStickParam(Settings::NativeAnalog::LStick, left_analog_param);
1068
1069 Common::ParamPackage right_analog_param{};
1070 right_analog_param.Set("engine", "mouse");
1071 right_analog_param.Set("port", 0);
1072 right_analog_param.Set("axis_x", 0);
1073 right_analog_param.Set("axis_y", 1);
1074 emulated_controller->SetStickParam(Settings::NativeAnalog::RStick,
1075 std::move(right_analog_param));
1250 1076
1251 for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { 1077 for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
1252 motions_param[motion_id] = Common::ParamPackage{ 1078 emulated_controller->SetMotionParam(
1253 InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])}; 1079 motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam(
1080 Config::default_motions[motion_id])});
1254 } 1081 }
1255 1082
1256 UpdateUI(); 1083 UpdateUI();
@@ -1262,14 +1089,17 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
1262 auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); 1089 auto button_mapping = input_subsystem->GetButtonMappingForDevice(device);
1263 auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); 1090 auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device);
1264 auto motion_mapping = input_subsystem->GetMotionMappingForDevice(device); 1091 auto motion_mapping = input_subsystem->GetMotionMappingForDevice(device);
1265 for (std::size_t i = 0; i < buttons_param.size(); ++i) { 1092 for (std::size_t i = 0; i < button_mapping.size(); ++i) {
1266 buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; 1093 emulated_controller->SetButtonParam(
1094 i, button_mapping[static_cast<Settings::NativeButton::Values>(i)]);
1267 } 1095 }
1268 for (std::size_t i = 0; i < analogs_param.size(); ++i) { 1096 for (std::size_t i = 0; i < analog_mapping.size(); ++i) {
1269 analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; 1097 emulated_controller->SetStickParam(
1098 i, analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]);
1270 } 1099 }
1271 for (std::size_t i = 0; i < motions_param.size(); ++i) { 1100 for (std::size_t i = 0; i < motion_mapping.size(); ++i) {
1272 motions_param[i] = motion_mapping[static_cast<Settings::NativeMotion::Values>(i)]; 1101 emulated_controller->SetMotionParam(
1102 i, motion_mapping[static_cast<Settings::NativeMotion::Values>(i)]);
1273 } 1103 }
1274 1104
1275 UpdateUI(); 1105 UpdateUI();
@@ -1278,7 +1108,7 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
1278void ConfigureInputPlayer::HandleClick( 1108void ConfigureInputPlayer::HandleClick(
1279 QPushButton* button, std::size_t button_id, 1109 QPushButton* button, std::size_t button_id,
1280 std::function<void(const Common::ParamPackage&)> new_input_setter, 1110 std::function<void(const Common::ParamPackage&)> new_input_setter,
1281 InputCommon::Polling::DeviceType type) { 1111 InputCommon::Polling::InputType type) {
1282 if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) { 1112 if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {
1283 button->setText(tr("Shake!")); 1113 button->setText(tr("Shake!"));
1284 } else { 1114 } else {
@@ -1286,25 +1116,16 @@ void ConfigureInputPlayer::HandleClick(
1286 } 1116 }
1287 button->setFocus(); 1117 button->setFocus();
1288 1118
1289 // The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a
1290 // controller, then they don't want keyboard/mouse input
1291 want_keyboard_mouse = ui->comboDevices->currentIndex() < 2;
1292
1293 input_setter = new_input_setter; 1119 input_setter = new_input_setter;
1294 1120
1295 device_pollers = input_subsystem->GetPollers(type); 1121 input_subsystem->BeginMapping(type);
1296
1297 for (auto& poller : device_pollers) {
1298 poller->Start();
1299 }
1300 1122
1301 QWidget::grabMouse(); 1123 QWidget::grabMouse();
1302 QWidget::grabKeyboard(); 1124 QWidget::grabKeyboard();
1303 1125
1304 1126 if (type == InputCommon::Polling::InputType::Button) {
1305 if (type == InputCommon::Polling::DeviceType::Button) {
1306 ui->controllerFrame->BeginMappingButton(button_id); 1127 ui->controllerFrame->BeginMappingButton(button_id);
1307 } else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) { 1128 } else if (type == InputCommon::Polling::InputType::Stick) {
1308 ui->controllerFrame->BeginMappingAnalog(button_id); 1129 ui->controllerFrame->BeginMappingAnalog(button_id);
1309 } 1130 }
1310 1131
@@ -1315,14 +1136,11 @@ void ConfigureInputPlayer::HandleClick(
1315void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { 1136void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) {
1316 timeout_timer->stop(); 1137 timeout_timer->stop();
1317 poll_timer->stop(); 1138 poll_timer->stop();
1318 for (auto& poller : device_pollers) { 1139 input_subsystem->StopMapping();
1319 poller->Stop();
1320 }
1321 1140
1322 QWidget::releaseMouse(); 1141 QWidget::releaseMouse();
1323 QWidget::releaseKeyboard(); 1142 QWidget::releaseKeyboard();
1324 1143
1325
1326 if (!abort) { 1144 if (!abort) {
1327 (*input_setter)(params); 1145 (*input_setter)(params);
1328 } 1146 }
@@ -1340,13 +1158,14 @@ bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params)
1340 } 1158 }
1341 1159
1342 // Keyboard/Mouse 1160 // Keyboard/Mouse
1343 if (ui->comboDevices->currentIndex() == 1) { 1161 if (ui->comboDevices->currentIndex() == 2) {
1344 return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse"; 1162 return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse";
1345 } 1163 }
1346 1164
1347 const auto current_input_device = input_devices[ui->comboDevices->currentIndex()]; 1165 const auto current_input_device = input_devices[ui->comboDevices->currentIndex()];
1348 return params.Get("engine", "") == current_input_device.Get("class", "") && 1166 return params.Get("engine", "") == current_input_device.Get("engine", "") &&
1349 params.Get("guid", "") == current_input_device.Get("guid", "") && 1167 (params.Get("guid", "") == current_input_device.Get("guid", "") ||
1168 params.Get("guid", "") == current_input_device.Get("guid2", "")) &&
1350 params.Get("port", "") == current_input_device.Get("port", ""); 1169 params.Get("port", "") == current_input_device.Get("port", "");
1351} 1170}
1352 1171
@@ -1355,25 +1174,18 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
1355 return; 1174 return;
1356 } 1175 }
1357 1176
1358 //const auto button = GRenderWindow::QtButtonToMouseButton(event->button()); 1177 const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
1178 input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button);
1359} 1179}
1360 1180
1361void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { 1181void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
1182 event->ignore();
1362 if (!input_setter || !event) { 1183 if (!input_setter || !event) {
1363 return; 1184 return;
1364 } 1185 }
1365
1366 if (event->key() != Qt::Key_Escape) { 1186 if (event->key() != Qt::Key_Escape) {
1367 if (want_keyboard_mouse) { 1187 input_subsystem->GetKeyboard()->PressKey(event->key());
1368 SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())},
1369 false);
1370 } else {
1371 // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling
1372 return;
1373 }
1374 } 1188 }
1375
1376 SetPollingResult({}, true);
1377} 1189}
1378 1190
1379void ConfigureInputPlayer::CreateProfile() { 1191void ConfigureInputPlayer::CreateProfile() {
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index 39b44b8a5..02d6920f1 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -38,14 +38,22 @@ class InputSubsystem;
38} 38}
39 39
40namespace InputCommon::Polling { 40namespace InputCommon::Polling {
41class DevicePoller; 41enum class InputType;
42enum class DeviceType;
43} // namespace InputCommon::Polling 42} // namespace InputCommon::Polling
44 43
45namespace Ui { 44namespace Ui {
46class ConfigureInputPlayer; 45class ConfigureInputPlayer;
47} 46}
48 47
48namespace Core {
49class System;
50}
51
52namespace Core::HID {
53class EmulatedController;
54enum class NpadType : u8;
55} // namespace Core::HID
56
49class ConfigureInputPlayer : public QWidget { 57class ConfigureInputPlayer : public QWidget {
50 Q_OBJECT 58 Q_OBJECT
51 59
@@ -59,18 +67,6 @@ public:
59 /// Save all button configurations to settings file. 67 /// Save all button configurations to settings file.
60 void ApplyConfiguration(); 68 void ApplyConfiguration();
61 69
62 /**
63 * Attempts to connect the currently selected controller in the HID backend.
64 * This function will not do anything if it is not connected in the frontend.
65 */
66 void TryConnectSelectedController();
67
68 /**
69 * Attempts to disconnect the currently selected controller in the HID backend.
70 * This function will not do anything if the configuration has not changed.
71 */
72 void TryDisconnectSelectedController();
73
74 /// Set the connection state checkbox (used to sync state). 70 /// Set the connection state checkbox (used to sync state).
75 void ConnectPlayer(bool connected); 71 void ConnectPlayer(bool connected);
76 72
@@ -104,6 +100,10 @@ protected:
104 void showEvent(QShowEvent* event) override; 100 void showEvent(QShowEvent* event) override;
105 101
106private: 102private:
103 QString ButtonToText(const Common::ParamPackage& param);
104
105 QString AnalogToText(const Common::ParamPackage& param, const std::string& dir);
106
107 void changeEvent(QEvent* event) override; 107 void changeEvent(QEvent* event) override;
108 void RetranslateUI(); 108 void RetranslateUI();
109 109
@@ -113,7 +113,7 @@ private:
113 /// Called when the button was pressed. 113 /// Called when the button was pressed.
114 void HandleClick(QPushButton* button, std::size_t button_id, 114 void HandleClick(QPushButton* button, std::size_t button_id,
115 std::function<void(const Common::ParamPackage&)> new_input_setter, 115 std::function<void(const Common::ParamPackage&)> new_input_setter,
116 InputCommon::Polling::DeviceType type); 116 InputCommon::Polling::InputType type);
117 117
118 /// Finish polling and configure input using the input_setter. 118 /// Finish polling and configure input using the input_setter.
119 void SetPollingResult(const Common::ParamPackage& params, bool abort); 119 void SetPollingResult(const Common::ParamPackage& params, bool abort);
@@ -134,17 +134,14 @@ private:
134 void SetConnectableControllers(); 134 void SetConnectableControllers();
135 135
136 /// Gets the Controller Type for a given controller combobox index. 136 /// Gets the Controller Type for a given controller combobox index.
137 Settings::ControllerType GetControllerTypeFromIndex(int index) const; 137 Core::HID::NpadType GetControllerTypeFromIndex(int index) const;
138 138
139 /// Gets the controller combobox index for a given Controller Type. 139 /// Gets the controller combobox index for a given Controller Type.
140 int GetIndexFromControllerType(Settings::ControllerType type) const; 140 int GetIndexFromControllerType(Core::HID::NpadType type) const;
141 141
142 /// Update the available input devices. 142 /// Update the available input devices.
143 void UpdateInputDevices(); 143 void UpdateInputDevices();
144 144
145 /// Update the current controller icon.
146 void UpdateControllerIcon();
147
148 /// Hides and disables controller settings based on the current controller type. 145 /// Hides and disables controller settings based on the current controller type.
149 void UpdateControllerAvailableButtons(); 146 void UpdateControllerAvailableButtons();
150 147
@@ -185,7 +182,7 @@ private:
185 std::unique_ptr<QTimer> poll_timer; 182 std::unique_ptr<QTimer> poll_timer;
186 183
187 /// Stores a pair of "Connected Controllers" combobox index and Controller Type enum. 184 /// Stores a pair of "Connected Controllers" combobox index and Controller Type enum.
188 std::vector<std::pair<int, Settings::ControllerType>> index_controller_type_pairs; 185 std::vector<std::pair<int, Core::HID::NpadType>> index_controller_type_pairs;
189 186
190 static constexpr int PLAYER_COUNT = 8; 187 static constexpr int PLAYER_COUNT = 8;
191 std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox; 188 std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox;
@@ -193,9 +190,7 @@ private:
193 /// This will be the the setting function when an input is awaiting configuration. 190 /// This will be the the setting function when an input is awaiting configuration.
194 std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; 191 std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
195 192
196 std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param; 193 Core::HID::EmulatedController* emulated_controller;
197 std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param;
198 std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions> motions_param;
199 194
200 static constexpr int ANALOG_SUB_BUTTONS_NUM = 4; 195 static constexpr int ANALOG_SUB_BUTTONS_NUM = 4;
201 196
@@ -221,15 +216,9 @@ private:
221 216
222 static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons; 217 static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons;
223 218
224 std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
225
226 /// A flag to indicate that the "Map Analog Stick" pop-up has been shown and accepted once. 219 /// A flag to indicate that the "Map Analog Stick" pop-up has been shown and accepted once.
227 bool map_analog_stick_accepted{}; 220 bool map_analog_stick_accepted{};
228 221
229 /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false,
230 /// keyboard events are ignored.
231 bool want_keyboard_mouse{};
232
233 /// List of physical devices users can map with. If a SDL backed device is selected, then you 222 /// List of physical devices users can map with. If a SDL backed device is selected, then you
234 /// can use this device to get a default mapping. 223 /// can use this device to get a default mapping.
235 std::vector<Common::ParamPackage> input_devices; 224 std::vector<Common::ParamPackage> input_devices;
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
index e7433912b..14ca02fd8 100644
--- a/src/yuzu/configuration/configure_input_player.ui
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -148,16 +148,6 @@
148 <height>21</height> 148 <height>21</height>
149 </size> 149 </size>
150 </property> 150 </property>
151 <item>
152 <property name="text">
153 <string>Any</string>
154 </property>
155 </item>
156 <item>
157 <property name="text">
158 <string>Keyboard/Mouse</string>
159 </property>
160 </item>
161 </widget> 151 </widget>
162 </item> 152 </item>
163 <item> 153 <item>
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index f31f86339..03d29f194 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -6,10 +6,11 @@
6#include <QMenu> 6#include <QMenu>
7#include <QPainter> 7#include <QPainter>
8#include <QTimer> 8#include <QTimer>
9#include "core/core.h"
9#include "yuzu/configuration/configure_input_player_widget.h" 10#include "yuzu/configuration/configure_input_player_widget.h"
10 11
11PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) { 12PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) {
12 UpdateColors(); 13 is_controller_set = false;
13 QTimer* timer = new QTimer(this); 14 QTimer* timer = new QTimer(this);
14 connect(timer, &QTimer::timeout, this, QOverload<>::of(&PlayerControlPreview::UpdateInput)); 15 connect(timer, &QTimer::timeout, this, QOverload<>::of(&PlayerControlPreview::UpdateInput));
15 16
@@ -17,38 +18,11 @@ PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) {
17 timer->start(16); 18 timer->start(16);
18} 19}
19 20
20PlayerControlPreview::~PlayerControlPreview() = default; 21PlayerControlPreview::~PlayerControlPreview() {
21 22 if (is_controller_set) {
22void PlayerControlPreview::SetPlayerInput(std::size_t index, const ButtonParam& buttons_param, 23 controller->DeleteCallback(callback_key);
23 const AnalogParam& analogs_param) { 24 }
24 player_index = index; 25};
25 Settings::ButtonsRaw buttonss;
26 Settings::AnalogsRaw analogs;
27 std::transform(buttons_param.begin(), buttons_param.end(), buttonss.begin(),
28 [](const Common::ParamPackage& param) { return param.Serialize(); });
29 std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(),
30 [](const Common::ParamPackage& param) { return param.Serialize(); });
31
32 std::transform(buttonss.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
33 buttonss.begin() + Settings::NativeButton::BUTTON_NS_END, buttons.begin(),
34 Input::CreateDevice<Input::ButtonDevice>);
35 std::transform(analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
36 analogs.begin() + Settings::NativeAnalog::STICK_HID_END, sticks.begin(),
37 Input::CreateDevice<Input::AnalogDevice>);
38 UpdateColors();
39}
40void PlayerControlPreview::SetPlayerInputRaw(std::size_t index,
41 const Settings::ButtonsRaw& buttons_,
42 Settings::AnalogsRaw analogs_) {
43 player_index = index;
44 std::transform(buttons_.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
45 buttons_.begin() + Settings::NativeButton::BUTTON_NS_END, buttons.begin(),
46 Input::CreateDevice<Input::ButtonDevice>);
47 std::transform(analogs_.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
48 analogs_.begin() + Settings::NativeAnalog::STICK_HID_END, sticks.begin(),
49 Input::CreateDevice<Input::AnalogDevice>);
50 UpdateColors();
51}
52 26
53PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size_t index, 27PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size_t index,
54 bool player_on) { 28 bool player_on) {
@@ -78,20 +52,16 @@ PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size
78 } 52 }
79} 53}
80 54
81void PlayerControlPreview::SetConnectedStatus(bool checked) { 55void PlayerControlPreview::SetController(Core::HID::EmulatedController* controller_) {
82 LedPattern led_pattern = GetColorPattern(player_index, checked); 56 if (is_controller_set) {
83 57 controller->DeleteCallback(callback_key);
84 led_color[0] = led_pattern.position1 ? colors.led_on : colors.led_off; 58 }
85 led_color[1] = led_pattern.position2 ? colors.led_on : colors.led_off; 59 is_controller_set = true;
86 led_color[2] = led_pattern.position3 ? colors.led_on : colors.led_off; 60 controller = controller_;
87 led_color[3] = led_pattern.position4 ? colors.led_on : colors.led_off; 61 Core::HID::ControllerUpdateCallback engine_callback{
88 is_enabled = checked; 62 [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }};
89 ResetInputs(); 63 callback_key = controller->SetCallback(engine_callback);
90} 64 ControllerUpdate(Core::HID::ControllerTriggerType::All);
91
92void PlayerControlPreview::SetControllerType(const Settings::ControllerType type) {
93 controller_type = type;
94 UpdateColors();
95} 65}
96 66
97void PlayerControlPreview::BeginMappingButton(std::size_t index) { 67void PlayerControlPreview::BeginMappingButton(std::size_t index) {
@@ -162,79 +132,99 @@ void PlayerControlPreview::UpdateColors() {
162} 132}
163 133
164void PlayerControlPreview::ResetInputs() { 134void PlayerControlPreview::ResetInputs() {
165 for (std::size_t index = 0; index < button_values.size(); ++index) { 135 button_values.fill({
166 button_values[index] = false; 136 .value = false,
167 } 137 });
168 138 stick_values.fill({
169 for (std::size_t index = 0; index < axis_values.size(); ++index) { 139 .x = {.value = 0, .properties = {0, 1, 0}},
170 axis_values[index].properties = {0, 1, 0}; 140 .y = {.value = 0, .properties = {0, 1, 0}},
171 axis_values[index].value = {0, 0}; 141 });
172 axis_values[index].raw_value = {0, 0}; 142 trigger_values.fill({
173 } 143 .analog = {.value = 0, .properties = {0, 1, 0}},
144 .pressed = false,
145 });
174 update(); 146 update();
175} 147}
176 148
177void PlayerControlPreview::UpdateInput() { 149void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType type) {
178 if (!is_enabled && !mapping_active && !Settings::values.tas_enable) { 150 if (type == Core::HID::ControllerTriggerType::All) {
151 ControllerUpdate(Core::HID::ControllerTriggerType::Color);
152 ControllerUpdate(Core::HID::ControllerTriggerType::Type);
153 ControllerUpdate(Core::HID::ControllerTriggerType::Connected);
154 ControllerUpdate(Core::HID::ControllerTriggerType::Button);
155 ControllerUpdate(Core::HID::ControllerTriggerType::Stick);
156 ControllerUpdate(Core::HID::ControllerTriggerType::Trigger);
157 ControllerUpdate(Core::HID::ControllerTriggerType::Battery);
179 return; 158 return;
180 } 159 }
181 bool input_changed = false; 160
182 const auto& button_state = buttons; 161 switch (type) {
183 for (std::size_t index = 0; index < button_values.size(); ++index) { 162 case Core::HID::ControllerTriggerType::Connected:
184 bool value = false; 163 case Core::HID::ControllerTriggerType::Disconnected:
185 if (index < Settings::NativeButton::BUTTON_NS_END) { 164 is_connected = controller->IsConnected();
186 value = button_state[index]->GetStatus(); 165 needs_redraw = true;
187 } 166 break;
188 bool blink = mapping_active && index == button_mapping_index; 167 case Core::HID::ControllerTriggerType::Type:
189 if (analog_mapping_index == Settings::NativeAnalog::NUM_STICKS_HID) { 168 controller_type = controller->GetNpadType();
190 blink &= blink_counter > 25; 169 needs_redraw = true;
191 } 170 break;
192 if (button_values[index] != value || blink) { 171 case Core::HID::ControllerTriggerType::Color:
193 input_changed = true; 172 UpdateColors();
194 } 173 needs_redraw = true;
195 button_values[index] = value || blink; 174 break;
175 case Core::HID::ControllerTriggerType::Button:
176 button_values = controller->GetButtonsValues();
177 needs_redraw = true;
178 break;
179 case Core::HID::ControllerTriggerType::Stick:
180 using namespace Settings::NativeAnalog;
181 stick_values = controller->GetSticksValues();
182 // Y axis is inverted
183 stick_values[LStick].y.value = -stick_values[LStick].y.value;
184 stick_values[LStick].y.raw_value = -stick_values[LStick].y.raw_value;
185 stick_values[RStick].y.value = -stick_values[RStick].y.value;
186 stick_values[RStick].y.raw_value = -stick_values[RStick].y.raw_value;
187 needs_redraw = true;
188 break;
189 case Core::HID::ControllerTriggerType::Trigger:
190 trigger_values = controller->GetTriggersValues();
191 needs_redraw = true;
192 break;
193 case Core::HID::ControllerTriggerType::Battery:
194 battery_values = controller->GetBatteryValues();
195 needs_redraw = true;
196 break;
197 default:
198 break;
196 } 199 }
200}
197 201
198 const auto& analog_state = sticks; 202void PlayerControlPreview::UpdateInput() {
199 for (std::size_t index = 0; index < axis_values.size(); ++index) { 203 if (mapping_active) {
200 const auto [stick_x_f, stick_y_f] = analog_state[index]->GetStatus();
201 const auto [stick_x_rf, stick_y_rf] = analog_state[index]->GetRawStatus();
202 204
203 if (static_cast<int>(stick_x_rf * 45) != 205 for (std::size_t index = 0; index < button_values.size(); ++index) {
204 static_cast<int>(axis_values[index].raw_value.x() * 45) || 206 bool blink = index == button_mapping_index;
205 static_cast<int>(-stick_y_rf * 45) != 207 if (analog_mapping_index == Settings::NativeAnalog::NumAnalogs) {
206 static_cast<int>(axis_values[index].raw_value.y() * 45)) { 208 blink &= blink_counter > 25;
207 input_changed = true; 209 }
210 if (button_values[index].value != blink) {
211 needs_redraw = true;
212 }
213 button_values[index].value = blink;
208 } 214 }
209 215
210 axis_values[index].properties = analog_state[index]->GetAnalogProperties(); 216 for (std::size_t index = 0; index < stick_values.size(); ++index) {
211 axis_values[index].value = QPointF(stick_x_f, -stick_y_f); 217 const bool blink_analog = index == analog_mapping_index;
212 axis_values[index].raw_value = QPointF(stick_x_rf, -stick_y_rf); 218 if (blink_analog) {
213 219 needs_redraw = true;
214 const bool blink_analog = mapping_active && index == analog_mapping_index; 220 stick_values[index].x.value = blink_counter < 25 ? -blink_counter / 25.0f : 0;
215 if (blink_analog) { 221 stick_values[index].y.value =
216 input_changed = true; 222 blink_counter > 25 ? -(blink_counter - 25) / 25.0f : 0;
217 axis_values[index].value = 223 }
218 QPointF(blink_counter < 25 ? -blink_counter / 25.0f : 0,
219 blink_counter > 25 ? -(blink_counter - 25) / 25.0f : 0);
220 } 224 }
221 } 225 }
222 226 if (needs_redraw) {
223 if (input_changed) {
224 update(); 227 update();
225 if (controller_callback.input != nullptr) {
226 ControllerInput input{
227 .axis_values = {std::pair<float, float>{
228 axis_values[Settings::NativeAnalog::LStick].value.x(),
229 axis_values[Settings::NativeAnalog::LStick].value.y()},
230 std::pair<float, float>{
231 axis_values[Settings::NativeAnalog::RStick].value.x(),
232 axis_values[Settings::NativeAnalog::RStick].value.y()}},
233 .button_values = button_values,
234 .changed = true,
235 };
236 controller_callback.input(std::move(input));
237 }
238 } 228 }
239 229
240 if (mapping_active) { 230 if (mapping_active) {
@@ -242,10 +232,6 @@ void PlayerControlPreview::UpdateInput() {
242 } 232 }
243} 233}
244 234
245void PlayerControlPreview::SetCallBack(ControllerCallback callback_) {
246 controller_callback = std::move(callback_);
247}
248
249void PlayerControlPreview::paintEvent(QPaintEvent* event) { 235void PlayerControlPreview::paintEvent(QPaintEvent* event) {
250 QFrame::paintEvent(event); 236 QFrame::paintEvent(event);
251 QPainter p(this); 237 QPainter p(this);
@@ -253,22 +239,22 @@ void PlayerControlPreview::paintEvent(QPaintEvent* event) {
253 const QPointF center = rect().center(); 239 const QPointF center = rect().center();
254 240
255 switch (controller_type) { 241 switch (controller_type) {
256 case Settings::ControllerType::Handheld: 242 case Core::HID::NpadType::Handheld:
257 DrawHandheldController(p, center); 243 DrawHandheldController(p, center);
258 break; 244 break;
259 case Settings::ControllerType::DualJoyconDetached: 245 case Core::HID::NpadType::JoyconDual:
260 DrawDualController(p, center); 246 DrawDualController(p, center);
261 break; 247 break;
262 case Settings::ControllerType::LeftJoycon: 248 case Core::HID::NpadType::JoyconLeft:
263 DrawLeftController(p, center); 249 DrawLeftController(p, center);
264 break; 250 break;
265 case Settings::ControllerType::RightJoycon: 251 case Core::HID::NpadType::JoyconRight:
266 DrawRightController(p, center); 252 DrawRightController(p, center);
267 break; 253 break;
268 case Settings::ControllerType::GameCube: 254 case Core::HID::NpadType::GameCube:
269 DrawGCController(p, center); 255 DrawGCController(p, center);
270 break; 256 break;
271 case Settings::ControllerType::ProController: 257 case Core::HID::NpadType::ProController:
272 default: 258 default:
273 DrawProController(p, center); 259 DrawProController(p, center);
274 break; 260 break;
@@ -281,7 +267,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
281 267
282 // Sideview left joystick 268 // Sideview left joystick
283 DrawJoystickSideview(p, center + QPoint(142, -69), 269 DrawJoystickSideview(p, center + QPoint(142, -69),
284 -axis_values[Settings::NativeAnalog::LStick].value.y(), 1.15f, 270 -stick_values[Settings::NativeAnalog::LStick].y.value, 1.15f,
285 button_values[LStick]); 271 button_values[LStick]);
286 272
287 // Topview D-pad buttons 273 // Topview D-pad buttons
@@ -292,7 +278,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
292 278
293 // Topview left joystick 279 // Topview left joystick
294 DrawJoystickSideview(p, center + QPointF(-140.5f, -28), 280 DrawJoystickSideview(p, center + QPointF(-140.5f, -28),
295 -axis_values[Settings::NativeAnalog::LStick].value.x() + 15.0f, 1.15f, 281 -stick_values[Settings::NativeAnalog::LStick].x.value + 15.0f, 1.15f,
296 button_values[LStick]); 282 button_values[LStick]);
297 283
298 // Topview minus button 284 // Topview minus button
@@ -334,8 +320,10 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
334 { 320 {
335 // Draw joysticks 321 // Draw joysticks
336 using namespace Settings::NativeAnalog; 322 using namespace Settings::NativeAnalog;
337 DrawJoystick(p, center + QPointF(9, -69) + (axis_values[LStick].value * 8), 1.8f, 323 DrawJoystick(p,
338 button_values[Settings::NativeButton::LStick]); 324 center + QPointF(9, -69) +
325 (QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value) * 8),
326 1.8f, button_values[Settings::NativeButton::LStick]);
339 DrawRawJoystick(p, center + QPointF(-140, 90), QPointF(0, 0)); 327 DrawRawJoystick(p, center + QPointF(-140, 90), QPointF(0, 0));
340 } 328 }
341 329
@@ -384,6 +372,9 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
384 p.setPen(colors.font2); 372 p.setPen(colors.font2);
385 p.setBrush(colors.font2); 373 p.setBrush(colors.font2);
386 DrawCircle(p, center + QPoint(26, 71), 5); 374 DrawCircle(p, center + QPoint(26, 71), 5);
375
376 // Draw battery
377 DrawBattery(p, center + QPoint(-170, -140), battery_values[0]);
387} 378}
388 379
389void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) { 380void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) {
@@ -392,20 +383,22 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
392 383
393 // Sideview right joystick 384 // Sideview right joystick
394 DrawJoystickSideview(p, center + QPoint(173 - 315, 11), 385 DrawJoystickSideview(p, center + QPoint(173 - 315, 11),
395 axis_values[Settings::NativeAnalog::RStick].value.y() + 10.0f, 1.15f, 386 stick_values[Settings::NativeAnalog::RStick].y.value + 10.0f, 1.15f,
396 button_values[Settings::NativeButton::RStick]); 387 button_values[Settings::NativeButton::RStick]);
397 388
389 // Topview right joystick
390 DrawJoystickSideview(p, center + QPointF(140, -28),
391 -stick_values[Settings::NativeAnalog::RStick].x.value + 15.0f, 1.15f,
392 button_values[RStick]);
393
398 // Topview face buttons 394 // Topview face buttons
399 p.setPen(colors.outline); 395 p.setPen(colors.outline);
400 button_color = colors.button; 396 button_color = colors.button;
401 DrawRoundButton(p, center + QPoint(163, -21), button_values[A], 11, 5, Direction::Up); 397 DrawRoundButton(p, center + QPoint(163, -21), button_values[A], 11, 5, Direction::Up);
398 DrawRoundButton(p, center + QPoint(140, -21), button_values[B], 11, 5, Direction::Up);
399 DrawRoundButton(p, center + QPoint(140, -21), button_values[X], 11, 5, Direction::Up);
402 DrawRoundButton(p, center + QPoint(117, -21), button_values[Y], 11, 5, Direction::Up); 400 DrawRoundButton(p, center + QPoint(117, -21), button_values[Y], 11, 5, Direction::Up);
403 401
404 // Topview right joystick
405 DrawJoystickSideview(p, center + QPointF(140, -28),
406 -axis_values[Settings::NativeAnalog::RStick].value.x() + 15.0f, 1.15f,
407 button_values[RStick]);
408
409 // Topview plus button 402 // Topview plus button
410 p.setPen(colors.outline); 403 p.setPen(colors.outline);
411 button_color = colors.button; 404 button_color = colors.button;
@@ -448,8 +441,10 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
448 { 441 {
449 // Draw joysticks 442 // Draw joysticks
450 using namespace Settings::NativeAnalog; 443 using namespace Settings::NativeAnalog;
451 DrawJoystick(p, center + QPointF(-9, 11) + (axis_values[RStick].value * 8), 1.8f, 444 DrawJoystick(p,
452 button_values[Settings::NativeButton::RStick]); 445 center + QPointF(-9, 11) +
446 (QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value) * 8),
447 1.8f, button_values[Settings::NativeButton::RStick]);
453 DrawRawJoystick(p, QPointF(0, 0), center + QPointF(140, 90)); 448 DrawRawJoystick(p, QPointF(0, 0), center + QPointF(140, 90));
454 } 449 }
455 450
@@ -503,6 +498,9 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
503 p.setPen(colors.transparent); 498 p.setPen(colors.transparent);
504 p.setBrush(colors.font2); 499 p.setBrush(colors.font2);
505 DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5); 500 DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5);
501
502 // Draw battery
503 DrawBattery(p, center + QPoint(110, -140), battery_values[1]);
506} 504}
507 505
508void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) { 506void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) {
@@ -512,17 +510,19 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
512 // Left/Right trigger 510 // Left/Right trigger
513 DrawDualTriggers(p, center, button_values[L], button_values[R]); 511 DrawDualTriggers(p, center, button_values[L], button_values[R]);
514 512
513 // Topview right joystick
514 DrawJoystickSideview(p, center + QPointF(180, -78),
515 -stick_values[Settings::NativeAnalog::RStick].x.value + 15.0f, 1,
516 button_values[RStick]);
517
515 // Topview face buttons 518 // Topview face buttons
516 p.setPen(colors.outline); 519 p.setPen(colors.outline);
517 button_color = colors.button; 520 button_color = colors.button;
518 DrawRoundButton(p, center + QPoint(200, -71), button_values[A], 10, 5, Direction::Up); 521 DrawRoundButton(p, center + QPoint(200, -71), button_values[A], 10, 5, Direction::Up);
522 DrawRoundButton(p, center + QPoint(180, -71), button_values[B], 10, 5, Direction::Up);
523 DrawRoundButton(p, center + QPoint(180, -71), button_values[X], 10, 5, Direction::Up);
519 DrawRoundButton(p, center + QPoint(160, -71), button_values[Y], 10, 5, Direction::Up); 524 DrawRoundButton(p, center + QPoint(160, -71), button_values[Y], 10, 5, Direction::Up);
520 525
521 // Topview right joystick
522 DrawJoystickSideview(p, center + QPointF(180, -78),
523 -axis_values[Settings::NativeAnalog::RStick].value.x() + 15.0f, 1,
524 button_values[RStick]);
525
526 // Topview plus button 526 // Topview plus button
527 p.setPen(colors.outline); 527 p.setPen(colors.outline);
528 button_color = colors.button; 528 button_color = colors.button;
@@ -538,7 +538,7 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
538 538
539 // Topview left joystick 539 // Topview left joystick
540 DrawJoystickSideview(p, center + QPointF(-180.5f, -78), 540 DrawJoystickSideview(p, center + QPointF(-180.5f, -78),
541 -axis_values[Settings::NativeAnalog::LStick].value.x() + 15.0f, 1, 541 -stick_values[Settings::NativeAnalog::LStick].x.value + 15.0f, 1,
542 button_values[LStick]); 542 button_values[LStick]);
543 543
544 // Topview minus button 544 // Topview minus button
@@ -557,13 +557,13 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
557 { 557 {
558 // Draw joysticks 558 // Draw joysticks
559 using namespace Settings::NativeAnalog; 559 using namespace Settings::NativeAnalog;
560 const auto& l_stick = axis_values[LStick]; 560 const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value);
561 const auto l_button = button_values[Settings::NativeButton::LStick]; 561 const auto l_button = button_values[Settings::NativeButton::LStick];
562 const auto& r_stick = axis_values[RStick]; 562 const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value);
563 const auto r_button = button_values[Settings::NativeButton::RStick]; 563 const auto r_button = button_values[Settings::NativeButton::RStick];
564 564
565 DrawJoystick(p, center + QPointF(-65, -65) + (l_stick.value * 7), 1.62f, l_button); 565 DrawJoystick(p, center + QPointF(-65, -65) + (l_stick * 7), 1.62f, l_button);
566 DrawJoystick(p, center + QPointF(65, 12) + (r_stick.value * 7), 1.62f, r_button); 566 DrawJoystick(p, center + QPointF(65, 12) + (r_stick * 7), 1.62f, r_button);
567 DrawRawJoystick(p, center + QPointF(-180, 90), center + QPointF(180, 90)); 567 DrawRawJoystick(p, center + QPointF(-180, 90), center + QPointF(180, 90));
568 } 568 }
569 569
@@ -634,6 +634,10 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
634 p.setPen(colors.transparent); 634 p.setPen(colors.transparent);
635 p.setBrush(colors.font2); 635 p.setBrush(colors.font2);
636 DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f); 636 DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f);
637
638 // Draw battery
639 DrawBattery(p, center + QPoint(-100, -160), battery_values[0]);
640 DrawBattery(p, center + QPoint(40, -160), battery_values[1]);
637} 641}
638 642
639void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) { 643void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) {
@@ -643,13 +647,13 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
643 { 647 {
644 // Draw joysticks 648 // Draw joysticks
645 using namespace Settings::NativeAnalog; 649 using namespace Settings::NativeAnalog;
646 const auto& l_stick = axis_values[LStick]; 650 const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value);
647 const auto l_button = button_values[Settings::NativeButton::LStick]; 651 const auto l_button = button_values[Settings::NativeButton::LStick];
648 const auto& r_stick = axis_values[RStick]; 652 const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value);
649 const auto r_button = button_values[Settings::NativeButton::RStick]; 653 const auto r_button = button_values[Settings::NativeButton::RStick];
650 654
651 DrawJoystick(p, center + QPointF(-171, -41) + (l_stick.value * 4), 1.0f, l_button); 655 DrawJoystick(p, center + QPointF(-171, -41) + (l_stick * 4), 1.0f, l_button);
652 DrawJoystick(p, center + QPointF(171, 8) + (r_stick.value * 4), 1.0f, r_button); 656 DrawJoystick(p, center + QPointF(171, 8) + (r_stick * 4), 1.0f, r_button);
653 DrawRawJoystick(p, center + QPointF(-50, 0), center + QPointF(50, 0)); 657 DrawRawJoystick(p, center + QPointF(-50, 0), center + QPointF(50, 0));
654 } 658 }
655 659
@@ -732,6 +736,11 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
732 p.setPen(colors.transparent); 736 p.setPen(colors.transparent);
733 p.setBrush(colors.font2); 737 p.setBrush(colors.font2);
734 DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f); 738 DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f);
739
740 // Draw battery
741 DrawBattery(p, center + QPoint(-200, 110), battery_values[0]);
742 DrawBattery(p, center + QPoint(-30, 110), battery_values[1]);
743 DrawBattery(p, center + QPoint(130, 110), battery_values[2]);
735} 744}
736 745
737void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) { 746void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) {
@@ -741,9 +750,11 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
741 { 750 {
742 // Draw joysticks 751 // Draw joysticks
743 using namespace Settings::NativeAnalog; 752 using namespace Settings::NativeAnalog;
744 DrawProJoystick(p, center + QPointF(-111, -55), axis_values[LStick].value, 11, 753 const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value);
754 const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value);
755 DrawProJoystick(p, center + QPointF(-111, -55), l_stick, 11,
745 button_values[Settings::NativeButton::LStick]); 756 button_values[Settings::NativeButton::LStick]);
746 DrawProJoystick(p, center + QPointF(51, 0), axis_values[RStick].value, 11, 757 DrawProJoystick(p, center + QPointF(51, 0), r_stick, 11,
747 button_values[Settings::NativeButton::RStick]); 758 button_values[Settings::NativeButton::RStick]);
748 DrawRawJoystick(p, center + QPointF(-50, 105), center + QPointF(50, 105)); 759 DrawRawJoystick(p, center + QPointF(-50, 105), center + QPointF(50, 105));
749 } 760 }
@@ -817,24 +828,26 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
817 p.setPen(colors.transparent); 828 p.setPen(colors.transparent);
818 p.setBrush(colors.font2); 829 p.setBrush(colors.font2);
819 DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f); 830 DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);
831
832 // Draw battery
833 DrawBattery(p, center + QPoint(-30, -165), battery_values[0]);
820} 834}
821 835
822void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) { 836void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
823 DrawGCTriggers(p, center, button_values[Settings::NativeButton::ZL], 837 DrawGCTriggers(p, center, trigger_values[0], trigger_values[1]);
824 button_values[Settings::NativeButton::ZR]);
825 DrawGCButtonZ(p, center, button_values[Settings::NativeButton::R]); 838 DrawGCButtonZ(p, center, button_values[Settings::NativeButton::R]);
826 DrawGCBody(p, center); 839 DrawGCBody(p, center);
827 { 840 {
828 // Draw joysticks 841 // Draw joysticks
829 using namespace Settings::NativeAnalog; 842 using namespace Settings::NativeAnalog;
830 DrawGCJoystick(p, center + QPointF(-111, -44) + (axis_values[LStick].value * 10), false); 843 const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value);
844 const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value);
845 DrawGCJoystick(p, center + QPointF(-111, -44) + (l_stick * 10), {});
831 button_color = colors.button2; 846 button_color = colors.button2;
832 DrawCircleButton(p, center + QPointF(61, 37) + (axis_values[RStick].value * 9.5f), false, 847 DrawCircleButton(p, center + QPointF(61, 37) + (r_stick * 9.5f), {}, 15);
833 15);
834 p.setPen(colors.transparent); 848 p.setPen(colors.transparent);
835 p.setBrush(colors.font); 849 p.setBrush(colors.font);
836 DrawSymbol(p, center + QPointF(61, 37) + (axis_values[RStick].value * 9.5f), Symbol::C, 850 DrawSymbol(p, center + QPointF(61, 37) + (r_stick * 9.5f), Symbol::C, 1.0f);
837 1.0f);
838 DrawRawJoystick(p, center + QPointF(-198, -125), center + QPointF(198, -125)); 851 DrawRawJoystick(p, center + QPointF(-198, -125), center + QPointF(198, -125));
839 } 852 }
840 853
@@ -871,6 +884,9 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
871 // Minus and Plus buttons 884 // Minus and Plus buttons
872 p.setPen(colors.outline); 885 p.setPen(colors.outline);
873 DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8); 886 DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8);
887
888 // Draw battery
889 DrawBattery(p, center + QPoint(-30, -165), battery_values[0]);
874} 890}
875 891
876constexpr std::array<float, 13 * 2> symbol_a = { 892constexpr std::array<float, 13 * 2> symbol_a = {
@@ -1939,8 +1955,9 @@ void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) {
1939 } 1955 }
1940} 1956}
1941 1957
1942void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bool left_pressed, 1958void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center,
1943 bool right_pressed) { 1959 const Input::ButtonStatus& left_pressed,
1960 const Input::ButtonStatus& right_pressed) {
1944 std::array<QPointF, pro_left_trigger.size() / 2> qleft_trigger; 1961 std::array<QPointF, pro_left_trigger.size() / 2> qleft_trigger;
1945 std::array<QPointF, pro_left_trigger.size() / 2> qright_trigger; 1962 std::array<QPointF, pro_left_trigger.size() / 2> qright_trigger;
1946 std::array<QPointF, pro_body_top.size()> qbody_top; 1963 std::array<QPointF, pro_body_top.size()> qbody_top;
@@ -1949,8 +1966,10 @@ void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bo
1949 const float trigger_x = pro_left_trigger[point * 2 + 0]; 1966 const float trigger_x = pro_left_trigger[point * 2 + 0];
1950 const float trigger_y = pro_left_trigger[point * 2 + 1]; 1967 const float trigger_y = pro_left_trigger[point * 2 + 1];
1951 1968
1952 qleft_trigger[point] = center + QPointF(trigger_x, trigger_y + (left_pressed ? 2 : 0)); 1969 qleft_trigger[point] =
1953 qright_trigger[point] = center + QPointF(-trigger_x, trigger_y + (right_pressed ? 2 : 0)); 1970 center + QPointF(trigger_x, trigger_y + (left_pressed.value ? 2 : 0));
1971 qright_trigger[point] =
1972 center + QPointF(-trigger_x, trigger_y + (right_pressed.value ? 2 : 0));
1954 } 1973 }
1955 1974
1956 for (std::size_t point = 0; point < pro_body_top.size() / 2; ++point) { 1975 for (std::size_t point = 0; point < pro_body_top.size() / 2; ++point) {
@@ -1967,16 +1986,17 @@ void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bo
1967 DrawPolygon(p, qbody_top); 1986 DrawPolygon(p, qbody_top);
1968 1987
1969 // Left trigger 1988 // Left trigger
1970 p.setBrush(left_pressed ? colors.highlight : colors.button); 1989 p.setBrush(left_pressed.value ? colors.highlight : colors.button);
1971 DrawPolygon(p, qleft_trigger); 1990 DrawPolygon(p, qleft_trigger);
1972 1991
1973 // Right trigger 1992 // Right trigger
1974 p.setBrush(right_pressed ? colors.highlight : colors.button); 1993 p.setBrush(right_pressed.value ? colors.highlight : colors.button);
1975 DrawPolygon(p, qright_trigger); 1994 DrawPolygon(p, qright_trigger);
1976} 1995}
1977 1996
1978void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, bool left_pressed, 1997void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center,
1979 bool right_pressed) { 1998 Input::TriggerStatus left_trigger,
1999 Input::TriggerStatus right_trigger) {
1980 std::array<QPointF, left_gc_trigger.size() / 2> qleft_trigger; 2000 std::array<QPointF, left_gc_trigger.size() / 2> qleft_trigger;
1981 std::array<QPointF, left_gc_trigger.size() / 2> qright_trigger; 2001 std::array<QPointF, left_gc_trigger.size() / 2> qright_trigger;
1982 2002
@@ -1984,32 +2004,37 @@ void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, boo
1984 const float trigger_x = left_gc_trigger[point * 2 + 0]; 2004 const float trigger_x = left_gc_trigger[point * 2 + 0];
1985 const float trigger_y = left_gc_trigger[point * 2 + 1]; 2005 const float trigger_y = left_gc_trigger[point * 2 + 1];
1986 2006
1987 qleft_trigger[point] = center + QPointF(trigger_x, trigger_y + (left_pressed ? 10 : 0)); 2007 qleft_trigger[point] =
1988 qright_trigger[point] = center + QPointF(-trigger_x, trigger_y + (right_pressed ? 10 : 0)); 2008 center + QPointF(trigger_x, trigger_y + (left_trigger.analog.value * 10.0f));
2009 qright_trigger[point] =
2010 center + QPointF(-trigger_x, trigger_y + (right_trigger.analog.value * 10.0f));
1989 } 2011 }
1990 2012
1991 // Left trigger 2013 // Left trigger
1992 p.setPen(colors.outline); 2014 p.setPen(colors.outline);
1993 p.setBrush(left_pressed ? colors.highlight : colors.button); 2015 p.setBrush(left_trigger.pressed ? colors.highlight : colors.button);
1994 DrawPolygon(p, qleft_trigger); 2016 DrawPolygon(p, qleft_trigger);
1995 2017
1996 // Right trigger 2018 // Right trigger
1997 p.setBrush(right_pressed ? colors.highlight : colors.button); 2019 p.setBrush(right_trigger.pressed ? colors.highlight : colors.button);
1998 DrawPolygon(p, qright_trigger); 2020 DrawPolygon(p, qright_trigger);
1999 2021
2000 // Draw L text 2022 // Draw L text
2001 p.setPen(colors.transparent); 2023 p.setPen(colors.transparent);
2002 p.setBrush(colors.font); 2024 p.setBrush(colors.font);
2003 DrawSymbol(p, center + QPointF(-132, -119 + (left_pressed ? 10 : 0)), Symbol::L, 1.7f); 2025 DrawSymbol(p, center + QPointF(-132, -119 + (left_trigger.analog.value * 10.0f)), Symbol::L,
2026 1.7f);
2004 2027
2005 // Draw R text 2028 // Draw R text
2006 p.setPen(colors.transparent); 2029 p.setPen(colors.transparent);
2007 p.setBrush(colors.font); 2030 p.setBrush(colors.font);
2008 DrawSymbol(p, center + QPointF(121.5f, -119 + (right_pressed ? 10 : 0)), Symbol::R, 1.7f); 2031 DrawSymbol(p, center + QPointF(121.5f, -119 + (right_trigger.analog.value * 10.0f)), Symbol::R,
2032 1.7f);
2009} 2033}
2010 2034
2011void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF center, 2035void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF center,
2012 bool left_pressed, bool right_pressed) { 2036 const Input::ButtonStatus& left_pressed,
2037 const Input::ButtonStatus& right_pressed) {
2013 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger; 2038 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
2014 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger; 2039 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
2015 2040
@@ -2018,23 +2043,24 @@ void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF cente
2018 const float left_trigger_y = left_joycon_trigger[point * 2 + 1]; 2043 const float left_trigger_y = left_joycon_trigger[point * 2 + 1];
2019 2044
2020 qleft_trigger[point] = 2045 qleft_trigger[point] =
2021 center + QPointF(left_trigger_x, left_trigger_y + (left_pressed ? 0.5f : 0)); 2046 center + QPointF(left_trigger_x, left_trigger_y + (left_pressed.value ? 0.5f : 0));
2022 qright_trigger[point] = 2047 qright_trigger[point] =
2023 center + QPointF(-left_trigger_x, left_trigger_y + (right_pressed ? 0.5f : 0)); 2048 center + QPointF(-left_trigger_x, left_trigger_y + (right_pressed.value ? 0.5f : 0));
2024 } 2049 }
2025 2050
2026 // Left trigger 2051 // Left trigger
2027 p.setPen(colors.outline); 2052 p.setPen(colors.outline);
2028 p.setBrush(left_pressed ? colors.highlight : colors.button); 2053 p.setBrush(left_pressed.value ? colors.highlight : colors.button);
2029 DrawPolygon(p, qleft_trigger); 2054 DrawPolygon(p, qleft_trigger);
2030 2055
2031 // Right trigger 2056 // Right trigger
2032 p.setBrush(right_pressed ? colors.highlight : colors.button); 2057 p.setBrush(right_pressed.value ? colors.highlight : colors.button);
2033 DrawPolygon(p, qright_trigger); 2058 DrawPolygon(p, qright_trigger);
2034} 2059}
2035 2060
2036void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, bool left_pressed, 2061void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center,
2037 bool right_pressed) { 2062 const Input::ButtonStatus& left_pressed,
2063 const Input::ButtonStatus& right_pressed) {
2038 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger; 2064 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
2039 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger; 2065 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
2040 constexpr float size = 1.62f; 2066 constexpr float size = 1.62f;
@@ -2043,25 +2069,27 @@ void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, b
2043 const float left_trigger_x = left_joycon_trigger[point * 2 + 0]; 2069 const float left_trigger_x = left_joycon_trigger[point * 2 + 0];
2044 const float left_trigger_y = left_joycon_trigger[point * 2 + 1]; 2070 const float left_trigger_y = left_joycon_trigger[point * 2 + 1];
2045 2071
2046 qleft_trigger[point] = center + QPointF(left_trigger_x * size + offset, 2072 qleft_trigger[point] =
2047 left_trigger_y * size + (left_pressed ? 0.5f : 0)); 2073 center + QPointF(left_trigger_x * size + offset,
2074 left_trigger_y * size + (left_pressed.value ? 0.5f : 0));
2048 qright_trigger[point] = 2075 qright_trigger[point] =
2049 center + QPointF(-left_trigger_x * size - offset, 2076 center + QPointF(-left_trigger_x * size - offset,
2050 left_trigger_y * size + (right_pressed ? 0.5f : 0)); 2077 left_trigger_y * size + (right_pressed.value ? 0.5f : 0));
2051 } 2078 }
2052 2079
2053 // Left trigger 2080 // Left trigger
2054 p.setPen(colors.outline); 2081 p.setPen(colors.outline);
2055 p.setBrush(left_pressed ? colors.highlight : colors.button); 2082 p.setBrush(left_pressed.value ? colors.highlight : colors.button);
2056 DrawPolygon(p, qleft_trigger); 2083 DrawPolygon(p, qleft_trigger);
2057 2084
2058 // Right trigger 2085 // Right trigger
2059 p.setBrush(right_pressed ? colors.highlight : colors.button); 2086 p.setBrush(right_pressed.value ? colors.highlight : colors.button);
2060 DrawPolygon(p, qright_trigger); 2087 DrawPolygon(p, qright_trigger);
2061} 2088}
2062 2089
2063void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF center, 2090void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF center,
2064 bool left_pressed, bool right_pressed) { 2091 const Input::ButtonStatus& left_pressed,
2092 const Input::ButtonStatus& right_pressed) {
2065 std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger; 2093 std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger;
2066 std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger; 2094 std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger;
2067 constexpr float size = 0.9f; 2095 constexpr float size = 0.9f;
@@ -2080,9 +2108,9 @@ void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF ce
2080 } 2108 }
2081 2109
2082 p.setPen(colors.outline); 2110 p.setPen(colors.outline);
2083 p.setBrush(left_pressed ? colors.highlight : colors.button); 2111 p.setBrush(left_pressed.value ? colors.highlight : colors.button);
2084 DrawPolygon(p, qleft_trigger); 2112 DrawPolygon(p, qleft_trigger);
2085 p.setBrush(right_pressed ? colors.highlight : colors.button); 2113 p.setBrush(right_pressed.value ? colors.highlight : colors.button);
2086 DrawPolygon(p, qright_trigger); 2114 DrawPolygon(p, qright_trigger);
2087 2115
2088 // Draw L text 2116 // Draw L text
@@ -2097,7 +2125,8 @@ void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF ce
2097} 2125}
2098 2126
2099void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF center, 2127void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF center,
2100 bool left_pressed, bool right_pressed) { 2128 const Input::ButtonStatus& left_pressed,
2129 const Input::ButtonStatus& right_pressed) {
2101 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger; 2130 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger;
2102 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger; 2131 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger;
2103 constexpr float size = 0.9f; 2132 constexpr float size = 0.9f;
@@ -2114,9 +2143,9 @@ void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF c
2114 } 2143 }
2115 2144
2116 p.setPen(colors.outline); 2145 p.setPen(colors.outline);
2117 p.setBrush(left_pressed ? colors.highlight : colors.button); 2146 p.setBrush(left_pressed.value ? colors.highlight : colors.button);
2118 DrawPolygon(p, qleft_trigger); 2147 DrawPolygon(p, qleft_trigger);
2119 p.setBrush(right_pressed ? colors.highlight : colors.button); 2148 p.setBrush(right_pressed.value ? colors.highlight : colors.button);
2120 DrawPolygon(p, qright_trigger); 2149 DrawPolygon(p, qright_trigger);
2121 2150
2122 // Draw ZL text 2151 // Draw ZL text
@@ -2130,7 +2159,8 @@ void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF c
2130 DrawSymbol(p, center + QPointF(180, -113), Symbol::ZR, 1.0f); 2159 DrawSymbol(p, center + QPointF(180, -113), Symbol::ZR, 1.0f);
2131} 2160}
2132 2161
2133void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, bool left_pressed) { 2162void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center,
2163 const Input::ButtonStatus& left_pressed) {
2134 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger; 2164 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
2135 constexpr float size = 1.78f; 2165 constexpr float size = 1.78f;
2136 constexpr float offset = 311.5f; 2166 constexpr float offset = 311.5f;
@@ -2138,15 +2168,16 @@ void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, b
2138 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) { 2168 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
2139 qleft_trigger[point] = center + QPointF(left_joycon_trigger[point * 2] * size + offset, 2169 qleft_trigger[point] = center + QPointF(left_joycon_trigger[point * 2] * size + offset,
2140 left_joycon_trigger[point * 2 + 1] * size - 2170 left_joycon_trigger[point * 2 + 1] * size -
2141 (left_pressed ? 0.5f : 1.0f)); 2171 (left_pressed.value ? 0.5f : 1.0f));
2142 } 2172 }
2143 2173
2144 p.setPen(colors.outline); 2174 p.setPen(colors.outline);
2145 p.setBrush(left_pressed ? colors.highlight : colors.button); 2175 p.setBrush(left_pressed.value ? colors.highlight : colors.button);
2146 DrawPolygon(p, qleft_trigger); 2176 DrawPolygon(p, qleft_trigger);
2147} 2177}
2148 2178
2149void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center, bool left_pressed) { 2179void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center,
2180 const Input::ButtonStatus& left_pressed) {
2150 std::array<QPointF, left_joycon_sideview_zl.size() / 2> qleft_trigger; 2181 std::array<QPointF, left_joycon_sideview_zl.size() / 2> qleft_trigger;
2151 constexpr float size = 1.1115f; 2182 constexpr float size = 1.1115f;
2152 constexpr float offset2 = 335; 2183 constexpr float offset2 = 335;
@@ -2154,18 +2185,18 @@ void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center,
2154 for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) { 2185 for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) {
2155 qleft_trigger[point] = center + QPointF(left_joycon_sideview_zl[point * 2] * size + offset2, 2186 qleft_trigger[point] = center + QPointF(left_joycon_sideview_zl[point * 2] * size + offset2,
2156 left_joycon_sideview_zl[point * 2 + 1] * size + 2187 left_joycon_sideview_zl[point * 2 + 1] * size +
2157 (left_pressed ? 1.5f : 1.0f)); 2188 (left_pressed.value ? 1.5f : 1.0f));
2158 } 2189 }
2159 2190
2160 p.setPen(colors.outline); 2191 p.setPen(colors.outline);
2161 p.setBrush(left_pressed ? colors.highlight : colors.button); 2192 p.setBrush(left_pressed.value ? colors.highlight : colors.button);
2162 DrawPolygon(p, qleft_trigger); 2193 DrawPolygon(p, qleft_trigger);
2163 p.drawArc(center.x() + 158, center.y() + (left_pressed ? -203.5f : -204.0f), 77, 77, 225 * 16, 2194 p.drawArc(center.x() + 158, center.y() + (left_pressed.value ? -203.5f : -204.0f), 77, 77,
2164 44 * 16); 2195 225 * 16, 44 * 16);
2165} 2196}
2166 2197
2167void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF center, 2198void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF center,
2168 bool left_pressed) { 2199 const Input::ButtonStatus& left_pressed) {
2169 std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger; 2200 std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger;
2170 2201
2171 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) { 2202 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
@@ -2174,7 +2205,7 @@ void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF ce
2174 } 2205 }
2175 2206
2176 p.setPen(colors.outline); 2207 p.setPen(colors.outline);
2177 p.setBrush(left_pressed ? colors.highlight : colors.button); 2208 p.setBrush(left_pressed.value ? colors.highlight : colors.button);
2178 DrawPolygon(p, qleft_trigger); 2209 DrawPolygon(p, qleft_trigger);
2179 2210
2180 // Draw L text 2211 // Draw L text
@@ -2184,7 +2215,7 @@ void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF ce
2184} 2215}
2185 2216
2186void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF center, 2217void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF center,
2187 bool left_pressed) { 2218 const Input::ButtonStatus& left_pressed) {
2188 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger; 2219 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger;
2189 2220
2190 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) { 2221 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
@@ -2193,7 +2224,7 @@ void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF c
2193 } 2224 }
2194 2225
2195 p.setPen(colors.outline); 2226 p.setPen(colors.outline);
2196 p.setBrush(left_pressed ? colors.highlight : colors.button); 2227 p.setBrush(left_pressed.value ? colors.highlight : colors.button);
2197 DrawPolygon(p, qleft_trigger); 2228 DrawPolygon(p, qleft_trigger);
2198 2229
2199 // Draw ZL text 2230 // Draw ZL text
@@ -2203,7 +2234,7 @@ void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF c
2203} 2234}
2204 2235
2205void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center, 2236void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center,
2206 bool right_pressed) { 2237 const Input::ButtonStatus& right_pressed) {
2207 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger; 2238 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
2208 constexpr float size = 1.78f; 2239 constexpr float size = 1.78f;
2209 constexpr float offset = 311.5f; 2240 constexpr float offset = 311.5f;
@@ -2211,36 +2242,36 @@ void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center,
2211 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) { 2242 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
2212 qright_trigger[point] = center + QPointF(-left_joycon_trigger[point * 2] * size - offset, 2243 qright_trigger[point] = center + QPointF(-left_joycon_trigger[point * 2] * size - offset,
2213 left_joycon_trigger[point * 2 + 1] * size - 2244 left_joycon_trigger[point * 2 + 1] * size -
2214 (right_pressed ? 0.5f : 1.0f)); 2245 (right_pressed.value ? 0.5f : 1.0f));
2215 } 2246 }
2216 2247
2217 p.setPen(colors.outline); 2248 p.setPen(colors.outline);
2218 p.setBrush(right_pressed ? colors.highlight : colors.button); 2249 p.setBrush(right_pressed.value ? colors.highlight : colors.button);
2219 DrawPolygon(p, qright_trigger); 2250 DrawPolygon(p, qright_trigger);
2220} 2251}
2221 2252
2222void PlayerControlPreview::DrawRightZTriggers(QPainter& p, const QPointF center, 2253void PlayerControlPreview::DrawRightZTriggers(QPainter& p, const QPointF center,
2223 bool right_pressed) { 2254 const Input::ButtonStatus& right_pressed) {
2224 std::array<QPointF, left_joycon_sideview_zl.size() / 2> qright_trigger; 2255 std::array<QPointF, left_joycon_sideview_zl.size() / 2> qright_trigger;
2225 constexpr float size = 1.1115f; 2256 constexpr float size = 1.1115f;
2226 constexpr float offset2 = 335; 2257 constexpr float offset2 = 335;
2227 2258
2228 for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) { 2259 for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) {
2229 qright_trigger[point] = 2260 qright_trigger[point] =
2230 center + 2261 center + QPointF(-left_joycon_sideview_zl[point * 2] * size - offset2,
2231 QPointF(-left_joycon_sideview_zl[point * 2] * size - offset2, 2262 left_joycon_sideview_zl[point * 2 + 1] * size +
2232 left_joycon_sideview_zl[point * 2 + 1] * size + (right_pressed ? 0.5f : 0) + 1); 2263 (right_pressed.value ? 0.5f : 0) + 1);
2233 } 2264 }
2234 2265
2235 p.setPen(colors.outline); 2266 p.setPen(colors.outline);
2236 p.setBrush(right_pressed ? colors.highlight : colors.button); 2267 p.setBrush(right_pressed.value ? colors.highlight : colors.button);
2237 DrawPolygon(p, qright_trigger); 2268 DrawPolygon(p, qright_trigger);
2238 p.drawArc(center.x() - 236, center.y() + (right_pressed ? -203.5f : -204.0f), 77, 77, 271 * 16, 2269 p.drawArc(center.x() - 236, center.y() + (right_pressed.value ? -203.5f : -204.0f), 77, 77,
2239 44 * 16); 2270 271 * 16, 44 * 16);
2240} 2271}
2241 2272
2242void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF center, 2273void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF center,
2243 bool right_pressed) { 2274 const Input::ButtonStatus& right_pressed) {
2244 std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger; 2275 std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger;
2245 2276
2246 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) { 2277 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
@@ -2249,7 +2280,7 @@ void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF c
2249 } 2280 }
2250 2281
2251 p.setPen(colors.outline); 2282 p.setPen(colors.outline);
2252 p.setBrush(right_pressed ? colors.highlight : colors.button); 2283 p.setBrush(right_pressed.value ? colors.highlight : colors.button);
2253 DrawPolygon(p, qright_trigger); 2284 DrawPolygon(p, qright_trigger);
2254 2285
2255 // Draw R text 2286 // Draw R text
@@ -2259,7 +2290,7 @@ void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF c
2259} 2290}
2260 2291
2261void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF center, 2292void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF center,
2262 bool right_pressed) { 2293 const Input::ButtonStatus& right_pressed) {
2263 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger; 2294 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger;
2264 2295
2265 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) { 2296 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
@@ -2268,7 +2299,7 @@ void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF
2268 } 2299 }
2269 2300
2270 p.setPen(colors.outline); 2301 p.setPen(colors.outline);
2271 p.setBrush(right_pressed ? colors.highlight : colors.button); 2302 p.setBrush(right_pressed.value ? colors.highlight : colors.button);
2272 DrawPolygon(p, qright_trigger); 2303 DrawPolygon(p, qright_trigger);
2273 2304
2274 // Draw ZR text 2305 // Draw ZR text
@@ -2278,13 +2309,13 @@ void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF
2278} 2309}
2279 2310
2280void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float size, 2311void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float size,
2281 bool pressed) { 2312 const Input::ButtonStatus& pressed) {
2282 const float radius1 = 13.0f * size; 2313 const float radius1 = 13.0f * size;
2283 const float radius2 = 9.0f * size; 2314 const float radius2 = 9.0f * size;
2284 2315
2285 // Outer circle 2316 // Outer circle
2286 p.setPen(colors.outline); 2317 p.setPen(colors.outline);
2287 p.setBrush(pressed ? colors.highlight : colors.button); 2318 p.setBrush(pressed.value ? colors.highlight : colors.button);
2288 DrawCircle(p, center, radius1); 2319 DrawCircle(p, center, radius1);
2289 2320
2290 // Cross 2321 // Cross
@@ -2292,17 +2323,17 @@ void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float
2292 p.drawLine(center - QPoint(0, radius1), center + QPoint(0, radius1)); 2323 p.drawLine(center - QPoint(0, radius1), center + QPoint(0, radius1));
2293 2324
2294 // Inner circle 2325 // Inner circle
2295 p.setBrush(pressed ? colors.highlight2 : colors.button2); 2326 p.setBrush(pressed.value ? colors.highlight2 : colors.button2);
2296 DrawCircle(p, center, radius2); 2327 DrawCircle(p, center, radius2);
2297} 2328}
2298 2329
2299void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF center, float angle, 2330void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF center, float angle,
2300 float size, bool pressed) { 2331 float size, const Input::ButtonStatus& pressed) {
2301 QVector<QPointF> joystick; 2332 QVector<QPointF> joystick;
2302 joystick.reserve(static_cast<int>(left_joystick_sideview.size() / 2)); 2333 joystick.reserve(static_cast<int>(left_joystick_sideview.size() / 2));
2303 2334
2304 for (std::size_t point = 0; point < left_joystick_sideview.size() / 2; ++point) { 2335 for (std::size_t point = 0; point < left_joystick_sideview.size() / 2; ++point) {
2305 joystick.append(QPointF(left_joystick_sideview[point * 2] * size + (pressed ? 1 : 0), 2336 joystick.append(QPointF(left_joystick_sideview[point * 2] * size + (pressed.value ? 1 : 0),
2306 left_joystick_sideview[point * 2 + 1] * size - 1)); 2337 left_joystick_sideview[point * 2 + 1] * size - 1));
2307 } 2338 }
2308 2339
@@ -2314,14 +2345,15 @@ void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF cente
2314 2345
2315 // Draw joystick 2346 // Draw joystick
2316 p.setPen(colors.outline); 2347 p.setPen(colors.outline);
2317 p.setBrush(pressed ? colors.highlight : colors.button); 2348 p.setBrush(pressed.value ? colors.highlight : colors.button);
2318 p.drawPolygon(p2); 2349 p.drawPolygon(p2);
2319 p.drawLine(p2.at(1), p2.at(30)); 2350 p.drawLine(p2.at(1), p2.at(30));
2320 p.drawLine(p2.at(32), p2.at(71)); 2351 p.drawLine(p2.at(32), p2.at(71));
2321} 2352}
2322 2353
2323void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, const QPointF offset, 2354void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, const QPointF offset,
2324 float offset_scalar, bool pressed) { 2355 float offset_scalar,
2356 const Input::ButtonStatus& pressed) {
2325 const float radius1 = 24.0f; 2357 const float radius1 = 24.0f;
2326 const float radius2 = 17.0f; 2358 const float radius2 = 17.0f;
2327 2359
@@ -2339,11 +2371,11 @@ void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, co
2339 2371
2340 // Outer circle 2372 // Outer circle
2341 p.setPen(colors.outline); 2373 p.setPen(colors.outline);
2342 p.setBrush(pressed ? colors.highlight : colors.button); 2374 p.setBrush(pressed.value ? colors.highlight : colors.button);
2343 p.drawEllipse(QPointF(0, 0), radius1 * amplitude, radius1); 2375 p.drawEllipse(QPointF(0, 0), radius1 * amplitude, radius1);
2344 2376
2345 // Inner circle 2377 // Inner circle
2346 p.setBrush(pressed ? colors.highlight2 : colors.button2); 2378 p.setBrush(pressed.value ? colors.highlight2 : colors.button2);
2347 2379
2348 const float inner_offset = 2380 const float inner_offset =
2349 (radius1 - radius2) * 0.4f * ((offset.x() == 0 && offset.y() < 0) ? -1.0f : 1.0f); 2381 (radius1 - radius2) * 0.4f * ((offset.x() == 0 && offset.y() < 0) ? -1.0f : 1.0f);
@@ -2355,14 +2387,15 @@ void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, co
2355 p.restore(); 2387 p.restore();
2356} 2388}
2357 2389
2358void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, bool pressed) { 2390void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center,
2391 const Input::ButtonStatus& pressed) {
2359 // Outer circle 2392 // Outer circle
2360 p.setPen(colors.outline); 2393 p.setPen(colors.outline);
2361 p.setBrush(pressed ? colors.highlight : colors.button); 2394 p.setBrush(pressed.value ? colors.highlight : colors.button);
2362 DrawCircle(p, center, 26.0f); 2395 DrawCircle(p, center, 26.0f);
2363 2396
2364 // Inner circle 2397 // Inner circle
2365 p.setBrush(pressed ? colors.highlight2 : colors.button2); 2398 p.setBrush(pressed.value ? colors.highlight2 : colors.button2);
2366 DrawCircle(p, center, 19.0f); 2399 DrawCircle(p, center, 19.0f);
2367 p.setBrush(colors.transparent); 2400 p.setBrush(colors.transparent);
2368 DrawCircle(p, center, 13.5f); 2401 DrawCircle(p, center, 13.5f);
@@ -2371,26 +2404,24 @@ void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, boo
2371 2404
2372void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right) { 2405void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right) {
2373 using namespace Settings::NativeAnalog; 2406 using namespace Settings::NativeAnalog;
2374 if (controller_type != Settings::ControllerType::LeftJoycon) { 2407 if (controller_type != Core::HID::NpadType::JoyconLeft) {
2375 DrawJoystickProperties(p, center_right, axis_values[RStick].properties); 2408 DrawJoystickProperties(p, center_right, stick_values[RStick].x.properties);
2376 p.setPen(colors.indicator); 2409 p.setPen(colors.indicator);
2377 p.setBrush(colors.indicator); 2410 p.setBrush(colors.indicator);
2378 DrawJoystickDot(p, center_right, axis_values[RStick].raw_value, 2411 DrawJoystickDot(p, center_right, stick_values[RStick], true);
2379 axis_values[RStick].properties);
2380 p.setPen(colors.indicator2); 2412 p.setPen(colors.indicator2);
2381 p.setBrush(colors.indicator2); 2413 p.setBrush(colors.indicator2);
2382 DrawJoystickDot(p, center_right, axis_values[RStick].value, axis_values[RStick].properties); 2414 DrawJoystickDot(p, center_right, stick_values[RStick], false);
2383 } 2415 }
2384 2416
2385 if (controller_type != Settings::ControllerType::RightJoycon) { 2417 if (controller_type != Core::HID::NpadType::JoyconRight) {
2386 DrawJoystickProperties(p, center_left, axis_values[LStick].properties); 2418 DrawJoystickProperties(p, center_left, stick_values[LStick].x.properties);
2387 p.setPen(colors.indicator); 2419 p.setPen(colors.indicator);
2388 p.setBrush(colors.indicator); 2420 p.setBrush(colors.indicator);
2389 DrawJoystickDot(p, center_left, axis_values[LStick].raw_value, 2421 DrawJoystickDot(p, center_left, stick_values[LStick], true);
2390 axis_values[LStick].properties);
2391 p.setPen(colors.indicator2); 2422 p.setPen(colors.indicator2);
2392 p.setBrush(colors.indicator2); 2423 p.setBrush(colors.indicator2);
2393 DrawJoystickDot(p, center_left, axis_values[LStick].value, axis_values[LStick].properties); 2424 DrawJoystickDot(p, center_left, stick_values[LStick], false);
2394 } 2425 }
2395} 2426}
2396 2427
@@ -2414,19 +2445,26 @@ void PlayerControlPreview::DrawJoystickProperties(QPainter& p, const QPointF cen
2414 DrawCircle(p, center, deadzone); 2445 DrawCircle(p, center, deadzone);
2415} 2446}
2416 2447
2417void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center, const QPointF value, 2448void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center,
2418 const Input::AnalogProperties& properties) { 2449 const Input::StickStatus& stick, bool raw) {
2419 constexpr float size = 45.0f; 2450 constexpr float size = 45.0f;
2420 const float range = size * properties.range; 2451 const float range = size * stick.x.properties.range;
2452
2453 if (raw) {
2454 const QPointF value = QPointF(stick.x.raw_value, stick.y.raw_value) * size;
2455 DrawCircle(p, center + value, 2);
2456 return;
2457 }
2421 2458
2422 // Dot pointer 2459 const QPointF value = QPointF(stick.x.value, stick.y.value) * range;
2423 DrawCircle(p, center + (value * range), 2); 2460 DrawCircle(p, center + value, 2);
2424} 2461}
2425 2462
2426void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width, 2463void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center,
2464 const Input::ButtonStatus& pressed, float width,
2427 float height, Direction direction, float radius) { 2465 float height, Direction direction, float radius) {
2428 p.setBrush(button_color); 2466 p.setBrush(button_color);
2429 if (pressed) { 2467 if (pressed.value) {
2430 switch (direction) { 2468 switch (direction) {
2431 case Direction::Left: 2469 case Direction::Left:
2432 center.setX(center.x() - 1); 2470 center.setX(center.x() - 1);
@@ -2448,17 +2486,17 @@ void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, bool pre
2448 QRectF rect = {center.x() - width, center.y() - height, width * 2.0f, height * 2.0f}; 2486 QRectF rect = {center.x() - width, center.y() - height, width * 2.0f, height * 2.0f};
2449 p.drawRoundedRect(rect, radius, radius); 2487 p.drawRoundedRect(rect, radius, radius);
2450} 2488}
2451void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center, bool pressed, 2489void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center,
2452 int button_size) { 2490 const Input::ButtonStatus& pressed, int button_size) {
2453 p.setPen(colors.outline); 2491 p.setPen(colors.outline);
2454 p.setBrush(pressed ? colors.highlight : colors.button); 2492 p.setBrush(pressed.value ? colors.highlight : colors.button);
2455 DrawRectangle(p, center, button_size, button_size / 3.0f); 2493 DrawRectangle(p, center, button_size, button_size / 3.0f);
2456} 2494}
2457void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, bool pressed, 2495void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center,
2458 int button_size) { 2496 const Input::ButtonStatus& pressed, int button_size) {
2459 // Draw outer line 2497 // Draw outer line
2460 p.setPen(colors.outline); 2498 p.setPen(colors.outline);
2461 p.setBrush(pressed ? colors.highlight : colors.button); 2499 p.setBrush(pressed.value ? colors.highlight : colors.button);
2462 DrawRectangle(p, center, button_size, button_size / 3.0f); 2500 DrawRectangle(p, center, button_size, button_size / 3.0f);
2463 DrawRectangle(p, center, button_size / 3.0f, button_size); 2501 DrawRectangle(p, center, button_size / 3.0f, button_size);
2464 2502
@@ -2471,7 +2509,8 @@ void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, boo
2471 DrawRectangle(p, center, button_size / 3.0f, button_size); 2509 DrawRectangle(p, center, button_size / 3.0f, button_size);
2472} 2510}
2473 2511
2474void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, bool pressed) { 2512void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center,
2513 const Input::ButtonStatus& pressed) {
2475 std::array<QPointF, gc_button_x.size() / 2> button_x; 2514 std::array<QPointF, gc_button_x.size() / 2> button_x;
2476 2515
2477 for (std::size_t point = 0; point < gc_button_x.size() / 2; ++point) { 2516 for (std::size_t point = 0; point < gc_button_x.size() / 2; ++point) {
@@ -2479,11 +2518,12 @@ void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, bool
2479 } 2518 }
2480 2519
2481 p.setPen(colors.outline); 2520 p.setPen(colors.outline);
2482 p.setBrush(pressed ? colors.highlight : colors.button); 2521 p.setBrush(pressed.value ? colors.highlight : colors.button);
2483 DrawPolygon(p, button_x); 2522 DrawPolygon(p, button_x);
2484} 2523}
2485 2524
2486void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, bool pressed) { 2525void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center,
2526 const Input::ButtonStatus& pressed) {
2487 std::array<QPointF, gc_button_y.size() / 2> button_x; 2527 std::array<QPointF, gc_button_y.size() / 2> button_x;
2488 2528
2489 for (std::size_t point = 0; point < gc_button_y.size() / 2; ++point) { 2529 for (std::size_t point = 0; point < gc_button_y.size() / 2; ++point) {
@@ -2491,27 +2531,28 @@ void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, bool
2491 } 2531 }
2492 2532
2493 p.setPen(colors.outline); 2533 p.setPen(colors.outline);
2494 p.setBrush(pressed ? colors.highlight : colors.button); 2534 p.setBrush(pressed.value ? colors.highlight : colors.button);
2495 DrawPolygon(p, button_x); 2535 DrawPolygon(p, button_x);
2496} 2536}
2497 2537
2498void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center, bool pressed) { 2538void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center,
2539 const Input::ButtonStatus& pressed) {
2499 std::array<QPointF, gc_button_z.size() / 2> button_x; 2540 std::array<QPointF, gc_button_z.size() / 2> button_x;
2500 2541
2501 for (std::size_t point = 0; point < gc_button_z.size() / 2; ++point) { 2542 for (std::size_t point = 0; point < gc_button_z.size() / 2; ++point) {
2502 button_x[point] = center + QPointF(gc_button_z[point * 2], 2543 button_x[point] = center + QPointF(gc_button_z[point * 2],
2503 gc_button_z[point * 2 + 1] + (pressed ? 1 : 0)); 2544 gc_button_z[point * 2 + 1] + (pressed.value ? 1 : 0));
2504 } 2545 }
2505 2546
2506 p.setPen(colors.outline); 2547 p.setPen(colors.outline);
2507 p.setBrush(pressed ? colors.highlight : colors.button2); 2548 p.setBrush(pressed.value ? colors.highlight : colors.button2);
2508 DrawPolygon(p, button_x); 2549 DrawPolygon(p, button_x);
2509} 2550}
2510 2551
2511void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center, bool pressed, 2552void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center,
2512 float button_size) { 2553 const Input::ButtonStatus& pressed, float button_size) {
2513 p.setBrush(button_color); 2554 p.setBrush(button_color);
2514 if (pressed) { 2555 if (pressed.value) {
2515 p.setBrush(colors.highlight); 2556 p.setBrush(colors.highlight);
2516 } 2557 }
2517 p.drawEllipse(center, button_size, button_size); 2558 p.drawEllipse(center, button_size, button_size);
@@ -2540,7 +2581,8 @@ void PlayerControlPreview::DrawArrowButtonOutline(QPainter& p, const QPointF cen
2540} 2581}
2541 2582
2542void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, 2583void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
2543 const Direction direction, bool pressed, float size) { 2584 const Direction direction,
2585 const Input::ButtonStatus& pressed, float size) {
2544 std::array<QPointF, up_arrow_button.size() / 2> arrow_button; 2586 std::array<QPointF, up_arrow_button.size() / 2> arrow_button;
2545 QPoint offset; 2587 QPoint offset;
2546 2588
@@ -2567,8 +2609,8 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
2567 } 2609 }
2568 2610
2569 // Draw arrow button 2611 // Draw arrow button
2570 p.setPen(pressed ? colors.highlight : colors.button); 2612 p.setPen(pressed.value ? colors.highlight : colors.button);
2571 p.setBrush(pressed ? colors.highlight : colors.button); 2613 p.setBrush(pressed.value ? colors.highlight : colors.button);
2572 DrawPolygon(p, arrow_button); 2614 DrawPolygon(p, arrow_button);
2573 2615
2574 switch (direction) { 2616 switch (direction) {
@@ -2596,7 +2638,8 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
2596} 2638}
2597 2639
2598void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center, 2640void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
2599 const Direction direction, bool pressed) { 2641 const Direction direction,
2642 const Input::ButtonStatus& pressed) {
2600 std::array<QPointF, trigger_button.size() / 2> qtrigger_button; 2643 std::array<QPointF, trigger_button.size() / 2> qtrigger_button;
2601 2644
2602 for (std::size_t point = 0; point < trigger_button.size() / 2; ++point) { 2645 for (std::size_t point = 0; point < trigger_button.size() / 2; ++point) {
@@ -2619,10 +2662,44 @@ void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
2619 2662
2620 // Draw arrow button 2663 // Draw arrow button
2621 p.setPen(colors.outline); 2664 p.setPen(colors.outline);
2622 p.setBrush(pressed ? colors.highlight : colors.button); 2665 p.setBrush(pressed.value ? colors.highlight : colors.button);
2623 DrawPolygon(p, qtrigger_button); 2666 DrawPolygon(p, qtrigger_button);
2624} 2667}
2625 2668
2669void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, Input::BatteryLevel battery) {
2670 p.setPen(colors.outline);
2671 p.setBrush(colors.transparent);
2672 p.drawRect(center.x(), center.y(), 56, 20);
2673 p.drawRect(center.x() + 56, center.y() + 6, 3, 8);
2674 p.setBrush(colors.deadzone);
2675 switch (battery) {
2676 case Input::BatteryLevel::Charging:
2677 p.setBrush(colors.indicator2);
2678 p.drawText(center + QPoint(2, 14), tr("Charging"));
2679 break;
2680 case Input::BatteryLevel::Full:
2681 p.drawRect(center.x() + 42, center.y(), 14, 20);
2682 p.drawRect(center.x() + 28, center.y(), 14, 20);
2683 p.drawRect(center.x() + 14, center.y(), 14, 20);
2684 break;
2685 case Input::BatteryLevel::Medium:
2686 p.drawRect(center.x() + 28, center.y(), 14, 20);
2687 p.drawRect(center.x() + 14, center.y(), 14, 20);
2688 p.drawRect(center.x(), center.y(), 14, 20);
2689 break;
2690 case Input::BatteryLevel::Low:
2691 p.drawRect(center.x() + 14, center.y(), 14, 20);
2692 p.drawRect(center.x(), center.y(), 14, 20);
2693 break;
2694 case Input::BatteryLevel::Critical:
2695 p.drawRect(center.x(), center.y(), 14, 20);
2696 break;
2697 case Input::BatteryLevel::Empty:
2698 p.drawRect(center.x(), center.y(), 5, 20);
2699 break;
2700 }
2701}
2702
2626void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol symbol, 2703void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol symbol,
2627 float icon_size) { 2704 float icon_size) {
2628 std::array<QPointF, house.size() / 2> house_icon; 2705 std::array<QPointF, house.size() / 2> house_icon;
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index f4bbfa528..b44a2e347 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -7,9 +7,10 @@
7#include <array> 7#include <array>
8#include <QFrame> 8#include <QFrame>
9#include <QPointer> 9#include <QPointer>
10#include "common/input.h"
10#include "common/settings.h" 11#include "common/settings.h"
11#include "core/frontend/input.h" 12#include "core/hid/hid_core.h"
12#include "yuzu/debugger/controller.h" 13#include "core/hid/hid_types.h"
13 14
14class QLabel; 15class QLabel;
15 16
@@ -24,17 +25,12 @@ public:
24 explicit PlayerControlPreview(QWidget* parent); 25 explicit PlayerControlPreview(QWidget* parent);
25 ~PlayerControlPreview() override; 26 ~PlayerControlPreview() override;
26 27
27 void SetPlayerInput(std::size_t index, const ButtonParam& buttons_param, 28 void SetController(Core::HID::EmulatedController* controller);
28 const AnalogParam& analogs_param);
29 void SetPlayerInputRaw(std::size_t index, const Settings::ButtonsRaw& buttons_,
30 Settings::AnalogsRaw analogs_);
31 void SetConnectedStatus(bool checked);
32 void SetControllerType(Settings::ControllerType type);
33 void BeginMappingButton(std::size_t button_id); 29 void BeginMappingButton(std::size_t button_id);
34 void BeginMappingAnalog(std::size_t button_id); 30 void BeginMappingAnalog(std::size_t button_id);
35 void EndMapping(); 31 void EndMapping();
32 void ControllerUpdate(Core::HID::ControllerTriggerType type);
36 void UpdateInput(); 33 void UpdateInput();
37 void SetCallBack(ControllerCallback callback_);
38 34
39protected: 35protected:
40 void paintEvent(QPaintEvent* event) override; 36 void paintEvent(QPaintEvent* event) override;
@@ -63,15 +59,6 @@ private:
63 SR, 59 SR,
64 }; 60 };
65 61
66 struct AxisValue {
67 QPointF value{};
68 QPointF raw_value{};
69 Input::AnalogProperties properties{};
70 int size{};
71 QPoint offset{};
72 bool active{};
73 };
74
75 struct LedPattern { 62 struct LedPattern {
76 bool position1; 63 bool position1;
77 bool position2; 64 bool position2;
@@ -122,47 +109,66 @@ private:
122 void DrawGCBody(QPainter& p, QPointF center); 109 void DrawGCBody(QPainter& p, QPointF center);
123 110
124 // Draw triggers functions 111 // Draw triggers functions
125 void DrawProTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); 112 void DrawProTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed,
126 void DrawGCTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); 113 const Input::ButtonStatus& right_pressed);
127 void DrawHandheldTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); 114 void DrawGCTriggers(QPainter& p, QPointF center, Input::TriggerStatus left_trigger,
128 void DrawDualTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); 115 Input::TriggerStatus right_trigger);
129 void DrawDualTriggersTopView(QPainter& p, QPointF center, bool left_pressed, 116 void DrawHandheldTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed,
130 bool right_pressed); 117 const Input::ButtonStatus& right_pressed);
131 void DrawDualZTriggersTopView(QPainter& p, QPointF center, bool left_pressed, 118 void DrawDualTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed,
132 bool right_pressed); 119 const Input::ButtonStatus& right_pressed);
133 void DrawLeftTriggers(QPainter& p, QPointF center, bool left_pressed); 120 void DrawDualTriggersTopView(QPainter& p, QPointF center,
134 void DrawLeftZTriggers(QPainter& p, QPointF center, bool left_pressed); 121 const Input::ButtonStatus& left_pressed,
135 void DrawLeftTriggersTopView(QPainter& p, QPointF center, bool left_pressed); 122 const Input::ButtonStatus& right_pressed);
136 void DrawLeftZTriggersTopView(QPainter& p, QPointF center, bool left_pressed); 123 void DrawDualZTriggersTopView(QPainter& p, QPointF center,
137 void DrawRightTriggers(QPainter& p, QPointF center, bool right_pressed); 124 const Input::ButtonStatus& left_pressed,
138 void DrawRightZTriggers(QPainter& p, QPointF center, bool right_pressed); 125 const Input::ButtonStatus& right_pressed);
139 void DrawRightTriggersTopView(QPainter& p, QPointF center, bool right_pressed); 126 void DrawLeftTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed);
140 void DrawRightZTriggersTopView(QPainter& p, QPointF center, bool right_pressed); 127 void DrawLeftZTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& left_pressed);
128 void DrawLeftTriggersTopView(QPainter& p, QPointF center,
129 const Input::ButtonStatus& left_pressed);
130 void DrawLeftZTriggersTopView(QPainter& p, QPointF center,
131 const Input::ButtonStatus& left_pressed);
132 void DrawRightTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& right_pressed);
133 void DrawRightZTriggers(QPainter& p, QPointF center, const Input::ButtonStatus& right_pressed);
134 void DrawRightTriggersTopView(QPainter& p, QPointF center,
135 const Input::ButtonStatus& right_pressed);
136 void DrawRightZTriggersTopView(QPainter& p, QPointF center,
137 const Input::ButtonStatus& right_pressed);
141 138
142 // Draw joystick functions 139 // Draw joystick functions
143 void DrawJoystick(QPainter& p, QPointF center, float size, bool pressed); 140 void DrawJoystick(QPainter& p, QPointF center, float size, const Input::ButtonStatus& pressed);
144 void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size, bool pressed); 141 void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size,
142 const Input::ButtonStatus& pressed);
145 void DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right); 143 void DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right);
146 void DrawJoystickProperties(QPainter& p, QPointF center, 144 void DrawJoystickProperties(QPainter& p, QPointF center,
147 const Input::AnalogProperties& properties); 145 const Input::AnalogProperties& properties);
148 void DrawJoystickDot(QPainter& p, QPointF center, QPointF value, 146 void DrawJoystickDot(QPainter& p, QPointF center, const Input::StickStatus& stick, bool raw);
149 const Input::AnalogProperties& properties); 147 void DrawProJoystick(QPainter& p, QPointF center, QPointF offset, float scalar,
150 void DrawProJoystick(QPainter& p, QPointF center, QPointF offset, float scalar, bool pressed); 148 const Input::ButtonStatus& pressed);
151 void DrawGCJoystick(QPainter& p, QPointF center, bool pressed); 149 void DrawGCJoystick(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
152 150
153 // Draw button functions 151 // Draw button functions
154 void DrawCircleButton(QPainter& p, QPointF center, bool pressed, float button_size); 152 void DrawCircleButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
155 void DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width, float height, 153 float button_size);
156 Direction direction = Direction::None, float radius = 2); 154 void DrawRoundButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
157 void DrawMinusButton(QPainter& p, QPointF center, bool pressed, int button_size); 155 float width, float height, Direction direction = Direction::None,
158 void DrawPlusButton(QPainter& p, QPointF center, bool pressed, int button_size); 156 float radius = 2);
159 void DrawGCButtonX(QPainter& p, QPointF center, bool pressed); 157 void DrawMinusButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
160 void DrawGCButtonY(QPainter& p, QPointF center, bool pressed); 158 int button_size);
161 void DrawGCButtonZ(QPainter& p, QPointF center, bool pressed); 159 void DrawPlusButton(QPainter& p, QPointF center, const Input::ButtonStatus& pressed,
160 int button_size);
161 void DrawGCButtonX(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
162 void DrawGCButtonY(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
163 void DrawGCButtonZ(QPainter& p, QPointF center, const Input::ButtonStatus& pressed);
162 void DrawArrowButtonOutline(QPainter& p, const QPointF center, float size = 1.0f); 164 void DrawArrowButtonOutline(QPainter& p, const QPointF center, float size = 1.0f);
163 void DrawArrowButton(QPainter& p, QPointF center, Direction direction, bool pressed, 165 void DrawArrowButton(QPainter& p, QPointF center, Direction direction,
164 float size = 1.0f); 166 const Input::ButtonStatus& pressed, float size = 1.0f);
165 void DrawTriggerButton(QPainter& p, QPointF center, Direction direction, bool pressed); 167 void DrawTriggerButton(QPainter& p, QPointF center, Direction direction,
168 const Input::ButtonStatus& pressed);
169
170 // Draw battery functions
171 void DrawBattery(QPainter& p, QPointF center, Input::BatteryLevel battery);
166 172
167 // Draw icon functions 173 // Draw icon functions
168 void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size); 174 void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size);
@@ -178,24 +184,23 @@ private:
178 void SetTextFont(QPainter& p, float text_size, 184 void SetTextFont(QPainter& p, float text_size,
179 const QString& font_family = QStringLiteral("sans-serif")); 185 const QString& font_family = QStringLiteral("sans-serif"));
180 186
181 using ButtonArray = 187 bool is_controller_set{};
182 std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::BUTTON_NS_END>; 188 bool is_connected{};
183 using StickArray = 189 bool needs_redraw{};
184 std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>; 190 Core::HID::NpadType controller_type;
185 191
186 ControllerCallback controller_callback;
187 bool is_enabled{};
188 bool mapping_active{}; 192 bool mapping_active{};
189 int blink_counter{}; 193 int blink_counter{};
194 int callback_key;
190 QColor button_color{}; 195 QColor button_color{};
191 ColorMapping colors{}; 196 ColorMapping colors{};
192 std::array<QColor, 4> led_color{}; 197 std::array<QColor, 4> led_color{};
193 ButtonArray buttons{};
194 StickArray sticks{};
195 std::size_t player_index{}; 198 std::size_t player_index{};
196 std::size_t button_mapping_index{Settings::NativeButton::BUTTON_NS_END}; 199 Core::HID::EmulatedController* controller;
197 std::size_t analog_mapping_index{Settings::NativeAnalog::NUM_STICKS_HID}; 200 std::size_t button_mapping_index{Settings::NativeButton::NumButtons};
198 std::array<AxisValue, Settings::NativeAnalog::NUM_STICKS_HID> axis_values{}; 201 std::size_t analog_mapping_index{Settings::NativeAnalog::NumAnalogs};
199 std::array<bool, Settings::NativeButton::NumButtons> button_values{}; 202 Core::HID::ButtonValues button_values{};
200 Settings::ControllerType controller_type{Settings::ControllerType::ProController}; 203 Core::HID::SticksValues stick_values{};
204 Core::HID::TriggerValues trigger_values{};
205 Core::HID::BatteryValues battery_values{};
201}; 206};
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index f8e08c422..9fd1a919f 100644
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -15,9 +15,9 @@
15 15
16#include "common/logging/log.h" 16#include "common/logging/log.h"
17#include "common/settings.h" 17#include "common/settings.h"
18#include "input_common/drivers/udp_client.h"
19#include "input_common/helpers/udp_protocol.h"
18#include "input_common/main.h" 20#include "input_common/main.h"
19#include "input_common/udp/client.h"
20#include "input_common/udp/udp.h"
21#include "ui_configure_motion_touch.h" 21#include "ui_configure_motion_touch.h"
22#include "yuzu/configuration/configure_motion_touch.h" 22#include "yuzu/configuration/configure_motion_touch.h"
23#include "yuzu/configuration/configure_touch_from_button.h" 23#include "yuzu/configuration/configure_touch_from_button.h"
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp
index 2af3afda8..1e7a3751d 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.cpp
+++ b/src/yuzu/configuration/configure_mouse_advanced.cpp
@@ -11,8 +11,11 @@
11 11
12#include "common/assert.h" 12#include "common/assert.h"
13#include "common/param_package.h" 13#include "common/param_package.h"
14#include "input_common/drivers/keyboard.h"
15#include "input_common/drivers/mouse.h"
14#include "input_common/main.h" 16#include "input_common/main.h"
15#include "ui_configure_mouse_advanced.h" 17#include "ui_configure_mouse_advanced.h"
18#include "yuzu/bootmanager.h"
16#include "yuzu/configuration/config.h" 19#include "yuzu/configuration/config.h"
17#include "yuzu/configuration/configure_mouse_advanced.h" 20#include "yuzu/configuration/configure_mouse_advanced.h"
18 21
@@ -101,7 +104,7 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent,
101 [=, this](const Common::ParamPackage& params) { 104 [=, this](const Common::ParamPackage& params) {
102 buttons_param[button_id] = params; 105 buttons_param[button_id] = params;
103 }, 106 },
104 InputCommon::Polling::DeviceType::Button); 107 InputCommon::Polling::InputType::Button);
105 }); 108 });
106 connect(button, &QPushButton::customContextMenuRequested, 109 connect(button, &QPushButton::customContextMenuRequested,
107 [=, this](const QPoint& menu_location) { 110 [=, this](const QPoint& menu_location) {
@@ -127,13 +130,10 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent,
127 connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); 130 connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
128 131
129 connect(poll_timer.get(), &QTimer::timeout, [this] { 132 connect(poll_timer.get(), &QTimer::timeout, [this] {
130 Common::ParamPackage params; 133 const auto& params = input_subsystem->GetNextInput();
131 for (auto& poller : device_pollers) { 134 if (params.Has("engine")) {
132 params = poller->GetNextInput(); 135 SetPollingResult(params, false);
133 if (params.Has("engine")) { 136 return;
134 SetPollingResult(params, false);
135 return;
136 }
137 } 137 }
138 }); 138 });
139 139
@@ -196,26 +196,13 @@ void ConfigureMouseAdvanced::UpdateButtonLabels() {
196 196
197void ConfigureMouseAdvanced::HandleClick( 197void ConfigureMouseAdvanced::HandleClick(
198 QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, 198 QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
199 InputCommon::Polling::DeviceType type) { 199 InputCommon::Polling::InputType type) {
200 button->setText(tr("[press key]")); 200 button->setText(tr("[press key]"));
201 button->setFocus(); 201 button->setFocus();
202 202
203 // Keyboard keys or mouse buttons can only be used as button devices
204 want_keyboard_mouse = type == InputCommon::Polling::DeviceType::Button;
205 if (want_keyboard_mouse) {
206 const auto iter = std::find(button_map.begin(), button_map.end(), button);
207 ASSERT(iter != button_map.end());
208 const auto index = std::distance(button_map.begin(), iter);
209 ASSERT(index < Settings::NativeButton::NumButtons && index >= 0);
210 }
211
212 input_setter = new_input_setter; 203 input_setter = new_input_setter;
213 204
214 device_pollers = input_subsystem->GetPollers(type); 205 input_subsystem->BeginMapping(type);
215
216 for (auto& poller : device_pollers) {
217 poller->Start();
218 }
219 206
220 QWidget::grabMouse(); 207 QWidget::grabMouse();
221 QWidget::grabKeyboard(); 208 QWidget::grabKeyboard();
@@ -227,9 +214,7 @@ void ConfigureMouseAdvanced::HandleClick(
227void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) { 214void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) {
228 timeout_timer->stop(); 215 timeout_timer->stop();
229 poll_timer->stop(); 216 poll_timer->stop();
230 for (auto& poller : device_pollers) { 217 input_subsystem->StopMapping();
231 poller->Stop();
232 }
233 218
234 QWidget::releaseMouse(); 219 QWidget::releaseMouse();
235 QWidget::releaseKeyboard(); 220 QWidget::releaseKeyboard();
@@ -247,15 +232,8 @@ void ConfigureMouseAdvanced::mousePressEvent(QMouseEvent* event) {
247 return; 232 return;
248 } 233 }
249 234
250 if (want_keyboard_mouse) { 235 const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
251 SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())}, 236 input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button);
252 false);
253 } else {
254 // We don't want any mouse buttons, so don't stop polling
255 return;
256 }
257
258 SetPollingResult({}, true);
259} 237}
260 238
261void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { 239void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) {
@@ -264,13 +242,6 @@ void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) {
264 } 242 }
265 243
266 if (event->key() != Qt::Key_Escape) { 244 if (event->key() != Qt::Key_Escape) {
267 if (want_keyboard_mouse) { 245 input_subsystem->GetKeyboard()->PressKey(event->key());
268 SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())},
269 false);
270 } else {
271 // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling
272 return;
273 }
274 } 246 }
275 SetPollingResult({}, true);
276} 247}
diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h
index 65b6fca9a..5fa534eaf 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.h
+++ b/src/yuzu/configuration/configure_mouse_advanced.h
@@ -46,7 +46,7 @@ private:
46 /// Called when the button was pressed. 46 /// Called when the button was pressed.
47 void HandleClick(QPushButton* button, 47 void HandleClick(QPushButton* button,
48 std::function<void(const Common::ParamPackage&)> new_input_setter, 48 std::function<void(const Common::ParamPackage&)> new_input_setter,
49 InputCommon::Polling::DeviceType type); 49 InputCommon::Polling::InputType type);
50 50
51 /// Finish polling and configure input using the input_setter 51 /// Finish polling and configure input using the input_setter
52 void SetPollingResult(const Common::ParamPackage& params, bool abort); 52 void SetPollingResult(const Common::ParamPackage& params, bool abort);
@@ -67,12 +67,6 @@ private:
67 std::array<QPushButton*, Settings::NativeMouseButton::NumMouseButtons> button_map; 67 std::array<QPushButton*, Settings::NativeMouseButton::NumMouseButtons> button_map;
68 std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons> buttons_param; 68 std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons> buttons_param;
69 69
70 std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
71
72 std::unique_ptr<QTimer> timeout_timer; 70 std::unique_ptr<QTimer> timeout_timer;
73 std::unique_ptr<QTimer> poll_timer; 71 std::unique_ptr<QTimer> poll_timer;
74
75 /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false,
76 /// keyboard events are ignored.
77 bool want_keyboard_mouse = false;
78}; 72};
diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp
index 40129f228..bde0a08c4 100644
--- a/src/yuzu/configuration/configure_touch_from_button.cpp
+++ b/src/yuzu/configuration/configure_touch_from_button.cpp
@@ -163,13 +163,10 @@ void ConfigureTouchFromButton::ConnectEvents() {
163 connect(timeout_timer.get(), &QTimer::timeout, [this]() { SetPollingResult({}, true); }); 163 connect(timeout_timer.get(), &QTimer::timeout, [this]() { SetPollingResult({}, true); });
164 164
165 connect(poll_timer.get(), &QTimer::timeout, [this]() { 165 connect(poll_timer.get(), &QTimer::timeout, [this]() {
166 Common::ParamPackage params; 166 const auto& params = input_subsystem->GetNextInput();
167 for (auto& poller : device_pollers) { 167 if (params.Has("engine")) {
168 params = poller->GetNextInput(); 168 SetPollingResult(params, false);
169 if (params.Has("engine")) { 169 return;
170 SetPollingResult(params, false);
171 return;
172 }
173 } 170 }
174 }); 171 });
175} 172}
@@ -248,11 +245,7 @@ void ConfigureTouchFromButton::GetButtonInput(const int row_index, const bool is
248 } 245 }
249 }; 246 };
250 247
251 device_pollers = input_subsystem->GetPollers(InputCommon::Polling::DeviceType::Button); 248 input_subsystem->BeginMapping(InputCommon::Polling::InputType::Button);
252
253 for (auto& poller : device_pollers) {
254 poller->Start();
255 }
256 249
257 grabKeyboard(); 250 grabKeyboard();
258 grabMouse(); 251 grabMouse();
@@ -365,14 +358,14 @@ void ConfigureTouchFromButton::SetCoordinates(const int dot_id, const QPoint& po
365 358
366void ConfigureTouchFromButton::SetPollingResult(const Common::ParamPackage& params, 359void ConfigureTouchFromButton::SetPollingResult(const Common::ParamPackage& params,
367 const bool cancel) { 360 const bool cancel) {
361 timeout_timer->stop();
362 poll_timer->stop();
363 input_subsystem->StopMapping();
364
368 releaseKeyboard(); 365 releaseKeyboard();
369 releaseMouse(); 366 releaseMouse();
370 qApp->restoreOverrideCursor(); 367 qApp->restoreOverrideCursor();
371 timeout_timer->stop(); 368
372 poll_timer->stop();
373 for (auto& poller : device_pollers) {
374 poller->Stop();
375 }
376 if (input_setter) { 369 if (input_setter) {
377 (*input_setter)(params, cancel); 370 (*input_setter)(params, cancel);
378 input_setter.reset(); 371 input_setter.reset();
diff --git a/src/yuzu/configuration/configure_touch_from_button.h b/src/yuzu/configuration/configure_touch_from_button.h
index d9513e3bc..e1400481a 100644
--- a/src/yuzu/configuration/configure_touch_from_button.h
+++ b/src/yuzu/configuration/configure_touch_from_button.h
@@ -24,10 +24,6 @@ namespace InputCommon {
24class InputSubsystem; 24class InputSubsystem;
25} 25}
26 26
27namespace InputCommon::Polling {
28class DevicePoller;
29}
30
31namespace Settings { 27namespace Settings {
32struct TouchFromButtonMap; 28struct TouchFromButtonMap;
33} 29}
@@ -85,7 +81,6 @@ private:
85 81
86 std::unique_ptr<QTimer> timeout_timer; 82 std::unique_ptr<QTimer> timeout_timer;
87 std::unique_ptr<QTimer> poll_timer; 83 std::unique_ptr<QTimer> poll_timer;
88 std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
89 std::optional<std::function<void(const Common::ParamPackage&, bool)>> input_setter; 84 std::optional<std::function<void(const Common::ParamPackage&, bool)>> input_setter;
90 85
91 static constexpr int DataRoleDot = Qt::ItemDataRole::UserRole + 2; 86 static constexpr int DataRoleDot = Qt::ItemDataRole::UserRole + 2;