summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2021-02-07 20:53:46 -0800
committerGravatar GitHub2021-02-07 20:53:46 -0800
commit089608909254dfa4860705a29a6c33f6872d85a5 (patch)
treec8f0924c8a9b67463883e405b2990005419ea619 /src
parentMerge pull request #5872 from lioncash/svc-error (diff)
parentAdd GC controller animation (diff)
downloadyuzu-089608909254dfa4860705a29a6c33f6872d85a5.tar.gz
yuzu-089608909254dfa4860705a29a6c33f6872d85a5.tar.xz
yuzu-089608909254dfa4860705a29a6c33f6872d85a5.zip
Merge pull request #5339 from german77/interactive
Settings: Make settings controller image change with controller input
Diffstat (limited to 'src')
-rw-r--r--src/core/frontend/input.h11
-rwxr-xr-xsrc/input_common/analog_from_button.cpp4
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp10
-rw-r--r--src/input_common/mouse/mouse_poller.cpp10
-rw-r--r--src/input_common/sdl/sdl_impl.cpp10
-rw-r--r--src/yuzu/CMakeLists.txt4
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp101
-rw-r--r--src/yuzu/configuration/configure_input_player.h2
-rw-r--r--src/yuzu/configuration/configure_input_player.ui74
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp2694
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.h192
-rw-r--r--src/yuzu/debugger/controller.cpp66
-rw-r--r--src/yuzu/debugger/controller.h31
-rw-r--r--src/yuzu/main.cpp7
-rw-r--r--src/yuzu/main.h2
15 files changed, 3143 insertions, 75 deletions
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h
index f014dfea3..88ebc6497 100644
--- a/src/core/frontend/input.h
+++ b/src/core/frontend/input.h
@@ -21,6 +21,11 @@ enum class AnalogDirection : u8 {
21 UP, 21 UP,
22 DOWN, 22 DOWN,
23}; 23};
24struct AnalogProperties {
25 float deadzone;
26 float range;
27 float threshold;
28};
24 29
25/// An abstract class template for an input device (a button, an analog input, etc.). 30/// An abstract class template for an input device (a button, an analog input, etc.).
26template <typename StatusType> 31template <typename StatusType>
@@ -30,6 +35,12 @@ public:
30 virtual StatusType GetStatus() const { 35 virtual StatusType GetStatus() const {
31 return {}; 36 return {};
32 } 37 }
38 virtual StatusType GetRawStatus() const {
39 return GetStatus();
40 }
41 virtual AnalogProperties GetAnalogProperties() const {
42 return {};
43 }
33 virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const { 44 virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const {
34 return {}; 45 return {};
35 } 46 }
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp
index 07a0fa4a1..770893687 100755
--- a/src/input_common/analog_from_button.cpp
+++ b/src/input_common/analog_from_button.cpp
@@ -139,6 +139,10 @@ public:
139 static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF)); 139 static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF));
140 } 140 }
141 141
142 Input::AnalogProperties GetAnalogProperties() const override {
143 return {modifier_scale, 1.0f, 0.5f};
144 }
145
142 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { 146 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
143 switch (direction) { 147 switch (direction) {
144 case Input::AnalogDirection::RIGHT: 148 case Input::AnalogDirection::RIGHT:
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp
index 9670bdeb2..1b6ded8d6 100644
--- a/src/input_common/gcadapter/gc_poller.cpp
+++ b/src/input_common/gcadapter/gc_poller.cpp
@@ -185,6 +185,16 @@ public:
185 return {0.0f, 0.0f}; 185 return {0.0f, 0.0f};
186 } 186 }
187 187
188 std::tuple<float, float> GetRawStatus() const override {
189 const float x = GetAxis(axis_x);
190 const float y = GetAxis(axis_y);
191 return {x, y};
192 }
193
194 Input::AnalogProperties GetAnalogProperties() const override {
195 return {deadzone, range, 0.5f};
196 }
197
188 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { 198 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
189 const auto [x, y] = GetStatus(); 199 const auto [x, y] = GetStatus();
190 const float directional_deadzone = 0.5f; 200 const float directional_deadzone = 0.5f;
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
index 508eb0c7d..3d799b293 100644
--- a/src/input_common/mouse/mouse_poller.cpp
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -106,6 +106,16 @@ public:
106 return {0.0f, 0.0f}; 106 return {0.0f, 0.0f};
107 } 107 }
108 108
109 std::tuple<float, float> GetRawStatus() const override {
110 const float x = GetAxis(axis_x);
111 const float y = GetAxis(axis_y);
112 return {x, y};
113 }
114
115 Input::AnalogProperties GetAnalogProperties() const override {
116 return {deadzone, range, 0.5f};
117 }
118
109private: 119private:
110 const u32 button; 120 const u32 button;
111 const u32 axis_x; 121 const u32 axis_x;
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index 1b5750937..f67de37e3 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -377,6 +377,16 @@ public:
377 return {}; 377 return {};
378 } 378 }
379 379
380 std::tuple<float, float> GetRawStatus() const override {
381 const float x = joystick->GetAxis(axis_x, range);
382 const float y = joystick->GetAxis(axis_y, range);
383 return {x, -y};
384 }
385
386 Input::AnalogProperties GetAnalogProperties() const override {
387 return {deadzone, range, 0.5f};
388 }
389
380 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { 390 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
381 const auto [x, y] = GetStatus(); 391 const auto [x, y] = GetStatus();
382 const float directional_deadzone = 0.5f; 392 const float directional_deadzone = 0.5f;
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index e1bab2112..fb9967c8f 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -71,6 +71,8 @@ add_executable(yuzu
71 configuration/configure_input_player.cpp 71 configuration/configure_input_player.cpp
72 configuration/configure_input_player.h 72 configuration/configure_input_player.h
73 configuration/configure_input_player.ui 73 configuration/configure_input_player.ui
74 configuration/configure_input_player_widget.cpp
75 configuration/configure_input_player_widget.h
74 configuration/configure_input_profile_dialog.cpp 76 configuration/configure_input_profile_dialog.cpp
75 configuration/configure_input_profile_dialog.h 77 configuration/configure_input_profile_dialog.h
76 configuration/configure_input_profile_dialog.ui 78 configuration/configure_input_profile_dialog.ui
@@ -115,6 +117,8 @@ add_executable(yuzu
115 configuration/input_profiles.h 117 configuration/input_profiles.h
116 debugger/console.cpp 118 debugger/console.cpp
117 debugger/console.h 119 debugger/console.h
120 debugger/controller.cpp
121 debugger/controller.h
118 debugger/profiler.cpp 122 debugger/profiler.cpp
119 debugger/profiler.h 123 debugger/profiler.h
120 debugger/wait_tree.cpp 124 debugger/wait_tree.cpp
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index b40d7c5e2..c9d19c948 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -23,6 +23,7 @@
23#include "ui_configure_input_player.h" 23#include "ui_configure_input_player.h"
24#include "yuzu/configuration/config.h" 24#include "yuzu/configuration/config.h"
25#include "yuzu/configuration/configure_input_player.h" 25#include "yuzu/configuration/configure_input_player.h"
26#include "yuzu/configuration/configure_input_player_widget.h"
26#include "yuzu/configuration/configure_vibration.h" 27#include "yuzu/configuration/configure_vibration.h"
27#include "yuzu/configuration/input_profiles.h" 28#include "yuzu/configuration/input_profiles.h"
28#include "yuzu/util/limitable_input_dialog.h" 29#include "yuzu/util/limitable_input_dialog.h"
@@ -254,11 +255,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
254 analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup}; 255 analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup};
255 analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange}; 256 analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange};
256 257
257 const auto ConfigureButtonClick = [&](QPushButton* button, Common::ParamPackage* param, 258 const auto ConfigureButtonClick = [&](QPushButton* button, std::size_t button_id,
258 int default_val, InputCommon::Polling::DeviceType type) { 259 Common::ParamPackage* param, int default_val,
260 InputCommon::Polling::DeviceType type) {
259 connect(button, &QPushButton::clicked, [=, this] { 261 connect(button, &QPushButton::clicked, [=, this] {
260 HandleClick( 262 HandleClick(
261 button, 263 button, button_id,
262 [=, this](Common::ParamPackage params) { 264 [=, this](Common::ParamPackage params) {
263 // Workaround for ZL & ZR for analog triggers like on XBOX 265 // Workaround for ZL & ZR for analog triggers like on XBOX
264 // controllers. Analog triggers (from controllers like the XBOX 266 // controllers. Analog triggers (from controllers like the XBOX
@@ -286,12 +288,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
286 continue; 288 continue;
287 } 289 }
288 290
289 ConfigureButtonClick(button_map[button_id], &buttons_param[button_id], 291 ConfigureButtonClick(button_map[button_id], button_id, &buttons_param[button_id],
290 Config::default_buttons[button_id], 292 Config::default_buttons[button_id],
291 InputCommon::Polling::DeviceType::Button); 293 InputCommon::Polling::DeviceType::Button);
292 294
293 button->setContextMenuPolicy(Qt::CustomContextMenu); 295 button->setContextMenuPolicy(Qt::CustomContextMenu);
294
295 connect(button, &QPushButton::customContextMenuRequested, 296 connect(button, &QPushButton::customContextMenuRequested,
296 [=, this](const QPoint& menu_location) { 297 [=, this](const QPoint& menu_location) {
297 QMenu context_menu; 298 QMenu context_menu;
@@ -300,6 +301,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
300 button_map[button_id]->setText(tr("[not set]")); 301 button_map[button_id]->setText(tr("[not set]"));
301 }); 302 });
302 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); 303 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
304 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
303 }); 305 });
304 } 306 }
305 307
@@ -309,7 +311,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
309 continue; 311 continue;
310 } 312 }
311 313
312 ConfigureButtonClick(motion_map[motion_id], &motions_param[motion_id], 314 ConfigureButtonClick(motion_map[motion_id], motion_id, &motions_param[motion_id],
313 Config::default_motions[motion_id], 315 Config::default_motions[motion_id],
314 InputCommon::Polling::DeviceType::Motion); 316 InputCommon::Polling::DeviceType::Motion);
315 317
@@ -348,7 +350,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
348 } 350 }
349 } 351 }
350 HandleClick( 352 HandleClick(
351 analog_map_buttons[analog_id][sub_button_id], 353 analog_map_buttons[analog_id][sub_button_id], analog_id,
352 [=, this](const Common::ParamPackage& params) { 354 [=, this](const Common::ParamPackage& params) {
353 SetAnalogParam(params, analogs_param[analog_id], 355 SetAnalogParam(params, analogs_param[analog_id],
354 analog_sub_buttons[sub_button_id]); 356 analog_sub_buttons[sub_button_id]);
@@ -358,41 +360,43 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
358 360
359 analog_button->setContextMenuPolicy(Qt::CustomContextMenu); 361 analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
360 362
361 connect(analog_button, &QPushButton::customContextMenuRequested, 363 connect(
362 [=, this](const QPoint& menu_location) { 364 analog_button, &QPushButton::customContextMenuRequested,
363 QMenu context_menu; 365 [=, this](const QPoint& menu_location) {
364 context_menu.addAction(tr("Clear"), [&] { 366 QMenu context_menu;
365 analogs_param[analog_id].Clear(); 367 context_menu.addAction(tr("Clear"), [&] {
366 analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); 368 analogs_param[analog_id].Clear();
367 }); 369 analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
368 context_menu.addAction(tr("Invert axis"), [&] { 370 });
369 if (sub_button_id == 2 || sub_button_id == 3) { 371 context_menu.addAction(tr("Invert axis"), [&] {
370 const bool invert_value = 372 if (sub_button_id == 2 || sub_button_id == 3) {
371 analogs_param[analog_id].Get("invert_x", "+") == "-"; 373 const bool invert_value =
372 const std::string invert_str = invert_value ? "+" : "-"; 374 analogs_param[analog_id].Get("invert_x", "+") == "-";
373 analogs_param[analog_id].Set("invert_x", invert_str); 375 const std::string invert_str = invert_value ? "+" : "-";
374 } 376 analogs_param[analog_id].Set("invert_x", invert_str);
375 if (sub_button_id == 0 || sub_button_id == 1) { 377 }
376 const bool invert_value = 378 if (sub_button_id == 0 || sub_button_id == 1) {
377 analogs_param[analog_id].Get("invert_y", "+") == "-"; 379 const bool invert_value =
378 const std::string invert_str = invert_value ? "+" : "-"; 380 analogs_param[analog_id].Get("invert_y", "+") == "-";
379 analogs_param[analog_id].Set("invert_y", invert_str); 381 const std::string invert_str = invert_value ? "+" : "-";
380 } 382 analogs_param[analog_id].Set("invert_y", invert_str);
381 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; 383 }
382 ++sub_button_id) { 384 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM;
383 analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( 385 ++sub_button_id) {
384 analogs_param[analog_id], analog_sub_buttons[sub_button_id])); 386 analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText(
385 } 387 analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
386 }); 388 }
387 context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(
388 menu_location));
389 }); 389 });
390 context_menu.exec(
391 analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(menu_location));
392 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
393 });
390 } 394 }
391 395
392 // Handle clicks for the modifier buttons as well. 396 // Handle clicks for the modifier buttons as well.
393 connect(analog_map_modifier_button[analog_id], &QPushButton::clicked, [=, this] { 397 connect(analog_map_modifier_button[analog_id], &QPushButton::clicked, [=, this] {
394 HandleClick( 398 HandleClick(
395 analog_map_modifier_button[analog_id], 399 analog_map_modifier_button[analog_id], analog_id,
396 [=, this](const Common::ParamPackage& params) { 400 [=, this](const Common::ParamPackage& params) {
397 analogs_param[analog_id].Set("modifier", params.Serialize()); 401 analogs_param[analog_id].Set("modifier", params.Serialize());
398 }, 402 },
@@ -416,12 +420,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
416 [=, this] { 420 [=, this] {
417 const auto spinbox_value = analog_map_range_spinbox[analog_id]->value(); 421 const auto spinbox_value = analog_map_range_spinbox[analog_id]->value();
418 analogs_param[analog_id].Set("range", spinbox_value / 100.0f); 422 analogs_param[analog_id].Set("range", spinbox_value / 100.0f);
423 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
419 }); 424 });
420 425
421 connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] { 426 connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] {
422 const auto slider_value = analog_map_deadzone_slider[analog_id]->value(); 427 const auto slider_value = analog_map_deadzone_slider[analog_id]->value();
423 analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value)); 428 analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value));
424 analogs_param[analog_id].Set("deadzone", slider_value / 100.0f); 429 analogs_param[analog_id].Set("deadzone", slider_value / 100.0f);
430 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
425 }); 431 });
426 432
427 connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] { 433 connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] {
@@ -433,8 +439,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
433 } 439 }
434 440
435 // Player Connected checkbox 441 // Player Connected checkbox
436 connect(ui->groupConnectedController, &QGroupBox::toggled, 442 connect(ui->groupConnectedController, &QGroupBox::toggled, [this](bool checked) {
437 [this](bool checked) { emit Connected(checked); }); 443 emit Connected(checked);
444 ui->controllerFrame->SetConnectedStatus(checked);
445 });
438 446
439 if (player_index == 0) { 447 if (player_index == 0) {
440 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), 448 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged),
@@ -553,6 +561,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
553 561
554 // TODO(wwylele): enable this when we actually emulate it 562 // TODO(wwylele): enable this when we actually emulate it
555 ui->buttonHome->setEnabled(false); 563 ui->buttonHome->setEnabled(false);
564 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
565 ui->controllerFrame->SetConnectedStatus(ui->groupConnectedController->isChecked());
556} 566}
557 567
558ConfigureInputPlayer::~ConfigureInputPlayer() = default; 568ConfigureInputPlayer::~ConfigureInputPlayer() = default;
@@ -875,6 +885,7 @@ void ConfigureInputPlayer::UpdateUI() {
875 modifier_label->setVisible(!is_controller); 885 modifier_label->setVisible(!is_controller);
876 modifier_slider->setVisible(!is_controller); 886 modifier_slider->setVisible(!is_controller);
877 range_groupbox->setVisible(is_controller); 887 range_groupbox->setVisible(is_controller);
888 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
878 } 889 }
879} 890}
880 891
@@ -991,8 +1002,8 @@ void ConfigureInputPlayer::UpdateControllerIcon() {
991 return QString{}; 1002 return QString{};
992 } 1003 }
993 }(); 1004 }();
994 1005 ui->controllerFrame->SetControllerType(
995 ui->controllerFrame->setStyleSheet(stylesheet.arg(theme)); 1006 GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()));
996} 1007}
997 1008
998void ConfigureInputPlayer::UpdateControllerAvailableButtons() { 1009void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
@@ -1129,7 +1140,8 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
1129} 1140}
1130 1141
1131void ConfigureInputPlayer::HandleClick( 1142void ConfigureInputPlayer::HandleClick(
1132 QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, 1143 QPushButton* button, std::size_t button_id,
1144 std::function<void(const Common::ParamPackage&)> new_input_setter,
1133 InputCommon::Polling::DeviceType type) { 1145 InputCommon::Polling::DeviceType type) {
1134 if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) { 1146 if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {
1135 button->setText(tr("Shake!")); 1147 button->setText(tr("Shake!"));
@@ -1173,6 +1185,12 @@ void ConfigureInputPlayer::HandleClick(
1173 input_subsystem->GetMouseTouch()->BeginConfiguration(); 1185 input_subsystem->GetMouseTouch()->BeginConfiguration();
1174 } 1186 }
1175 1187
1188 if (type == InputCommon::Polling::DeviceType::Button) {
1189 ui->controllerFrame->BeginMappingButton(button_id);
1190 } else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) {
1191 ui->controllerFrame->BeginMappingAnalog(button_id);
1192 }
1193
1176 timeout_timer->start(2500); // Cancel after 2.5 seconds 1194 timeout_timer->start(2500); // Cancel after 2.5 seconds
1177 poll_timer->start(50); // Check for new inputs every 50ms 1195 poll_timer->start(50); // Check for new inputs every 50ms
1178} 1196}
@@ -1203,6 +1221,7 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params,
1203 1221
1204 UpdateUI(); 1222 UpdateUI();
1205 UpdateInputDeviceCombobox(); 1223 UpdateInputDeviceCombobox();
1224 ui->controllerFrame->EndMapping();
1206 1225
1207 input_setter = std::nullopt; 1226 input_setter = std::nullopt;
1208} 1227}
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index c4ae50de7..da2b89136 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -106,7 +106,7 @@ private:
106 void LoadConfiguration(); 106 void LoadConfiguration();
107 107
108 /// Called when the button was pressed. 108 /// Called when the button was pressed.
109 void HandleClick(QPushButton* button, 109 void HandleClick(QPushButton* button, std::size_t button_id,
110 std::function<void(const Common::ParamPackage&)> new_input_setter, 110 std::function<void(const Common::ParamPackage&)> new_input_setter,
111 InputCommon::Polling::DeviceType type); 111 InputCommon::Polling::DeviceType type);
112 112
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
index 1e78b4c10..e76aa484f 100644
--- a/src/yuzu/configuration/configure_input_player.ui
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -1964,39 +1964,39 @@
1964 </item> 1964 </item>
1965 </layout> 1965 </layout>
1966 </item> 1966 </item>
1967 <item> 1967 <item>
1968 <widget class="QFrame" name="controllerFrame"> 1968 <widget class="PlayerControlPreview" name="controllerFrame">
1969 <property name="sizePolicy"> 1969 <property name="sizePolicy">
1970 <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> 1970 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1971 <horstretch>0</horstretch> 1971 <horstretch>0</horstretch>
1972 <verstretch>0</verstretch> 1972 <verstretch>0</verstretch>
1973 </sizepolicy> 1973 </sizepolicy>
1974 </property> 1974 </property>
1975 <property name="font"> 1975 <property name="font">
1976 <font> 1976 <font>
1977 <weight>75</weight> 1977 <weight>75</weight>
1978 <bold>true</bold> 1978 <bold>true</bold>
1979 </font> 1979 </font>
1980 </property> 1980 </property>
1981 <property name="styleSheet"> 1981 <property name="styleSheet">
1982 <string notr="true">image: url(:/controller/pro);</string> 1982 <string notr="true">image: url(:/controller/pro);</string>
1983 </property> 1983 </property>
1984 <layout class="QVBoxLayout" name="verticalLayout_4"> 1984 <layout class="QVBoxLayout" name="verticalLayout_4">
1985 <property name="leftMargin"> 1985 <property name="leftMargin">
1986 <number>0</number> 1986 <number>0</number>
1987 </property> 1987 </property>
1988 <property name="topMargin"> 1988 <property name="topMargin">
1989 <number>0</number> 1989 <number>0</number>
1990 </property> 1990 </property>
1991 <property name="rightMargin"> 1991 <property name="rightMargin">
1992 <number>0</number> 1992 <number>0</number>
1993 </property> 1993 </property>
1994 <property name="bottomMargin"> 1994 <property name="bottomMargin">
1995 <number>0</number> 1995 <number>0</number>
1996 </property> 1996 </property>
1997 </layout> 1997 </layout>
1998 </widget> 1998 </widget>
1999 </item> 1999 </item>
2000 <item> 2000 <item>
2001 <layout class="QHBoxLayout" name="miscButtons"> 2001 <layout class="QHBoxLayout" name="miscButtons">
2002 <property name="spacing"> 2002 <property name="spacing">
@@ -3087,6 +3087,14 @@
3087 </item> 3087 </item>
3088 </layout> 3088 </layout>
3089 </widget> 3089 </widget>
3090 <customwidgets>
3091 <customwidget>
3092 <class>PlayerControlPreview</class>
3093 <extends>QFrame</extends>
3094 <header>yuzu/configuration/configure_input_player_widget.h</header>
3095 <container>1</container>
3096 </customwidget>
3097 </customwidgets>
3090 <resources> 3098 <resources>
3091 <include location="../../../dist/icons/controller/controller.qrc"/> 3099 <include location="../../../dist/icons/controller/controller.qrc"/>
3092 </resources> 3100 </resources>
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
new file mode 100644
index 000000000..e3e8bde48
--- /dev/null
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -0,0 +1,2694 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <QMenu>
7#include <QPainter>
8#include <QTimer>
9#include "yuzu/configuration/configure_input_player_widget.h"
10
11PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) {
12 UpdateColors();
13 QTimer* timer = new QTimer(this);
14 connect(timer, &QTimer::timeout, this, QOverload<>::of(&PlayerControlPreview::UpdateInput));
15
16 // refresh at 60hz
17 timer->start(16);
18}
19
20PlayerControlPreview::~PlayerControlPreview() = default;
21
22void PlayerControlPreview::SetPlayerInput(std::size_t index, const ButtonParam& buttons_param,
23 const AnalogParam& analogs_param) {
24 player_index = index;
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, const Settings::ButtonsRaw buttons_,
41 Settings::AnalogsRaw analogs_) {
42 player_index = index;
43 std::transform(buttons_.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
44 buttons_.begin() + Settings::NativeButton::BUTTON_NS_END, buttons.begin(),
45 Input::CreateDevice<Input::ButtonDevice>);
46 std::transform(analogs_.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
47 analogs_.begin() + Settings::NativeAnalog::STICK_HID_END, sticks.begin(),
48 Input::CreateDevice<Input::AnalogDevice>);
49 UpdateColors();
50}
51
52PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size_t index,
53 bool player_on) {
54 if (!player_on) {
55 return {0, 0, 0, 0};
56 }
57
58 switch (index) {
59 case 0:
60 return {1, 0, 0, 0};
61 case 1:
62 return {1, 1, 0, 0};
63 case 2:
64 return {1, 1, 1, 0};
65 case 3:
66 return {1, 1, 1, 1};
67 case 4:
68 return {1, 0, 0, 1};
69 case 5:
70 return {1, 0, 1, 0};
71 case 6:
72 return {1, 0, 1, 1};
73 case 7:
74 return {0, 1, 1, 0};
75 default:
76 return {0, 0, 0, 0};
77 }
78}
79
80void PlayerControlPreview::SetConnectedStatus(bool checked) {
81 LedPattern led_pattern = GetColorPattern(player_index, checked);
82
83 led_color[0] = led_pattern.position1 ? colors.led_on : colors.led_off;
84 led_color[1] = led_pattern.position2 ? colors.led_on : colors.led_off;
85 led_color[2] = led_pattern.position3 ? colors.led_on : colors.led_off;
86 led_color[3] = led_pattern.position4 ? colors.led_on : colors.led_off;
87}
88
89void PlayerControlPreview::SetControllerType(const Settings::ControllerType type) {
90 controller_type = type;
91 UpdateColors();
92}
93
94void PlayerControlPreview::BeginMappingButton(std::size_t index) {
95 button_mapping_index = index;
96 mapping_active = true;
97}
98
99void PlayerControlPreview::BeginMappingAnalog(std::size_t index) {
100 button_mapping_index = Settings::NativeButton::LStick + index;
101 analog_mapping_index = index;
102 mapping_active = true;
103}
104
105void PlayerControlPreview::EndMapping() {
106 button_mapping_index = Settings::NativeButton::BUTTON_NS_END;
107 analog_mapping_index = Settings::NativeAnalog::NumAnalogs;
108 mapping_active = false;
109 blink_counter = 0;
110}
111
112void PlayerControlPreview::UpdateColors() {
113 if (QIcon::themeName().contains(QStringLiteral("dark")) ||
114 QIcon::themeName().contains(QStringLiteral("midnight"))) {
115 colors.primary = QColor(204, 204, 204);
116 colors.button = QColor(35, 38, 41);
117 colors.button2 = QColor(26, 27, 30);
118 colors.slider_arrow = QColor(14, 15, 18);
119 colors.font2 = QColor(255, 255, 255);
120 colors.indicator = QColor(170, 238, 255);
121 colors.deadzone = QColor(204, 136, 136);
122 colors.slider_button = colors.button;
123 }
124
125 if (QIcon::themeName().contains(QStringLiteral("dark"))) {
126 colors.outline = QColor(160, 160, 160);
127 } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
128 colors.outline = QColor(145, 145, 145);
129 } else {
130 colors.outline = QColor(0, 0, 0);
131 colors.primary = QColor(225, 225, 225);
132 colors.button = QColor(109, 111, 114);
133 colors.button2 = QColor(109, 111, 114);
134 colors.button2 = QColor(77, 80, 84);
135 colors.slider_arrow = QColor(65, 68, 73);
136 colors.font2 = QColor(0, 0, 0);
137 colors.indicator = QColor(0, 0, 200);
138 colors.deadzone = QColor(170, 0, 0);
139 colors.slider_button = QColor(153, 149, 149);
140 }
141
142 // Constant colors
143 colors.highlight = QColor(170, 0, 0);
144 colors.highlight2 = QColor(119, 0, 0);
145 colors.slider = QColor(103, 106, 110);
146 colors.transparent = QColor(0, 0, 0, 0);
147 colors.font = QColor(255, 255, 255);
148 colors.led_on = QColor(255, 255, 0);
149 colors.led_off = QColor(170, 238, 255);
150
151 colors.left = colors.primary;
152 colors.right = colors.primary;
153 // Possible alternative to set colors from settings
154 // colors.left = QColor(Settings::values.players.GetValue()[player_index].body_color_left);
155 // colors.right = QColor(Settings::values.players.GetValue()[player_index].body_color_right);
156}
157
158void PlayerControlPreview::UpdateInput() {
159 bool input_changed = false;
160 const auto& button_state = buttons;
161 for (std::size_t index = 0; index < button_values.size(); ++index) {
162 bool value = false;
163 if (index < Settings::NativeButton::BUTTON_NS_END) {
164 value = button_state[index]->GetStatus();
165 }
166 bool blink = mapping_active && index == button_mapping_index;
167 if (analog_mapping_index == Settings::NativeAnalog::NUM_STICKS_HID) {
168 blink &= blink_counter > 25;
169 }
170 if (button_values[index] != value || blink) {
171 input_changed = true;
172 }
173 button_values[index] = value || blink;
174 }
175
176 const auto& analog_state = sticks;
177 for (std::size_t index = 0; index < axis_values.size(); ++index) {
178 const auto [stick_x_f, stick_y_f] = analog_state[index]->GetStatus();
179 const auto [stick_x_rf, stick_y_rf] = analog_state[index]->GetRawStatus();
180
181 if (static_cast<int>(stick_x_rf * 45) !=
182 static_cast<int>(axis_values[index].raw_value.x() * 45) ||
183 static_cast<int>(-stick_y_rf * 45) !=
184 static_cast<int>(axis_values[index].raw_value.y() * 45)) {
185 input_changed = true;
186 }
187
188 axis_values[index].properties = analog_state[index]->GetAnalogProperties();
189 axis_values[index].value = QPointF(stick_x_f, -stick_y_f);
190 axis_values[index].raw_value = QPointF(stick_x_rf, -stick_y_rf);
191
192 const bool blink_analog = mapping_active && index == analog_mapping_index;
193 if (blink_analog) {
194 input_changed = true;
195 axis_values[index].value =
196 QPointF(blink_counter < 25 ? -blink_counter / 25.0f : 0,
197 blink_counter > 25 ? -(blink_counter - 25) / 25.0f : 0);
198 }
199 }
200
201 if (input_changed) {
202 update();
203 }
204
205 if (mapping_active) {
206 blink_counter = (blink_counter + 1) % 50;
207 }
208}
209
210void PlayerControlPreview::paintEvent(QPaintEvent* event) {
211 QFrame::paintEvent(event);
212 QPainter p(this);
213 p.setRenderHint(QPainter::Antialiasing);
214 const QPointF center = rect().center();
215
216 switch (controller_type) {
217 case Settings::ControllerType::Handheld:
218 DrawHandheldController(p, center);
219 break;
220 case Settings::ControllerType::DualJoyconDetached:
221 DrawDualController(p, center);
222 break;
223 case Settings::ControllerType::LeftJoycon:
224 DrawLeftController(p, center);
225 break;
226 case Settings::ControllerType::RightJoycon:
227 DrawRightController(p, center);
228 break;
229 case Settings::ControllerType::ProController:
230 default:
231 DrawProController(p, center);
232 break;
233 }
234}
235
236void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) {
237 {
238 using namespace Settings::NativeButton;
239
240 // Sideview left joystick
241 DrawJoystickSideview(p, center + QPoint(142, -69),
242 -axis_values[Settings::NativeAnalog::LStick].value.y(), 1.15f,
243 button_values[LStick]);
244
245 // Topview D-pad buttons
246 p.setPen(colors.outline);
247 button_color = colors.button;
248 DrawRoundButton(p, center + QPoint(-163, -21), button_values[DLeft], 11, 5, Direction::Up);
249 DrawRoundButton(p, center + QPoint(-117, -21), button_values[DRight], 11, 5, Direction::Up);
250
251 // Topview left joystick
252 DrawJoystickSideview(p, center + QPointF(-140.5f, -28),
253 -axis_values[Settings::NativeAnalog::LStick].value.x() + 15.0f, 1.15f,
254 button_values[LStick]);
255
256 // Topview minus button
257 p.setPen(colors.outline);
258 button_color = colors.button;
259 DrawRoundButton(p, center + QPoint(-111, -22), button_values[Minus], 8, 4, Direction::Up,
260 1);
261
262 // Left trigger
263 DrawLeftTriggers(p, center, button_values[L]);
264 DrawRoundButton(p, center + QPoint(151, -146), button_values[L], 8, 4, Direction::Down);
265 DrawLeftZTriggers(p, center, button_values[ZL]);
266
267 // Sideview D-pad buttons
268 DrawRoundButton(p, center + QPoint(135, 14), button_values[DLeft], 5, 11, Direction::Right);
269 DrawRoundButton(p, center + QPoint(135, 36), button_values[DDown], 5, 11, Direction::Right);
270 DrawRoundButton(p, center + QPoint(135, -10), button_values[DUp], 5, 11, Direction::Right);
271 DrawRoundButton(p, center + QPoint(135, 14), button_values[DRight], 5, 11,
272 Direction::Right);
273 DrawRoundButton(p, center + QPoint(135, 71), button_values[Screenshot], 3, 8,
274 Direction::Right, 1);
275
276 // Sideview minus button
277 DrawRoundButton(p, center + QPoint(135, -118), button_values[Minus], 4, 2.66f,
278 Direction::Right, 1);
279
280 // Sideview SL and SR buttons
281 button_color = colors.slider_button;
282 DrawRoundButton(p, center + QPoint(59, 52), button_values[SR], 5, 12, Direction::Left);
283 DrawRoundButton(p, center + QPoint(59, -69), button_values[SL], 5, 12, Direction::Left);
284
285 DrawLeftBody(p, center);
286
287 // Left trigger top view
288 DrawLeftTriggersTopView(p, center, button_values[L]);
289 DrawLeftZTriggersTopView(p, center, button_values[ZL]);
290 }
291
292 {
293 // Draw joysticks
294 using namespace Settings::NativeAnalog;
295 DrawJoystick(p, center + QPointF(9, -69) + (axis_values[LStick].value * 8), 1.8f,
296 button_values[Settings::NativeButton::LStick]);
297 DrawRawJoystick(p, center + QPointF(-140, 90), axis_values[LStick].raw_value,
298 axis_values[LStick].properties);
299 }
300
301 using namespace Settings::NativeButton;
302
303 // D-pad constants
304 const QPointF dpad_center = center + QPoint(9, 14);
305 constexpr int dpad_distance = 23;
306 constexpr int dpad_radius = 11;
307 constexpr float dpad_arrow_size = 1.2f;
308
309 // D-pad buttons
310 p.setPen(colors.outline);
311 button_color = colors.button;
312 DrawCircleButton(p, dpad_center + QPoint(dpad_distance, 0), button_values[DRight], dpad_radius);
313 DrawCircleButton(p, dpad_center + QPoint(0, dpad_distance), button_values[DDown], dpad_radius);
314 DrawCircleButton(p, dpad_center + QPoint(0, -dpad_distance), button_values[DUp], dpad_radius);
315 DrawCircleButton(p, dpad_center + QPoint(-dpad_distance, 0), button_values[DLeft], dpad_radius);
316
317 // D-pad arrows
318 p.setPen(colors.font2);
319 p.setBrush(colors.font2);
320 DrawArrow(p, dpad_center + QPoint(dpad_distance, 0), Direction::Right, dpad_arrow_size);
321 DrawArrow(p, dpad_center + QPoint(0, dpad_distance), Direction::Down, dpad_arrow_size);
322 DrawArrow(p, dpad_center + QPoint(0, -dpad_distance), Direction::Up, dpad_arrow_size);
323 DrawArrow(p, dpad_center + QPoint(-dpad_distance, 0), Direction::Left, dpad_arrow_size);
324
325 // SR and SL buttons
326 p.setPen(colors.outline);
327 button_color = colors.slider_button;
328 DrawRoundButton(p, center + QPoint(155, 52), button_values[SR], 5.2f, 12, Direction::None, 4);
329 DrawRoundButton(p, center + QPoint(155, -69), button_values[SL], 5.2f, 12, Direction::None, 4);
330
331 // SR and SL text
332 p.setPen(colors.transparent);
333 p.setBrush(colors.font2);
334 DrawSymbol(p, center + QPointF(155, 52), Symbol::SR, 1.0f);
335 DrawSymbol(p, center + QPointF(155, -69), Symbol::SL, 1.0f);
336
337 // Minus button
338 button_color = colors.button;
339 DrawMinusButton(p, center + QPoint(39, -118), button_values[Minus], 16);
340
341 // Screenshot button
342 DrawRoundButton(p, center + QPoint(26, 71), button_values[Screenshot], 8, 8);
343 p.setPen(colors.font2);
344 p.setBrush(colors.font2);
345 DrawCircle(p, center + QPoint(26, 71), 5);
346}
347
348void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) {
349 {
350 using namespace Settings::NativeButton;
351
352 // Sideview right joystick
353 DrawJoystickSideview(p, center + QPoint(173 - 315, 11),
354 axis_values[Settings::NativeAnalog::RStick].value.y() + 10.0f, 1.15f,
355 button_values[Settings::NativeButton::RStick]);
356
357 // Topview face buttons
358 p.setPen(colors.outline);
359 button_color = colors.button;
360 DrawRoundButton(p, center + QPoint(163, -21), button_values[A], 11, 5, Direction::Up);
361 DrawRoundButton(p, center + QPoint(117, -21), button_values[Y], 11, 5, Direction::Up);
362
363 // Topview right joystick
364 DrawJoystickSideview(p, center + QPointF(140, -28),
365 -axis_values[Settings::NativeAnalog::RStick].value.x() + 15.0f, 1.15f,
366 button_values[RStick]);
367
368 // Topview plus button
369 p.setPen(colors.outline);
370 button_color = colors.button;
371 DrawRoundButton(p, center + QPoint(111, -22), button_values[Plus], 8, 4, Direction::Up, 1);
372 DrawRoundButton(p, center + QPoint(111, -22), button_values[Plus], 2.66f, 4, Direction::Up,
373 1);
374
375 // Right trigger
376 p.setPen(colors.outline);
377 button_color = colors.button;
378 DrawRightTriggers(p, center, button_values[R]);
379 DrawRoundButton(p, center + QPoint(-151, -146), button_values[R], 8, 4, Direction::Down);
380 DrawRightZTriggers(p, center, button_values[ZR]);
381
382 // Sideview face buttons
383 DrawRoundButton(p, center + QPoint(-135, -73), button_values[A], 5, 11, Direction::Left);
384 DrawRoundButton(p, center + QPoint(-135, -50), button_values[B], 5, 11, Direction::Left);
385 DrawRoundButton(p, center + QPoint(-135, -95), button_values[X], 5, 11, Direction::Left);
386 DrawRoundButton(p, center + QPoint(-135, -73), button_values[Y], 5, 11, Direction::Left);
387
388 // Sideview home and plus button
389 DrawRoundButton(p, center + QPoint(-135, 66), button_values[Home], 3, 12, Direction::Left);
390 DrawRoundButton(p, center + QPoint(-135, -118), button_values[Plus], 4, 8, Direction::Left,
391 1);
392 DrawRoundButton(p, center + QPoint(-135, -118), button_values[Plus], 4, 2.66f,
393 Direction::Left, 1);
394
395 // Sideview SL and SR buttons
396 button_color = colors.slider_button;
397 DrawRoundButton(p, center + QPoint(-59, 52), button_values[SL], 5, 11, Direction::Right);
398 DrawRoundButton(p, center + QPoint(-59, -69), button_values[SR], 5, 11, Direction::Right);
399
400 DrawRightBody(p, center);
401
402 // Right trigger top view
403 DrawRightTriggersTopView(p, center, button_values[R]);
404 DrawRightZTriggersTopView(p, center, button_values[ZR]);
405 }
406
407 {
408 // Draw joysticks
409 using namespace Settings::NativeAnalog;
410 DrawJoystick(p, center + QPointF(-9, 11) + (axis_values[RStick].value * 8), 1.8f,
411 button_values[Settings::NativeButton::RStick]);
412 DrawRawJoystick(p, center + QPointF(140, 90), axis_values[RStick].raw_value,
413 axis_values[RStick].properties);
414 }
415
416 using namespace Settings::NativeButton;
417
418 // Face buttons constants
419 const QPointF face_center = center + QPoint(-9, -73);
420 constexpr int face_distance = 23;
421 constexpr int face_radius = 11;
422 constexpr float text_size = 1.1f;
423
424 // Face buttons
425 p.setPen(colors.outline);
426 button_color = colors.button;
427 DrawCircleButton(p, face_center + QPoint(face_distance, 0), button_values[A], face_radius);
428 DrawCircleButton(p, face_center + QPoint(0, face_distance), button_values[B], face_radius);
429 DrawCircleButton(p, face_center + QPoint(0, -face_distance), button_values[X], face_radius);
430 DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius);
431
432 // Face buttons text
433 p.setPen(colors.transparent);
434 p.setBrush(colors.font);
435 DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size);
436 DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size);
437 DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size);
438 DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size);
439
440 // SR and SL buttons
441 p.setPen(colors.outline);
442 button_color = colors.slider_button;
443 DrawRoundButton(p, center + QPoint(-155, 52), button_values[SL], 5, 12, Direction::None, 4.0f);
444 DrawRoundButton(p, center + QPoint(-155, -69), button_values[SR], 5, 12, Direction::None, 4.0f);
445
446 // SR and SL text
447 p.setPen(colors.transparent);
448 p.setBrush(colors.font2);
449 p.rotate(-180);
450 DrawSymbol(p, QPointF(-center.x(), -center.y()) + QPointF(155, 69), Symbol::SR, 1.0f);
451 DrawSymbol(p, QPointF(-center.x(), -center.y()) + QPointF(155, -52), Symbol::SL, 1.0f);
452 p.rotate(180);
453
454 // Plus Button
455 DrawPlusButton(p, center + QPoint(-40, -118), button_values[Plus], 16);
456
457 // Home Button
458 p.setPen(colors.outline);
459 button_color = colors.slider_button;
460 DrawCircleButton(p, center + QPoint(-26, 66), button_values[Home], 12);
461 button_color = colors.button;
462 DrawCircleButton(p, center + QPoint(-26, 66), button_values[Home], 9);
463 p.setPen(colors.transparent);
464 p.setBrush(colors.font2);
465 DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5);
466}
467
468void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) {
469 {
470 using namespace Settings::NativeButton;
471
472 // Left/Right trigger
473 DrawDualTriggers(p, center, button_values[L], button_values[R]);
474
475 // Topview face buttons
476 p.setPen(colors.outline);
477 button_color = colors.button;
478 DrawRoundButton(p, center + QPoint(200, -71), button_values[A], 10, 5, Direction::Up);
479 DrawRoundButton(p, center + QPoint(160, -71), button_values[Y], 10, 5, Direction::Up);
480
481 // Topview right joystick
482 DrawJoystickSideview(p, center + QPointF(180, -78),
483 -axis_values[Settings::NativeAnalog::RStick].value.x() + 15.0f, 1,
484 button_values[RStick]);
485
486 // Topview plus button
487 p.setPen(colors.outline);
488 button_color = colors.button;
489 DrawRoundButton(p, center + QPoint(154, -72), button_values[Plus], 7, 4, Direction::Up, 1);
490 DrawRoundButton(p, center + QPoint(154, -72), button_values[Plus], 2.33f, 4, Direction::Up,
491 1);
492
493 // Topview D-pad buttons
494 p.setPen(colors.outline);
495 button_color = colors.button;
496 DrawRoundButton(p, center + QPoint(-200, -71), button_values[DLeft], 10, 5, Direction::Up);
497 DrawRoundButton(p, center + QPoint(-160, -71), button_values[DRight], 10, 5, Direction::Up);
498
499 // Topview left joystick
500 DrawJoystickSideview(p, center + QPointF(-180.5f, -78),
501 -axis_values[Settings::NativeAnalog::LStick].value.x() + 15.0f, 1,
502 button_values[LStick]);
503
504 // Topview minus button
505 p.setPen(colors.outline);
506 button_color = colors.button;
507 DrawRoundButton(p, center + QPoint(-154, -72), button_values[Minus], 7, 4, Direction::Up,
508 1);
509
510 DrawDualBody(p, center);
511
512 // Right trigger top view
513 DrawDualTriggersTopView(p, center, button_values[L], button_values[R]);
514 DrawDualZTriggersTopView(p, center, button_values[ZL], button_values[ZR]);
515 }
516
517 {
518 // Draw joysticks
519 using namespace Settings::NativeAnalog;
520 DrawJoystick(p, center + QPointF(-65, -65) + (axis_values[LStick].value * 7), 1.62f,
521 button_values[Settings::NativeButton::LStick]);
522 DrawJoystick(p, center + QPointF(65, 12) + (axis_values[RStick].value * 7), 1.62f,
523 button_values[Settings::NativeButton::RStick]);
524 DrawRawJoystick(p, center + QPointF(-180, 90), axis_values[LStick].raw_value,
525 axis_values[LStick].properties);
526 DrawRawJoystick(p, center + QPointF(180, 90), axis_values[RStick].raw_value,
527 axis_values[RStick].properties);
528 }
529
530 using namespace Settings::NativeButton;
531
532 // Face buttons constants
533 const QPointF face_center = center + QPoint(65, -65);
534 constexpr int face_distance = 20;
535 constexpr int face_radius = 10;
536 constexpr float text_size = 1.0f;
537
538 // Face buttons
539 p.setPen(colors.outline);
540 button_color = colors.button;
541 DrawCircleButton(p, face_center + QPoint(face_distance, 0), button_values[A], face_radius);
542 DrawCircleButton(p, face_center + QPoint(0, face_distance), button_values[B], face_radius);
543 DrawCircleButton(p, face_center + QPoint(0, -face_distance), button_values[X], face_radius);
544 DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius);
545
546 // Face buttons text
547 p.setPen(colors.transparent);
548 p.setBrush(colors.font);
549 DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size);
550 DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size);
551 DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size);
552 DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size);
553
554 // D-pad constants
555 const QPointF dpad_center = center + QPoint(-65, 12);
556 constexpr int dpad_distance = 20;
557 constexpr int dpad_radius = 10;
558 constexpr float dpad_arrow_size = 1.1f;
559
560 // D-pad buttons
561 p.setPen(colors.outline);
562 button_color = colors.button;
563 DrawCircleButton(p, dpad_center + QPoint(dpad_distance, 0), button_values[DRight], dpad_radius);
564 DrawCircleButton(p, dpad_center + QPoint(0, dpad_distance), button_values[DDown], dpad_radius);
565 DrawCircleButton(p, dpad_center + QPoint(0, -dpad_distance), button_values[DUp], dpad_radius);
566 DrawCircleButton(p, dpad_center + QPoint(-dpad_distance, 0), button_values[DLeft], dpad_radius);
567
568 // D-pad arrows
569 p.setPen(colors.font2);
570 p.setBrush(colors.font2);
571 DrawArrow(p, dpad_center + QPoint(dpad_distance, 0), Direction::Right, dpad_arrow_size);
572 DrawArrow(p, dpad_center + QPoint(0, dpad_distance), Direction::Down, dpad_arrow_size);
573 DrawArrow(p, dpad_center + QPoint(0, -dpad_distance), Direction::Up, dpad_arrow_size);
574 DrawArrow(p, dpad_center + QPoint(-dpad_distance, 0), Direction::Left, dpad_arrow_size);
575
576 // Minus and Plus button
577 button_color = colors.button;
578 DrawMinusButton(p, center + QPoint(-39, -106), button_values[Minus], 14);
579 DrawPlusButton(p, center + QPoint(39, -106), button_values[Plus], 14);
580
581 // Screenshot button
582 p.setPen(colors.outline);
583 DrawRoundButton(p, center + QPoint(-52, 63), button_values[Screenshot], 8, 8);
584 p.setPen(colors.font2);
585 p.setBrush(colors.font2);
586 DrawCircle(p, center + QPoint(-52, 63), 5);
587
588 // Home Button
589 p.setPen(colors.outline);
590 button_color = colors.slider_button;
591 DrawCircleButton(p, center + QPoint(50, 60), button_values[Home], 11);
592 button_color = colors.button;
593 DrawCircleButton(p, center + QPoint(50, 60), button_values[Home], 8.5f);
594 p.setPen(colors.transparent);
595 p.setBrush(colors.font2);
596 DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f);
597}
598
599void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) {
600 DrawHandheldTriggers(p, center, button_values[Settings::NativeButton::L],
601 button_values[Settings::NativeButton::R]);
602 DrawHandheldBody(p, center);
603 {
604 // Draw joysticks
605 using namespace Settings::NativeAnalog;
606 DrawJoystick(p, center + QPointF(-171, -41) + (axis_values[LStick].value * 4), 1.0f,
607 button_values[Settings::NativeButton::LStick]);
608 DrawJoystick(p, center + QPointF(171, 8) + (axis_values[RStick].value * 4), 1.0f,
609 button_values[Settings::NativeButton::RStick]);
610 DrawRawJoystick(p, center + QPointF(-50, 0), axis_values[LStick].raw_value,
611 axis_values[LStick].properties);
612 DrawRawJoystick(p, center + QPointF(50, 0), axis_values[RStick].raw_value,
613 axis_values[RStick].properties);
614 }
615
616 using namespace Settings::NativeButton;
617
618 // Face buttons constants
619 const QPointF face_center = center + QPoint(171, -41);
620 constexpr float face_distance = 12.8f;
621 constexpr float face_radius = 6.4f;
622 constexpr float text_size = 0.6f;
623
624 // Face buttons
625 p.setPen(colors.outline);
626 button_color = colors.button;
627 DrawCircleButton(p, face_center + QPoint(face_distance, 0), button_values[A], face_radius);
628 DrawCircleButton(p, face_center + QPoint(0, face_distance), button_values[B], face_radius);
629 DrawCircleButton(p, face_center + QPoint(0, -face_distance), button_values[X], face_radius);
630 DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius);
631
632 // Face buttons text
633 p.setPen(colors.transparent);
634 p.setBrush(colors.font);
635 DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size);
636 DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size);
637 DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size);
638 DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size);
639
640 // D-pad constants
641 const QPointF dpad_center = center + QPoint(-171, 8);
642 constexpr float dpad_distance = 12.8f;
643 constexpr float dpad_radius = 6.4f;
644 constexpr float dpad_arrow_size = 0.68f;
645
646 // D-pad buttons
647 p.setPen(colors.outline);
648 button_color = colors.button;
649 DrawCircleButton(p, dpad_center + QPoint(dpad_distance, 0), button_values[DRight], dpad_radius);
650 DrawCircleButton(p, dpad_center + QPoint(0, dpad_distance), button_values[DDown], dpad_radius);
651 DrawCircleButton(p, dpad_center + QPoint(0, -dpad_distance), button_values[DUp], dpad_radius);
652 DrawCircleButton(p, dpad_center + QPoint(-dpad_distance, 0), button_values[DLeft], dpad_radius);
653
654 // D-pad arrows
655 p.setPen(colors.font2);
656 p.setBrush(colors.font2);
657 DrawArrow(p, dpad_center + QPoint(dpad_distance, 0), Direction::Right, dpad_arrow_size);
658 DrawArrow(p, dpad_center + QPoint(0, dpad_distance), Direction::Down, dpad_arrow_size);
659 DrawArrow(p, dpad_center + QPoint(0, -dpad_distance), Direction::Up, dpad_arrow_size);
660 DrawArrow(p, dpad_center + QPoint(-dpad_distance, 0), Direction::Left, dpad_arrow_size);
661
662 // ZL and ZR buttons
663 p.setPen(colors.outline);
664 DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]);
665 DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]);
666 p.setPen(colors.transparent);
667 p.setBrush(colors.font);
668 DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f);
669 DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f);
670
671 // Minus and Plus button
672 p.setPen(colors.outline);
673 button_color = colors.button;
674 DrawMinusButton(p, center + QPoint(-155, -67), button_values[Minus], 8);
675 DrawPlusButton(p, center + QPoint(155, -67), button_values[Plus], 8);
676
677 // Screenshot button
678 p.setPen(colors.outline);
679 DrawRoundButton(p, center + QPoint(-162, 39), button_values[Screenshot], 5, 5);
680 p.setPen(colors.font2);
681 p.setBrush(colors.font2);
682 DrawCircle(p, center + QPoint(-162, 39), 3);
683
684 // Home Button
685 p.setPen(colors.outline);
686 button_color = colors.slider_button;
687 DrawCircleButton(p, center + QPoint(161, 37), button_values[Home], 7);
688 button_color = colors.button;
689 DrawCircleButton(p, center + QPoint(161, 37), button_values[Home], 5);
690 p.setPen(colors.transparent);
691 p.setBrush(colors.font2);
692 DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f);
693}
694
695void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) {
696 DrawProTriggers(p, center, button_values[Settings::NativeButton::L],
697 button_values[Settings::NativeButton::R]);
698 DrawProBody(p, center);
699 {
700 // Draw joysticks
701 using namespace Settings::NativeAnalog;
702 DrawProJoystick(p, center + QPointF(-111, -55) + (axis_values[LStick].value * 11),
703 button_values[Settings::NativeButton::LStick]);
704 DrawProJoystick(p, center + QPointF(51, 0) + (axis_values[RStick].value * 11),
705 button_values[Settings::NativeButton::RStick]);
706 DrawRawJoystick(p, center + QPointF(-50, 105), axis_values[LStick].raw_value,
707 axis_values[LStick].properties);
708 DrawRawJoystick(p, center + QPointF(50, 105), axis_values[RStick].raw_value,
709 axis_values[RStick].properties);
710 }
711
712 using namespace Settings::NativeButton;
713
714 // Face buttons constants
715 const QPointF face_center = center + QPoint(105, -56);
716 constexpr int face_distance = 31;
717 constexpr int face_radius = 15;
718 constexpr float text_size = 1.5f;
719
720 // Face buttons
721 p.setPen(colors.outline);
722 button_color = colors.button;
723 DrawCircleButton(p, face_center + QPoint(face_distance, 0), button_values[A], face_radius);
724 DrawCircleButton(p, face_center + QPoint(0, face_distance), button_values[B], face_radius);
725 DrawCircleButton(p, face_center + QPoint(0, -face_distance), button_values[X], face_radius);
726 DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius);
727
728 // Face buttons text
729 p.setPen(colors.transparent);
730 p.setBrush(colors.font);
731 DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size);
732 DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size);
733 DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size);
734 DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size);
735
736 // D-pad buttons
737 const QPointF dpad_postion = center + QPoint(-61, 0);
738 DrawArrowButton(p, dpad_postion, Direction::Up, button_values[DUp]);
739 DrawArrowButton(p, dpad_postion, Direction::Left, button_values[DLeft]);
740 DrawArrowButton(p, dpad_postion, Direction::Right, button_values[DRight]);
741 DrawArrowButton(p, dpad_postion, Direction::Down, button_values[DDown]);
742 DrawArrowButtonOutline(p, dpad_postion);
743
744 // ZL and ZR buttons
745 p.setPen(colors.outline);
746 DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]);
747 DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]);
748 p.setPen(colors.transparent);
749 p.setBrush(colors.font);
750 DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f);
751 DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f);
752
753 // Minus and Plus buttons
754 p.setPen(colors.outline);
755 DrawCircleButton(p, center + QPoint(-50, -86), button_values[Minus], 9);
756 DrawCircleButton(p, center + QPoint(50, -86), button_values[Plus], 9);
757
758 // Minus and Plus symbols
759 p.setPen(colors.font2);
760 p.setBrush(colors.font2);
761 DrawRectangle(p, center + QPoint(-50, -86), 9, 1.5f);
762 DrawRectangle(p, center + QPoint(50, -86), 9, 1.5f);
763 DrawRectangle(p, center + QPoint(50, -86), 1.5f, 9);
764
765 // Screenshot button
766 p.setPen(colors.outline);
767 DrawRoundButton(p, center + QPoint(-29, -56), button_values[Screenshot], 7, 7);
768 p.setPen(colors.font2);
769 p.setBrush(colors.font2);
770 DrawCircle(p, center + QPoint(-29, -56), 4.5f);
771
772 // Home Button
773 p.setPen(colors.outline);
774 button_color = colors.slider_button;
775 DrawCircleButton(p, center + QPoint(29, -56), button_values[Home], 10.0f);
776 button_color = colors.button;
777 DrawCircleButton(p, center + QPoint(29, -56), button_values[Home], 7.1f);
778 p.setPen(colors.transparent);
779 p.setBrush(colors.font2);
780 DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);
781}
782
783void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
784 DrawGCTriggers(p, center, button_values[Settings::NativeButton::ZL],
785 button_values[Settings::NativeButton::ZR]);
786 DrawGCButtonZ(p, center, button_values[Settings::NativeButton::R]);
787 DrawGCBody(p, center);
788 {
789 // Draw joysticks
790 using namespace Settings::NativeAnalog;
791 DrawGCJoystick(p, center + QPointF(-111, -44) + (axis_values[LStick].value * 10), false);
792 button_color = colors.button2;
793 DrawCircleButton(p, center + QPointF(61, 37) + (axis_values[RStick].value * 9.5f), false,
794 15);
795 p.setPen(colors.transparent);
796 p.setBrush(colors.font);
797 DrawSymbol(p, center + QPointF(61, 37) + (axis_values[RStick].value * 9.5f), Symbol::C,
798 1.0f);
799 DrawRawJoystick(p, center + QPointF(-198, -125), axis_values[LStick].raw_value,
800 axis_values[LStick].properties);
801 DrawRawJoystick(p, center + QPointF(198, -125), axis_values[RStick].raw_value,
802 axis_values[RStick].properties);
803 }
804
805 using namespace Settings::NativeButton;
806
807 // Face buttons constants
808 constexpr float text_size = 1.1f;
809
810 // Face buttons
811 p.setPen(colors.outline);
812 button_color = colors.button;
813 DrawCircleButton(p, center + QPoint(111, -44), button_values[A], 21);
814 DrawCircleButton(p, center + QPoint(70, -23), button_values[B], 13);
815 DrawGCButtonX(p, center, button_values[Settings::NativeButton::X]);
816 DrawGCButtonY(p, center, button_values[Settings::NativeButton::Y]);
817
818 // Face buttons text
819 p.setPen(colors.transparent);
820 p.setBrush(colors.font);
821 DrawSymbol(p, center + QPoint(111, -44), Symbol::A, 1.5f);
822 DrawSymbol(p, center + QPoint(70, -23), Symbol::B, text_size);
823 DrawSymbol(p, center + QPoint(151, -53), Symbol::X, text_size);
824 DrawSymbol(p, center + QPoint(100, -83), Symbol::Y, text_size);
825
826 // D-pad buttons
827 const QPointF dpad_postion = center + QPoint(-61, 37);
828 const float dpad_size = 0.8f;
829 DrawArrowButton(p, dpad_postion, Direction::Up, button_values[DUp], dpad_size);
830 DrawArrowButton(p, dpad_postion, Direction::Left, button_values[DLeft], dpad_size);
831 DrawArrowButton(p, dpad_postion, Direction::Right, button_values[DRight], dpad_size);
832 DrawArrowButton(p, dpad_postion, Direction::Down, button_values[DDown], dpad_size);
833 DrawArrowButtonOutline(p, dpad_postion, dpad_size);
834
835 // Minus and Plus buttons
836 p.setPen(colors.outline);
837 DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8);
838}
839
840constexpr std::array<float, 13 * 2> symbol_a = {
841 -1.085f, -5.2f, 1.085f, -5.2f, 5.085f, 5.0f, 2.785f, 5.0f, 1.785f,
842 2.65f, -1.785f, 2.65f, -2.785f, 5.0f, -5.085f, 5.0f, -1.4f, 1.0f,
843 0.0f, -2.8f, 1.4f, 1.0f, -1.4f, 1.0f, -5.085f, 5.0f,
844};
845constexpr std::array<float, 134 * 2> symbol_b = {
846 -4.0f, 0.0f, -4.0f, 0.0f, -4.0f, -0.1f, -3.8f, -5.1f, 1.8f, -5.0f, 2.3f, -4.9f, 2.6f,
847 -4.8f, 2.8f, -4.7f, 2.9f, -4.6f, 3.1f, -4.5f, 3.2f, -4.4f, 3.4f, -4.3f, 3.4f, -4.2f,
848 3.5f, -4.1f, 3.7f, -4.0f, 3.7f, -3.9f, 3.8f, -3.8f, 3.8f, -3.7f, 3.9f, -3.6f, 3.9f,
849 -3.5f, 4.0f, -3.4f, 4.0f, -3.3f, 4.1f, -3.1f, 4.1f, -3.0f, 4.0f, -2.0f, 4.0f, -1.9f,
850 3.9f, -1.7f, 3.9f, -1.6f, 3.8f, -1.5f, 3.8f, -1.4f, 3.7f, -1.3f, 3.7f, -1.2f, 3.6f,
851 -1.1f, 3.6f, -1.0f, 3.5f, -0.9f, 3.3f, -0.8f, 3.3f, -0.7f, 3.2f, -0.6f, 3.0f, -0.5f,
852 2.9f, -0.4f, 2.7f, -0.3f, 2.9f, -0.2f, 3.2f, -0.1f, 3.3f, 0.0f, 3.5f, 0.1f, 3.6f,
853 0.2f, 3.8f, 0.3f, 3.9f, 0.4f, 4.0f, 0.6f, 4.1f, 0.7f, 4.3f, 0.8f, 4.3f, 0.9f,
854 4.4f, 1.0f, 4.4f, 1.1f, 4.5f, 1.3f, 4.5f, 1.4f, 4.6f, 1.6f, 4.6f, 1.7f, 4.5f,
855 2.8f, 4.5f, 2.9f, 4.4f, 3.1f, 4.4f, 3.2f, 4.3f, 3.4f, 4.3f, 3.5f, 4.2f, 3.6f,
856 4.2f, 3.7f, 4.1f, 3.8f, 4.1f, 3.9f, 4.0f, 4.0f, 3.9f, 4.2f, 3.8f, 4.3f, 3.6f,
857 4.4f, 3.6f, 4.5f, 3.4f, 4.6f, 3.3f, 4.7f, 3.1f, 4.8f, 2.8f, 4.9f, 2.6f, 5.0f,
858 2.1f, 5.1f, -4.0f, 5.0f, -4.0f, 4.9f,
859
860 -4.0f, 0.0f, 1.1f, 3.4f, 1.1f, 3.4f, 1.5f, 3.3f, 1.8f, 3.2f, 2.0f, 3.1f, 2.1f,
861 3.0f, 2.3f, 2.9f, 2.3f, 2.8f, 2.4f, 2.7f, 2.4f, 2.6f, 2.5f, 2.3f, 2.5f, 2.2f,
862 2.4f, 1.7f, 2.4f, 1.6f, 2.3f, 1.4f, 2.3f, 1.3f, 2.2f, 1.2f, 2.2f, 1.1f, 2.1f,
863 1.0f, 1.9f, 0.9f, 1.6f, 0.8f, 1.4f, 0.7f, -1.9f, 0.6f, -1.9f, 0.7f, -1.8f, 3.4f,
864 1.1f, 3.4f, -4.0f, 0.0f,
865
866 0.3f, -1.1f, 0.3f, -1.1f, 1.3f, -1.2f, 1.5f, -1.3f, 1.8f, -1.4f, 1.8f, -1.5f, 1.9f,
867 -1.6f, 2.0f, -1.8f, 2.0f, -1.9f, 2.1f, -2.0f, 2.1f, -2.1f, 2.0f, -2.7f, 2.0f, -2.8f,
868 1.9f, -2.9f, 1.9f, -3.0f, 1.8f, -3.1f, 1.6f, -3.2f, 1.6f, -3.3f, 1.3f, -3.4f, -1.9f,
869 -3.3f, -1.9f, -3.2f, -1.8f, -1.0f, 0.2f, -1.1f, 0.3f, -1.1f, -4.0f, 0.0f,
870};
871
872constexpr std::array<float, 9 * 2> symbol_y = {
873 -4.79f, -4.9f, -2.44f, -4.9f, 0.0f, -0.9f, 2.44f, -4.9f, 4.79f,
874 -4.9f, 1.05f, 1.0f, 1.05f, 5.31f, -1.05f, 5.31f, -1.05f, 1.0f,
875
876};
877
878constexpr std::array<float, 12 * 2> symbol_x = {
879 -4.4f, -5.0f, -2.0f, -5.0f, 0.0f, -1.7f, 2.0f, -5.0f, 4.4f, -5.0f, 1.2f, 0.0f,
880 4.4f, 5.0f, 2.0f, 5.0f, 0.0f, 1.7f, -2.0f, 5.0f, -4.4f, 5.0f, -1.2f, 0.0f,
881
882};
883
884constexpr std::array<float, 7 * 2> symbol_l = {
885 2.4f, -3.23f, 2.4f, 2.1f, 5.43f, 2.1f, 5.43f, 3.22f, 0.98f, 3.22f, 0.98f, -3.23f, 2.4f, -3.23f,
886};
887
888constexpr std::array<float, 98 * 2> symbol_r = {
889 1.0f, 0.0f, 1.0f, -0.1f, 1.1f, -3.3f, 4.3f, -3.2f, 5.1f, -3.1f, 5.4f, -3.0f, 5.6f, -2.9f,
890 5.7f, -2.8f, 5.9f, -2.7f, 5.9f, -2.6f, 6.0f, -2.5f, 6.1f, -2.3f, 6.2f, -2.2f, 6.2f, -2.1f,
891 6.3f, -2.0f, 6.3f, -1.9f, 6.2f, -0.8f, 6.2f, -0.7f, 6.1f, -0.6f, 6.1f, -0.5f, 6.0f, -0.4f,
892 6.0f, -0.3f, 5.9f, -0.2f, 5.7f, -0.1f, 5.7f, 0.0f, 5.6f, 0.1f, 5.4f, 0.2f, 5.1f, 0.3f,
893 4.7f, 0.4f, 4.7f, 0.5f, 4.9f, 0.6f, 5.0f, 0.7f, 5.2f, 0.8f, 5.2f, 0.9f, 5.3f, 1.0f,
894 5.5f, 1.1f, 5.5f, 1.2f, 5.6f, 1.3f, 5.7f, 1.5f, 5.8f, 1.6f, 5.9f, 1.8f, 6.0f, 1.9f,
895 6.1f, 2.1f, 6.2f, 2.2f, 6.2f, 2.3f, 6.3f, 2.4f, 6.4f, 2.6f, 6.5f, 2.7f, 6.6f, 2.9f,
896 6.7f, 3.0f, 6.7f, 3.1f, 6.8f, 3.2f, 6.8f, 3.3f, 5.3f, 3.2f, 5.2f, 3.1f, 5.2f, 3.0f,
897 5.1f, 2.9f, 5.0f, 2.7f, 4.9f, 2.6f, 4.8f, 2.4f, 4.7f, 2.3f, 4.6f, 2.1f, 4.5f, 2.0f,
898 4.4f, 1.8f, 4.3f, 1.7f, 4.1f, 1.4f, 4.0f, 1.3f, 3.9f, 1.1f, 3.8f, 1.0f, 3.6f, 0.9f,
899 3.6f, 0.8f, 3.5f, 0.7f, 3.3f, 0.6f, 2.9f, 0.5f, 2.3f, 0.6f, 2.3f, 0.7f, 2.2f, 3.3f,
900 1.0f, 3.2f, 1.0f, 3.1f, 1.0f, 0.0f,
901
902 4.2f, -0.5f, 4.4f, -0.6f, 4.7f, -0.7f, 4.8f, -0.8f, 4.9f, -1.0f, 5.0f, -1.1f, 5.0f, -1.2f,
903 4.9f, -1.7f, 4.9f, -1.8f, 4.8f, -1.9f, 4.8f, -2.0f, 4.6f, -2.1f, 4.3f, -2.2f, 2.3f, -2.1f,
904 2.3f, -2.0f, 2.4f, -0.5f, 4.2f, -0.5f, 1.0f, 0.0f,
905};
906
907constexpr std::array<float, 18 * 2> symbol_zl = {
908 -2.6f, -2.13f, -5.6f, -2.13f, -5.6f, -3.23f, -0.8f, -3.23f, -0.8f, -2.13f, -4.4f, 2.12f,
909 -0.7f, 2.12f, -0.7f, 3.22f, -6.0f, 3.22f, -6.0f, 2.12f, 2.4f, -3.23f, 2.4f, 2.1f,
910 5.43f, 2.1f, 5.43f, 3.22f, 0.98f, 3.22f, 0.98f, -3.23f, 2.4f, -3.23f, -6.0f, 2.12f,
911};
912
913constexpr std::array<float, 57 * 2> symbol_sl = {
914 -3.0f, -3.65f, -2.76f, -4.26f, -2.33f, -4.76f, -1.76f, -5.09f, -1.13f, -5.26f, -0.94f,
915 -4.77f, -0.87f, -4.11f, -1.46f, -3.88f, -1.91f, -3.41f, -2.05f, -2.78f, -1.98f, -2.13f,
916 -1.59f, -1.61f, -0.96f, -1.53f, -0.56f, -2.04f, -0.38f, -2.67f, -0.22f, -3.31f, 0.0f,
917 -3.93f, 0.34f, -4.49f, 0.86f, -4.89f, 1.49f, -5.05f, 2.14f, -4.95f, 2.69f, -4.6f,
918 3.07f, -4.07f, 3.25f, -3.44f, 3.31f, -2.78f, 3.25f, -2.12f, 3.07f, -1.49f, 2.7f,
919 -0.95f, 2.16f, -0.58f, 1.52f, -0.43f, 1.41f, -0.99f, 1.38f, -1.65f, 1.97f, -1.91f,
920 2.25f, -2.49f, 2.25f, -3.15f, 1.99f, -3.74f, 1.38f, -3.78f, 1.06f, -3.22f, 0.88f,
921 -2.58f, 0.71f, -1.94f, 0.49f, -1.32f, 0.13f, -0.77f, -0.4f, -0.4f, -1.04f, -0.25f,
922 -1.69f, -0.32f, -2.28f, -0.61f, -2.73f, -1.09f, -2.98f, -1.69f, -3.09f, -2.34f,
923
924 3.23f, 2.4f, -2.1f, 2.4f, -2.1f, 5.43f, -3.22f, 5.43f, -3.22f, 0.98f, 3.23f,
925 0.98f, 3.23f, 2.4f, -3.09f, -2.34f,
926};
927constexpr std::array<float, 109 * 2> symbol_zr = {
928 -2.6f, -2.13f, -5.6f, -2.13f, -5.6f, -3.23f, -0.8f, -3.23f, -0.8f, -2.13f, -4.4f, 2.12f, -0.7f,
929 2.12f, -0.7f, 3.22f, -6.0f, 3.22f, -6.0f, 2.12f,
930
931 1.0f, 0.0f, 1.0f, -0.1f, 1.1f, -3.3f, 4.3f, -3.2f, 5.1f, -3.1f, 5.4f, -3.0f, 5.6f,
932 -2.9f, 5.7f, -2.8f, 5.9f, -2.7f, 5.9f, -2.6f, 6.0f, -2.5f, 6.1f, -2.3f, 6.2f, -2.2f,
933 6.2f, -2.1f, 6.3f, -2.0f, 6.3f, -1.9f, 6.2f, -0.8f, 6.2f, -0.7f, 6.1f, -0.6f, 6.1f,
934 -0.5f, 6.0f, -0.4f, 6.0f, -0.3f, 5.9f, -0.2f, 5.7f, -0.1f, 5.7f, 0.0f, 5.6f, 0.1f,
935 5.4f, 0.2f, 5.1f, 0.3f, 4.7f, 0.4f, 4.7f, 0.5f, 4.9f, 0.6f, 5.0f, 0.7f, 5.2f,
936 0.8f, 5.2f, 0.9f, 5.3f, 1.0f, 5.5f, 1.1f, 5.5f, 1.2f, 5.6f, 1.3f, 5.7f, 1.5f,
937 5.8f, 1.6f, 5.9f, 1.8f, 6.0f, 1.9f, 6.1f, 2.1f, 6.2f, 2.2f, 6.2f, 2.3f, 6.3f,
938 2.4f, 6.4f, 2.6f, 6.5f, 2.7f, 6.6f, 2.9f, 6.7f, 3.0f, 6.7f, 3.1f, 6.8f, 3.2f,
939 6.8f, 3.3f, 5.3f, 3.2f, 5.2f, 3.1f, 5.2f, 3.0f, 5.1f, 2.9f, 5.0f, 2.7f, 4.9f,
940 2.6f, 4.8f, 2.4f, 4.7f, 2.3f, 4.6f, 2.1f, 4.5f, 2.0f, 4.4f, 1.8f, 4.3f, 1.7f,
941 4.1f, 1.4f, 4.0f, 1.3f, 3.9f, 1.1f, 3.8f, 1.0f, 3.6f, 0.9f, 3.6f, 0.8f, 3.5f,
942 0.7f, 3.3f, 0.6f, 2.9f, 0.5f, 2.3f, 0.6f, 2.3f, 0.7f, 2.2f, 3.3f, 1.0f, 3.2f,
943 1.0f, 3.1f, 1.0f, 0.0f,
944
945 4.2f, -0.5f, 4.4f, -0.6f, 4.7f, -0.7f, 4.8f, -0.8f, 4.9f, -1.0f, 5.0f, -1.1f, 5.0f,
946 -1.2f, 4.9f, -1.7f, 4.9f, -1.8f, 4.8f, -1.9f, 4.8f, -2.0f, 4.6f, -2.1f, 4.3f, -2.2f,
947 2.3f, -2.1f, 2.3f, -2.0f, 2.4f, -0.5f, 4.2f, -0.5f, 1.0f, 0.0f, -6.0f, 2.12f,
948};
949
950constexpr std::array<float, 148 * 2> symbol_sr = {
951 -3.0f, -3.65f, -2.76f, -4.26f, -2.33f, -4.76f, -1.76f, -5.09f, -1.13f, -5.26f, -0.94f, -4.77f,
952 -0.87f, -4.11f, -1.46f, -3.88f, -1.91f, -3.41f, -2.05f, -2.78f, -1.98f, -2.13f, -1.59f, -1.61f,
953 -0.96f, -1.53f, -0.56f, -2.04f, -0.38f, -2.67f, -0.22f, -3.31f, 0.0f, -3.93f, 0.34f, -4.49f,
954 0.86f, -4.89f, 1.49f, -5.05f, 2.14f, -4.95f, 2.69f, -4.6f, 3.07f, -4.07f, 3.25f, -3.44f,
955 3.31f, -2.78f, 3.25f, -2.12f, 3.07f, -1.49f, 2.7f, -0.95f, 2.16f, -0.58f, 1.52f, -0.43f,
956 1.41f, -0.99f, 1.38f, -1.65f, 1.97f, -1.91f, 2.25f, -2.49f, 2.25f, -3.15f, 1.99f, -3.74f,
957 1.38f, -3.78f, 1.06f, -3.22f, 0.88f, -2.58f, 0.71f, -1.94f, 0.49f, -1.32f, 0.13f, -0.77f,
958 -0.4f, -0.4f, -1.04f, -0.25f, -1.69f, -0.32f, -2.28f, -0.61f, -2.73f, -1.09f, -2.98f, -1.69f,
959 -3.09f, -2.34f,
960
961 -1.0f, 0.0f, 0.1f, 1.0f, 3.3f, 1.1f, 3.2f, 4.3f, 3.1f, 5.1f, 3.0f, 5.4f,
962 2.9f, 5.6f, 2.8f, 5.7f, 2.7f, 5.9f, 2.6f, 5.9f, 2.5f, 6.0f, 2.3f, 6.1f,
963 2.2f, 6.2f, 2.1f, 6.2f, 2.0f, 6.3f, 1.9f, 6.3f, 0.8f, 6.2f, 0.7f, 6.2f,
964 0.6f, 6.1f, 0.5f, 6.1f, 0.4f, 6.0f, 0.3f, 6.0f, 0.2f, 5.9f, 0.1f, 5.7f,
965 0.0f, 5.7f, -0.1f, 5.6f, -0.2f, 5.4f, -0.3f, 5.1f, -0.4f, 4.7f, -0.5f, 4.7f,
966 -0.6f, 4.9f, -0.7f, 5.0f, -0.8f, 5.2f, -0.9f, 5.2f, -1.0f, 5.3f, -1.1f, 5.5f,
967 -1.2f, 5.5f, -1.3f, 5.6f, -1.5f, 5.7f, -1.6f, 5.8f, -1.8f, 5.9f, -1.9f, 6.0f,
968 -2.1f, 6.1f, -2.2f, 6.2f, -2.3f, 6.2f, -2.4f, 6.3f, -2.6f, 6.4f, -2.7f, 6.5f,
969 -2.9f, 6.6f, -3.0f, 6.7f, -3.1f, 6.7f, -3.2f, 6.8f, -3.3f, 6.8f, -3.2f, 5.3f,
970 -3.1f, 5.2f, -3.0f, 5.2f, -2.9f, 5.1f, -2.7f, 5.0f, -2.6f, 4.9f, -2.4f, 4.8f,
971 -2.3f, 4.7f, -2.1f, 4.6f, -2.0f, 4.5f, -1.8f, 4.4f, -1.7f, 4.3f, -1.4f, 4.1f,
972 -1.3f, 4.0f, -1.1f, 3.9f, -1.0f, 3.8f, -0.9f, 3.6f, -0.8f, 3.6f, -0.7f, 3.5f,
973 -0.6f, 3.3f, -0.5f, 2.9f, -0.6f, 2.3f, -0.7f, 2.3f, -3.3f, 2.2f, -3.2f, 1.0f,
974 -3.1f, 1.0f, 0.0f, 1.0f,
975
976 0.5f, 4.2f, 0.6f, 4.4f, 0.7f, 4.7f, 0.8f, 4.8f, 1.0f, 4.9f, 1.1f, 5.0f,
977 1.2f, 5.0f, 1.7f, 4.9f, 1.8f, 4.9f, 1.9f, 4.8f, 2.0f, 4.8f, 2.1f, 4.6f,
978 2.2f, 4.3f, 2.1f, 2.3f, 2.0f, 2.3f, 0.5f, 2.4f, 0.5f, 4.2f, -0.0f, 1.0f,
979 -3.09f, -2.34f,
980
981};
982
983constexpr std::array<float, 30 * 2> symbol_c = {
984 2.86f, 7.57f, 0.99f, 7.94f, -0.91f, 7.87f, -2.73f, 7.31f, -4.23f, 6.14f, -5.2f, 4.51f,
985 -5.65f, 2.66f, -5.68f, 0.75f, -5.31f, -1.12f, -4.43f, -2.81f, -3.01f, -4.08f, -1.24f, -4.78f,
986 0.66f, -4.94f, 2.54f, -4.67f, 4.33f, -4.0f, 4.63f, -2.27f, 3.37f, -2.7f, 1.6f, -3.4f,
987 -0.3f, -3.5f, -2.09f, -2.87f, -3.34f, -1.45f, -3.91f, 0.37f, -3.95f, 2.27f, -3.49f, 4.12f,
988 -2.37f, 5.64f, -0.65f, 6.44f, 1.25f, 6.47f, 3.06f, 5.89f, 4.63f, 4.92f, 4.63f, 6.83f,
989};
990
991constexpr std::array<float, 12 * 2> house = {
992 -1.3f, 0.0f, -0.93f, 0.0f, -0.93f, 1.15f, 0.93f, 1.15f, 0.93f, 0.0f, 1.3f, 0.0f,
993 0.0f, -1.2f, -1.3f, 0.0f, -0.43f, 0.0f, -0.43f, .73f, 0.43f, .73f, 0.43f, 0.0f,
994};
995
996constexpr std::array<float, 11 * 2> up_arrow_button = {
997 9.1f, -9.1f, 9.1f, -30.0f, 8.1f, -30.1f, 7.7f, -30.1f, -8.6f, -30.0f, -9.0f,
998 -29.8f, -9.3f, -29.5f, -9.5f, -29.1f, -9.1f, -28.7f, -9.1f, -9.1f, 0.0f, 0.6f,
999};
1000
1001constexpr std::array<float, 3 * 2> up_arrow_symbol = {
1002 0.0f, -3.0f, -3.0f, 2.0f, 3.0f, 2.0f,
1003};
1004
1005constexpr std::array<float, 13 * 2> up_arrow = {
1006 9.4f, -9.8f, 9.4f, -10.2f, 8.9f, -29.8f, 8.5f, -30.0f, 8.1f,
1007 -30.1f, 7.7f, -30.1f, -8.6f, -30.0f, -9.0f, -29.8f, -9.3f, -29.5f,
1008 -9.5f, -29.1f, -9.5f, -28.7f, -9.1f, -9.1f, -8.8f, -8.8f,
1009};
1010
1011constexpr std::array<float, 64 * 2> trigger_button = {
1012 5.5f, -12.6f, 5.8f, -12.6f, 6.7f, -12.5f, 8.1f, -12.3f, 8.6f, -12.2f, 9.2f, -12.0f,
1013 9.5f, -11.9f, 9.9f, -11.8f, 10.6f, -11.5f, 11.0f, -11.3f, 11.2f, -11.2f, 11.4f, -11.1f,
1014 11.8f, -10.9f, 12.0f, -10.8f, 12.2f, -10.7f, 12.4f, -10.5f, 12.6f, -10.4f, 12.8f, -10.3f,
1015 13.6f, -9.7f, 13.8f, -9.6f, 13.9f, -9.4f, 14.1f, -9.3f, 14.8f, -8.6f, 15.0f, -8.5f,
1016 15.1f, -8.3f, 15.6f, -7.8f, 15.7f, -7.6f, 16.1f, -7.0f, 16.3f, -6.8f, 16.4f, -6.6f,
1017 16.5f, -6.4f, 16.8f, -6.0f, 16.9f, -5.8f, 17.0f, -5.6f, 17.1f, -5.4f, 17.2f, -5.2f,
1018 17.3f, -5.0f, 17.4f, -4.8f, 17.5f, -4.6f, 17.6f, -4.4f, 17.7f, -4.1f, 17.8f, -3.9f,
1019 17.9f, -3.5f, 18.0f, -3.3f, 18.1f, -3.0f, 18.2f, -2.6f, 18.2f, -2.3f, 18.3f, -2.1f,
1020 18.3f, -1.9f, 18.4f, -1.4f, 18.5f, -1.2f, 18.6f, -0.3f, 18.6f, 0.0f, 18.3f, 13.9f,
1021 -17.0f, 13.8f, -17.0f, 13.6f, -16.4f, -11.4f, -16.3f, -11.6f, -16.1f, -11.8f, -15.7f, -12.0f,
1022 -15.5f, -12.1f, -15.1f, -12.3f, -14.6f, -12.4f, -13.4f, -12.5f,
1023};
1024
1025constexpr std::array<float, 36 * 2> pro_left_trigger = {
1026 -65.2f, -132.6f, -68.2f, -134.1f, -71.3f, -135.5f, -74.4f, -136.7f, -77.6f,
1027 -137.6f, -80.9f, -138.1f, -84.3f, -138.3f, -87.6f, -138.3f, -91.0f, -138.1f,
1028 -94.3f, -137.8f, -97.6f, -137.3f, -100.9f, -136.7f, -107.5f, -135.3f, -110.7f,
1029 -134.5f, -120.4f, -131.8f, -123.6f, -130.8f, -126.8f, -129.7f, -129.9f, -128.5f,
1030 -132.9f, -127.1f, -135.9f, -125.6f, -138.8f, -123.9f, -141.6f, -122.0f, -144.1f,
1031 -119.8f, -146.3f, -117.3f, -148.4f, -114.7f, -150.4f, -112.0f, -152.3f, -109.2f,
1032 -155.3f, -104.0f, -152.0f, -104.3f, -148.7f, -104.5f, -145.3f, -104.8f, -35.5f,
1033 -117.2f, -38.5f, -118.7f, -41.4f, -120.3f, -44.4f, -121.8f, -50.4f, -124.9f,
1034};
1035
1036constexpr std::array<float, 14 * 2> pro_body_top = {
1037 0.0f, -115.4f, -4.4f, -116.1f, -69.7f, -131.3f, -66.4f, -131.9f, -63.1f, -132.3f,
1038 -56.4f, -133.0f, -53.1f, -133.3f, -49.8f, -133.5f, -43.1f, -133.8f, -39.8f, -134.0f,
1039 -36.5f, -134.1f, -16.4f, -134.4f, -13.1f, -134.4f, 0.0f, -134.1f,
1040};
1041
1042constexpr std::array<float, 145 * 2> pro_left_handle = {
1043 -178.7f, -47.5f, -179.0f, -46.1f, -179.3f, -44.6f, -182.0f, -29.8f, -182.3f, -28.4f,
1044 -182.6f, -26.9f, -182.8f, -25.4f, -183.1f, -23.9f, -183.3f, -22.4f, -183.6f, -21.0f,
1045 -183.8f, -19.5f, -184.1f, -18.0f, -184.3f, -16.5f, -184.6f, -15.1f, -184.8f, -13.6f,
1046 -185.1f, -12.1f, -185.3f, -10.6f, -185.6f, -9.1f, -185.8f, -7.7f, -186.1f, -6.2f,
1047 -186.3f, -4.7f, -186.6f, -3.2f, -186.8f, -1.7f, -187.1f, -0.3f, -187.3f, 1.2f,
1048 -187.6f, 2.7f, -187.8f, 4.2f, -188.3f, 7.1f, -188.5f, 8.6f, -188.8f, 10.1f,
1049 -189.0f, 11.6f, -189.3f, 13.1f, -189.5f, 14.5f, -190.0f, 17.5f, -190.2f, 19.0f,
1050 -190.5f, 20.5f, -190.7f, 21.9f, -191.2f, 24.9f, -191.4f, 26.4f, -191.7f, 27.9f,
1051 -191.9f, 29.3f, -192.4f, 32.3f, -192.6f, 33.8f, -193.1f, 36.8f, -193.3f, 38.2f,
1052 -193.8f, 41.2f, -194.0f, 42.7f, -194.7f, 47.1f, -194.9f, 48.6f, -199.0f, 82.9f,
1053 -199.1f, 84.4f, -199.1f, 85.9f, -199.2f, 87.4f, -199.2f, 88.9f, -199.1f, 94.9f,
1054 -198.9f, 96.4f, -198.8f, 97.8f, -198.5f, 99.3f, -198.3f, 100.8f, -198.0f, 102.3f,
1055 -197.7f, 103.7f, -197.4f, 105.2f, -197.0f, 106.7f, -196.6f, 108.1f, -195.7f, 111.0f,
1056 -195.2f, 112.4f, -194.1f, 115.2f, -193.5f, 116.5f, -192.8f, 117.9f, -192.1f, 119.2f,
1057 -190.6f, 121.8f, -189.8f, 123.1f, -188.9f, 124.3f, -187.0f, 126.6f, -186.0f, 127.7f,
1058 -183.9f, 129.8f, -182.7f, 130.8f, -180.3f, 132.6f, -179.1f, 133.4f, -177.8f, 134.1f,
1059 -176.4f, 134.8f, -175.1f, 135.5f, -173.7f, 136.0f, -169.4f, 137.3f, -167.9f, 137.7f,
1060 -166.5f, 138.0f, -165.0f, 138.3f, -163.5f, 138.4f, -162.0f, 138.4f, -160.5f, 138.3f,
1061 -159.0f, 138.0f, -157.6f, 137.7f, -156.1f, 137.3f, -154.7f, 136.9f, -153.2f, 136.5f,
1062 -151.8f, 136.0f, -150.4f, 135.4f, -149.1f, 134.8f, -147.7f, 134.1f, -146.5f, 133.3f,
1063 -145.2f, 132.5f, -144.0f, 131.6f, -142.8f, 130.6f, -141.7f, 129.6f, -139.6f, 127.5f,
1064 -138.6f, 126.4f, -137.7f, 125.2f, -135.1f, 121.5f, -134.3f, 120.3f, -133.5f, 119.0f,
1065 -131.9f, 116.5f, -131.1f, 115.2f, -128.8f, 111.3f, -128.0f, 110.1f, -127.2f, 108.8f,
1066 -126.5f, 107.5f, -125.7f, 106.2f, -125.0f, 104.9f, -124.2f, 103.6f, -123.5f, 102.3f,
1067 -122.0f, 99.6f, -121.3f, 98.3f, -115.8f, 87.7f, -115.1f, 86.4f, -114.4f, 85.0f,
1068 -113.7f, 83.7f, -112.3f, 81.0f, -111.6f, 79.7f, -110.1f, 77.1f, -109.4f, 75.8f,
1069 -108.0f, 73.1f, -107.2f, 71.8f, -106.4f, 70.6f, -105.7f, 69.3f, -104.8f, 68.0f,
1070 -104.0f, 66.8f, -103.1f, 65.6f, -101.1f, 63.3f, -100.0f, 62.3f, -98.8f, 61.4f,
1071 -97.6f, 60.6f, -97.9f, 59.5f, -98.8f, 58.3f, -101.5f, 54.6f, -102.4f, 53.4f,
1072};
1073
1074constexpr std::array<float, 245 * 2> pro_body = {
1075 -0.7f, -129.1f, -54.3f, -129.1f, -55.0f, -129.1f, -57.8f, -129.0f, -58.5f, -129.0f,
1076 -60.7f, -128.9f, -61.4f, -128.9f, -62.8f, -128.8f, -63.5f, -128.8f, -65.7f, -128.7f,
1077 -66.4f, -128.7f, -67.8f, -128.6f, -68.5f, -128.6f, -69.2f, -128.5f, -70.0f, -128.5f,
1078 -70.7f, -128.4f, -71.4f, -128.4f, -72.1f, -128.3f, -72.8f, -128.3f, -73.5f, -128.2f,
1079 -74.2f, -128.2f, -74.9f, -128.1f, -75.7f, -128.1f, -76.4f, -128.0f, -77.1f, -128.0f,
1080 -77.8f, -127.9f, -78.5f, -127.9f, -79.2f, -127.8f, -80.6f, -127.7f, -81.4f, -127.6f,
1081 -82.1f, -127.5f, -82.8f, -127.5f, -83.5f, -127.4f, -84.9f, -127.3f, -85.6f, -127.2f,
1082 -87.0f, -127.1f, -87.7f, -127.0f, -88.5f, -126.9f, -89.2f, -126.8f, -89.9f, -126.8f,
1083 -90.6f, -126.7f, -94.1f, -126.3f, -94.8f, -126.2f, -113.2f, -123.3f, -113.9f, -123.2f,
1084 -114.6f, -123.0f, -115.3f, -122.9f, -116.7f, -122.6f, -117.4f, -122.5f, -118.1f, -122.3f,
1085 -118.8f, -122.2f, -119.5f, -122.0f, -120.9f, -121.7f, -121.6f, -121.5f, -122.3f, -121.4f,
1086 -122.9f, -121.2f, -123.6f, -121.0f, -126.4f, -120.3f, -127.1f, -120.1f, -127.8f, -119.8f,
1087 -128.4f, -119.6f, -129.1f, -119.4f, -131.2f, -118.7f, -132.5f, -118.3f, -133.2f, -118.0f,
1088 -133.8f, -117.7f, -134.5f, -117.4f, -135.1f, -117.2f, -135.8f, -116.9f, -136.4f, -116.5f,
1089 -137.0f, -116.2f, -137.7f, -115.8f, -138.3f, -115.4f, -138.9f, -115.1f, -139.5f, -114.7f,
1090 -160.0f, -100.5f, -160.5f, -100.0f, -162.5f, -97.9f, -162.9f, -97.4f, -163.4f, -96.8f,
1091 -163.8f, -96.2f, -165.3f, -93.8f, -165.7f, -93.2f, -166.0f, -92.6f, -166.4f, -91.9f,
1092 -166.7f, -91.3f, -167.3f, -90.0f, -167.6f, -89.4f, -167.8f, -88.7f, -168.1f, -88.0f,
1093 -168.4f, -87.4f, -168.6f, -86.7f, -168.9f, -86.0f, -169.1f, -85.4f, -169.3f, -84.7f,
1094 -169.6f, -84.0f, -169.8f, -83.3f, -170.2f, -82.0f, -170.4f, -81.3f, -172.8f, -72.3f,
1095 -173.0f, -71.6f, -173.5f, -69.5f, -173.7f, -68.8f, -173.9f, -68.2f, -174.0f, -67.5f,
1096 -174.2f, -66.8f, -174.5f, -65.4f, -174.7f, -64.7f, -174.8f, -64.0f, -175.0f, -63.3f,
1097 -175.3f, -61.9f, -175.5f, -61.2f, -175.8f, -59.8f, -176.0f, -59.1f, -176.1f, -58.4f,
1098 -176.3f, -57.7f, -176.6f, -56.3f, -176.8f, -55.6f, -176.9f, -54.9f, -177.1f, -54.2f,
1099 -177.3f, -53.6f, -177.4f, -52.9f, -177.6f, -52.2f, -177.9f, -50.8f, -178.1f, -50.1f,
1100 -178.2f, -49.4f, -178.2f, -48.7f, -177.8f, -48.1f, -177.1f, -46.9f, -176.7f, -46.3f,
1101 -176.4f, -45.6f, -176.0f, -45.0f, -175.3f, -43.8f, -174.9f, -43.2f, -174.2f, -42.0f,
1102 -173.4f, -40.7f, -173.1f, -40.1f, -172.7f, -39.5f, -172.0f, -38.3f, -171.6f, -37.7f,
1103 -170.5f, -35.9f, -170.1f, -35.3f, -169.7f, -34.6f, -169.3f, -34.0f, -168.6f, -32.8f,
1104 -168.2f, -32.2f, -166.3f, -29.2f, -165.9f, -28.6f, -163.2f, -24.4f, -162.8f, -23.8f,
1105 -141.8f, 6.8f, -141.4f, 7.4f, -139.4f, 10.3f, -139.0f, 10.9f, -138.5f, 11.5f,
1106 -138.1f, 12.1f, -137.3f, 13.2f, -136.9f, 13.8f, -136.0f, 15.0f, -135.6f, 15.6f,
1107 -135.2f, 16.1f, -134.8f, 16.7f, -133.9f, 17.9f, -133.5f, 18.4f, -133.1f, 19.0f,
1108 -131.8f, 20.7f, -131.4f, 21.3f, -130.1f, 23.0f, -129.7f, 23.6f, -128.4f, 25.3f,
1109 -128.0f, 25.9f, -126.7f, 27.6f, -126.3f, 28.2f, -125.4f, 29.3f, -125.0f, 29.9f,
1110 -124.1f, 31.0f, -123.7f, 31.6f, -122.8f, 32.7f, -122.4f, 33.3f, -121.5f, 34.4f,
1111 -121.1f, 35.0f, -120.6f, 35.6f, -120.2f, 36.1f, -119.7f, 36.7f, -119.3f, 37.2f,
1112 -118.9f, 37.8f, -118.4f, 38.4f, -118.0f, 38.9f, -117.5f, 39.5f, -117.1f, 40.0f,
1113 -116.6f, 40.6f, -116.2f, 41.1f, -115.7f, 41.7f, -115.2f, 42.2f, -114.8f, 42.8f,
1114 -114.3f, 43.3f, -113.9f, 43.9f, -113.4f, 44.4f, -112.4f, 45.5f, -112.0f, 46.0f,
1115 -111.5f, 46.5f, -110.5f, 47.6f, -110.0f, 48.1f, -109.6f, 48.6f, -109.1f, 49.2f,
1116 -108.6f, 49.7f, -107.7f, 50.8f, -107.2f, 51.3f, -105.7f, 52.9f, -105.3f, 53.4f,
1117 -104.8f, 53.9f, -104.3f, 54.5f, -103.8f, 55.0f, -100.7f, 58.0f, -100.2f, 58.4f,
1118 -99.7f, 58.9f, -99.1f, 59.3f, -97.2f, 60.3f, -96.5f, 60.1f, -95.9f, 59.7f,
1119 -95.3f, 59.4f, -94.6f, 59.1f, -93.9f, 58.9f, -92.6f, 58.5f, -91.9f, 58.4f,
1120 -91.2f, 58.2f, -90.5f, 58.1f, -89.7f, 58.0f, -89.0f, 57.9f, -86.2f, 57.6f,
1121 -85.5f, 57.5f, -84.1f, 57.4f, -83.4f, 57.3f, -82.6f, 57.3f, -81.9f, 57.2f,
1122 -81.2f, 57.2f, -80.5f, 57.1f, -79.8f, 57.1f, -78.4f, 57.0f, -77.7f, 57.0f,
1123 -75.5f, 56.9f, -74.8f, 56.9f, -71.9f, 56.8f, -71.2f, 56.8f, 0.0f, 56.8f,
1124};
1125
1126constexpr std::array<float, 199 * 2> gc_body = {
1127 0.0f, -138.03f, -4.91f, -138.01f, -8.02f, -137.94f, -11.14f, -137.82f, -14.25f,
1128 -137.67f, -17.37f, -137.48f, -20.48f, -137.25f, -23.59f, -137.0f, -26.69f, -136.72f,
1129 -29.8f, -136.41f, -32.9f, -136.07f, -35.99f, -135.71f, -39.09f, -135.32f, -42.18f,
1130 -134.91f, -45.27f, -134.48f, -48.35f, -134.03f, -51.43f, -133.55f, -54.51f, -133.05f,
1131 -57.59f, -132.52f, -60.66f, -131.98f, -63.72f, -131.41f, -66.78f, -130.81f, -69.84f,
1132 -130.2f, -72.89f, -129.56f, -75.94f, -128.89f, -78.98f, -128.21f, -82.02f, -127.49f,
1133 -85.05f, -126.75f, -88.07f, -125.99f, -91.09f, -125.19f, -94.1f, -124.37f, -97.1f,
1134 -123.52f, -100.09f, -122.64f, -103.07f, -121.72f, -106.04f, -120.77f, -109.0f, -119.79f,
1135 -111.95f, -118.77f, -114.88f, -117.71f, -117.8f, -116.61f, -120.7f, -115.46f, -123.58f,
1136 -114.27f, -126.44f, -113.03f, -129.27f, -111.73f, -132.08f, -110.38f, -134.86f, -108.96f,
1137 -137.6f, -107.47f, -140.3f, -105.91f, -142.95f, -104.27f, -145.55f, -102.54f, -148.07f,
1138 -100.71f, -150.51f, -98.77f, -152.86f, -96.71f, -155.09f, -94.54f, -157.23f, -92.27f,
1139 -159.26f, -89.9f, -161.2f, -87.46f, -163.04f, -84.94f, -164.78f, -82.35f, -166.42f,
1140 -79.7f, -167.97f, -77.0f, -169.43f, -74.24f, -170.8f, -71.44f, -172.09f, -68.6f,
1141 -173.29f, -65.72f, -174.41f, -62.81f, -175.45f, -59.87f, -176.42f, -56.91f, -177.31f,
1142 -53.92f, -178.14f, -50.91f, -178.9f, -47.89f, -179.6f, -44.85f, -180.24f, -41.8f,
1143 -180.82f, -38.73f, -181.34f, -35.66f, -181.8f, -32.57f, -182.21f, -29.48f, -182.57f,
1144 -26.38f, -182.88f, -23.28f, -183.15f, -20.17f, -183.36f, -17.06f, -183.54f, -13.95f,
1145 -183.71f, -10.84f, -184.0f, -7.73f, -184.23f, -4.62f, -184.44f, -1.51f, -184.62f,
1146 1.6f, -184.79f, 4.72f, -184.95f, 7.83f, -185.11f, 10.95f, -185.25f, 14.06f,
1147 -185.38f, 17.18f, -185.51f, 20.29f, -185.63f, 23.41f, -185.74f, 26.53f, -185.85f,
1148 29.64f, -185.95f, 32.76f, -186.04f, 35.88f, -186.12f, 39.0f, -186.19f, 42.11f,
1149 -186.26f, 45.23f, -186.32f, 48.35f, -186.37f, 51.47f, -186.41f, 54.59f, -186.44f,
1150 57.7f, -186.46f, 60.82f, -186.46f, 63.94f, -186.44f, 70.18f, -186.41f, 73.3f,
1151 -186.36f, 76.42f, -186.3f, 79.53f, -186.22f, 82.65f, -186.12f, 85.77f, -185.99f,
1152 88.88f, -185.84f, 92.0f, -185.66f, 95.11f, -185.44f, 98.22f, -185.17f, 101.33f,
1153 -184.85f, 104.43f, -184.46f, 107.53f, -183.97f, 110.61f, -183.37f, 113.67f, -182.65f,
1154 116.7f, -181.77f, 119.69f, -180.71f, 122.62f, -179.43f, 125.47f, -177.89f, 128.18f,
1155 -176.05f, 130.69f, -173.88f, 132.92f, -171.36f, 134.75f, -168.55f, 136.1f, -165.55f,
1156 136.93f, -162.45f, 137.29f, -156.23f, 137.03f, -153.18f, 136.41f, -150.46f, 134.9f,
1157 -148.14f, 132.83f, -146.14f, 130.43f, -144.39f, 127.85f, -142.83f, 125.16f, -141.41f,
1158 122.38f, -140.11f, 119.54f, -138.9f, 116.67f, -137.77f, 113.76f, -136.7f, 110.84f,
1159 -135.68f, 107.89f, -134.71f, 104.93f, -133.77f, 101.95f, -132.86f, 98.97f, -131.97f,
1160 95.98f, -131.09f, 92.99f, -130.23f, 89.99f, -129.36f, 86.99f, -128.49f, 84.0f,
1161 -127.63f, 81.0f, -126.76f, 78.01f, -125.9f, 75.01f, -124.17f, 69.02f, -123.31f,
1162 66.02f, -121.59f, 60.03f, -120.72f, 57.03f, -119.86f, 54.03f, -118.13f, 48.04f,
1163 -117.27f, 45.04f, -115.55f, 39.05f, -114.68f, 36.05f, -113.82f, 33.05f, -112.96f,
1164 30.06f, -110.4f, 28.29f, -107.81f, 26.55f, -105.23f, 24.8f, -97.48f, 19.55f,
1165 -94.9f, 17.81f, -92.32f, 16.06f, -87.15f, 12.56f, -84.57f, 10.81f, -81.99f,
1166 9.07f, -79.4f, 7.32f, -76.82f, 5.57f, -69.07f, 0.33f, -66.49f, -1.42f,
1167 -58.74f, -6.66f, -56.16f, -8.41f, -48.4f, -13.64f, -45.72f, -15.22f, -42.93f,
1168 -16.62f, -40.07f, -17.86f, -37.15f, -18.96f, -34.19f, -19.94f, -31.19f, -20.79f,
1169 -28.16f, -21.55f, -25.12f, -22.21f, -22.05f, -22.79f, -18.97f, -23.28f, -15.88f,
1170 -23.7f, -12.78f, -24.05f, -9.68f, -24.33f, -6.57f, -24.55f, -3.45f, -24.69f,
1171 0.0f, -24.69f,
1172};
1173
1174constexpr std::array<float, 99 * 2> gc_left_body = {
1175 -74.59f, -97.22f, -70.17f, -94.19f, -65.95f, -90.89f, -62.06f, -87.21f, -58.58f,
1176 -83.14f, -55.58f, -78.7f, -53.08f, -73.97f, -51.05f, -69.01f, -49.46f, -63.89f,
1177 -48.24f, -58.67f, -47.36f, -53.39f, -46.59f, -48.09f, -45.7f, -42.8f, -44.69f,
1178 -37.54f, -43.54f, -32.31f, -42.25f, -27.11f, -40.8f, -21.95f, -39.19f, -16.84f,
1179 -37.38f, -11.8f, -35.34f, -6.84f, -33.04f, -2.0f, -30.39f, 2.65f, -27.26f,
1180 7.0f, -23.84f, 11.11f, -21.19f, 15.76f, -19.18f, 20.73f, -17.73f, 25.88f,
1181 -16.82f, 31.16f, -16.46f, 36.5f, -16.7f, 41.85f, -17.63f, 47.13f, -19.31f,
1182 52.21f, -21.8f, 56.95f, -24.91f, 61.3f, -28.41f, 65.36f, -32.28f, 69.06f,
1183 -36.51f, 72.35f, -41.09f, 75.13f, -45.97f, 77.32f, -51.1f, 78.86f, -56.39f,
1184 79.7f, -61.74f, 79.84f, -67.07f, 79.3f, -72.3f, 78.15f, -77.39f, 76.48f,
1185 -82.29f, 74.31f, -86.76f, 71.37f, -90.7f, 67.75f, -94.16f, 63.66f, -97.27f,
1186 59.3f, -100.21f, 54.81f, -103.09f, 50.3f, -106.03f, 45.82f, -109.11f, 41.44f,
1187 -112.37f, 37.19f, -115.85f, 33.11f, -119.54f, 29.22f, -123.45f, 25.56f, -127.55f,
1188 22.11f, -131.77f, 18.81f, -136.04f, 15.57f, -140.34f, 12.37f, -144.62f, 9.15f,
1189 -148.86f, 5.88f, -153.03f, 2.51f, -157.05f, -1.03f, -160.83f, -4.83f, -164.12f,
1190 -9.05f, -166.71f, -13.73f, -168.91f, -18.62f, -170.77f, -23.64f, -172.3f, -28.78f,
1191 -173.49f, -34.0f, -174.3f, -39.3f, -174.72f, -44.64f, -174.72f, -49.99f, -174.28f,
1192 -55.33f, -173.37f, -60.61f, -172.0f, -65.79f, -170.17f, -70.82f, -167.79f, -75.62f,
1193 -164.84f, -80.09f, -161.43f, -84.22f, -157.67f, -88.03f, -153.63f, -91.55f, -149.37f,
1194 -94.81f, -144.94f, -97.82f, -140.37f, -100.61f, -135.65f, -103.16f, -130.73f, -105.26f,
1195 -125.62f, -106.86f, -120.37f, -107.95f, -115.05f, -108.56f, -109.7f, -108.69f, -104.35f,
1196 -108.36f, -99.05f, -107.6f, -93.82f, -106.41f, -88.72f, -104.79f, -83.78f, -102.7f,
1197};
1198
1199constexpr std::array<float, 47 * 2> left_gc_trigger = {
1200 -99.69f, -125.04f, -101.81f, -126.51f, -104.02f, -127.85f, -106.3f, -129.06f, -108.65f,
1201 -130.12f, -111.08f, -130.99f, -113.58f, -131.62f, -116.14f, -131.97f, -121.26f, -131.55f,
1202 -123.74f, -130.84f, -126.17f, -129.95f, -128.53f, -128.9f, -130.82f, -127.71f, -133.03f,
1203 -126.38f, -135.15f, -124.92f, -137.18f, -123.32f, -139.11f, -121.6f, -140.91f, -119.75f,
1204 -142.55f, -117.77f, -144.0f, -115.63f, -145.18f, -113.34f, -146.17f, -110.95f, -147.05f,
1205 -108.53f, -147.87f, -106.08f, -148.64f, -103.61f, -149.37f, -101.14f, -149.16f, -100.12f,
1206 -147.12f, -101.71f, -144.99f, -103.16f, -142.8f, -104.53f, -140.57f, -105.83f, -138.31f,
1207 -107.08f, -136.02f, -108.27f, -133.71f, -109.42f, -131.38f, -110.53f, -129.04f, -111.61f,
1208 -126.68f, -112.66f, -124.31f, -113.68f, -121.92f, -114.67f, -119.53f, -115.64f, -117.13f,
1209 -116.58f, -114.72f, -117.51f, -112.3f, -118.41f, -109.87f, -119.29f, -107.44f, -120.16f,
1210 -105.0f, -121.0f, -100.11f, -122.65f,
1211};
1212
1213constexpr std::array<float, 50 * 2> gc_button_x = {
1214 142.1f, -50.67f, 142.44f, -48.65f, 142.69f, -46.62f, 142.8f, -44.57f, 143.0f, -42.54f,
1215 143.56f, -40.57f, 144.42f, -38.71f, 145.59f, -37.04f, 147.08f, -35.64f, 148.86f, -34.65f,
1216 150.84f, -34.11f, 152.88f, -34.03f, 154.89f, -34.38f, 156.79f, -35.14f, 158.49f, -36.28f,
1217 159.92f, -37.74f, 161.04f, -39.45f, 161.85f, -41.33f, 162.4f, -43.3f, 162.72f, -45.32f,
1218 162.85f, -47.37f, 162.82f, -49.41f, 162.67f, -51.46f, 162.39f, -53.48f, 162.0f, -55.5f,
1219 161.51f, -57.48f, 160.9f, -59.44f, 160.17f, -61.35f, 159.25f, -63.18f, 158.19f, -64.93f,
1220 157.01f, -66.61f, 155.72f, -68.2f, 154.31f, -69.68f, 152.78f, -71.04f, 151.09f, -72.2f,
1221 149.23f, -73.04f, 147.22f, -73.36f, 145.19f, -73.11f, 143.26f, -72.42f, 141.51f, -71.37f,
1222 140.0f, -69.99f, 138.82f, -68.32f, 138.13f, -66.4f, 138.09f, -64.36f, 138.39f, -62.34f,
1223 139.05f, -60.41f, 139.91f, -58.55f, 140.62f, -56.63f, 141.21f, -54.67f, 141.67f, -52.67f,
1224};
1225
1226constexpr std::array<float, 50 * 2> gc_button_y = {
1227 104.02f, -75.23f, 106.01f, -75.74f, 108.01f, -76.15f, 110.04f, -76.42f, 112.05f, -76.78f,
1228 113.97f, -77.49f, 115.76f, -78.49f, 117.33f, -79.79f, 118.6f, -81.39f, 119.46f, -83.25f,
1229 119.84f, -85.26f, 119.76f, -87.3f, 119.24f, -89.28f, 118.33f, -91.11f, 117.06f, -92.71f,
1230 115.49f, -94.02f, 113.7f, -95.01f, 111.77f, -95.67f, 109.76f, -96.05f, 107.71f, -96.21f,
1231 105.67f, -96.18f, 103.63f, -95.99f, 101.61f, -95.67f, 99.61f, -95.24f, 97.63f, -94.69f,
1232 95.69f, -94.04f, 93.79f, -93.28f, 91.94f, -92.4f, 90.19f, -91.34f, 88.53f, -90.14f,
1233 86.95f, -88.84f, 85.47f, -87.42f, 84.1f, -85.9f, 82.87f, -84.26f, 81.85f, -82.49f,
1234 81.15f, -80.57f, 81.0f, -78.54f, 81.41f, -76.54f, 82.24f, -74.67f, 83.43f, -73.01f,
1235 84.92f, -71.61f, 86.68f, -70.57f, 88.65f, -70.03f, 90.69f, -70.15f, 92.68f, -70.61f,
1236 94.56f, -71.42f, 96.34f, -72.43f, 98.2f, -73.29f, 100.11f, -74.03f, 102.06f, -74.65f,
1237};
1238
1239constexpr std::array<float, 47 * 2> gc_button_z = {
1240 95.74f, -126.41f, 98.34f, -126.38f, 100.94f, -126.24f, 103.53f, -126.01f, 106.11f, -125.7f,
1241 108.69f, -125.32f, 111.25f, -124.87f, 113.8f, -124.34f, 116.33f, -123.73f, 118.84f, -123.05f,
1242 121.33f, -122.3f, 123.79f, -121.47f, 126.23f, -120.56f, 128.64f, -119.58f, 131.02f, -118.51f,
1243 133.35f, -117.37f, 135.65f, -116.14f, 137.9f, -114.84f, 140.1f, -113.46f, 142.25f, -111.99f,
1244 144.35f, -110.45f, 146.38f, -108.82f, 148.35f, -107.13f, 150.25f, -105.35f, 151.89f, -103.38f,
1245 151.43f, -100.86f, 149.15f, -100.15f, 146.73f, -101.06f, 144.36f, -102.12f, 141.98f, -103.18f,
1246 139.6f, -104.23f, 137.22f, -105.29f, 134.85f, -106.35f, 132.47f, -107.41f, 127.72f, -109.53f,
1247 125.34f, -110.58f, 122.96f, -111.64f, 120.59f, -112.7f, 118.21f, -113.76f, 113.46f, -115.88f,
1248 111.08f, -116.93f, 108.7f, -117.99f, 106.33f, -119.05f, 103.95f, -120.11f, 99.2f, -122.23f,
1249 96.82f, -123.29f, 94.44f, -124.34f,
1250};
1251
1252constexpr std::array<float, 84 * 2> left_joycon_body = {
1253 -145.0f, -78.9f, -145.0f, -77.9f, -145.0f, 85.6f, -145.0f, 85.6f, -168.3f, 85.5f,
1254 -169.3f, 85.4f, -171.3f, 85.1f, -172.3f, 84.9f, -173.4f, 84.7f, -174.3f, 84.5f,
1255 -175.3f, 84.2f, -176.3f, 83.8f, -177.3f, 83.5f, -178.2f, 83.1f, -179.2f, 82.7f,
1256 -180.1f, 82.2f, -181.0f, 81.8f, -181.9f, 81.3f, -182.8f, 80.7f, -183.7f, 80.2f,
1257 -184.5f, 79.6f, -186.2f, 78.3f, -186.9f, 77.7f, -187.7f, 77.0f, -189.2f, 75.6f,
1258 -189.9f, 74.8f, -190.6f, 74.1f, -191.3f, 73.3f, -191.9f, 72.5f, -192.5f, 71.6f,
1259 -193.1f, 70.8f, -193.7f, 69.9f, -194.3f, 69.1f, -194.8f, 68.2f, -196.2f, 65.5f,
1260 -196.6f, 64.5f, -197.0f, 63.6f, -197.4f, 62.6f, -198.1f, 60.7f, -198.4f, 59.7f,
1261 -198.6f, 58.7f, -199.2f, 55.6f, -199.3f, 54.6f, -199.5f, 51.5f, -199.5f, 50.5f,
1262 -199.5f, -49.4f, -199.4f, -50.5f, -199.3f, -51.5f, -199.1f, -52.5f, -198.2f, -56.5f,
1263 -197.9f, -57.5f, -197.2f, -59.4f, -196.8f, -60.4f, -196.4f, -61.3f, -195.9f, -62.2f,
1264 -194.3f, -64.9f, -193.7f, -65.7f, -193.1f, -66.6f, -192.5f, -67.4f, -191.8f, -68.2f,
1265 -191.2f, -68.9f, -190.4f, -69.7f, -188.2f, -71.8f, -187.4f, -72.5f, -186.6f, -73.1f,
1266 -185.8f, -73.8f, -185.0f, -74.4f, -184.1f, -74.9f, -183.2f, -75.5f, -182.4f, -76.0f,
1267 -181.5f, -76.5f, -179.6f, -77.5f, -178.7f, -77.9f, -177.8f, -78.4f, -176.8f, -78.8f,
1268 -175.9f, -79.1f, -174.9f, -79.5f, -173.9f, -79.8f, -170.9f, -80.6f, -169.9f, -80.8f,
1269 -167.9f, -81.1f, -166.9f, -81.2f, -165.8f, -81.2f, -145.0f, -80.9f,
1270};
1271
1272constexpr std::array<float, 84 * 2> left_joycon_trigger = {
1273 -166.8f, -83.3f, -167.9f, -83.2f, -168.9f, -83.1f, -170.0f, -83.0f, -171.0f, -82.8f,
1274 -172.1f, -82.6f, -173.1f, -82.4f, -174.2f, -82.1f, -175.2f, -81.9f, -176.2f, -81.5f,
1275 -177.2f, -81.2f, -178.2f, -80.8f, -180.1f, -80.0f, -181.1f, -79.5f, -182.0f, -79.0f,
1276 -183.0f, -78.5f, -183.9f, -78.0f, -184.8f, -77.4f, -185.7f, -76.9f, -186.6f, -76.3f,
1277 -187.4f, -75.6f, -188.3f, -75.0f, -189.1f, -74.3f, -192.2f, -71.5f, -192.9f, -70.7f,
1278 -193.7f, -69.9f, -194.3f, -69.1f, -195.0f, -68.3f, -195.6f, -67.4f, -196.8f, -65.7f,
1279 -197.3f, -64.7f, -197.8f, -63.8f, -198.2f, -62.8f, -198.9f, -60.8f, -198.6f, -59.8f,
1280 -197.6f, -59.7f, -196.6f, -60.0f, -195.6f, -60.5f, -194.7f, -60.9f, -193.7f, -61.4f,
1281 -192.8f, -61.9f, -191.8f, -62.4f, -190.9f, -62.8f, -189.9f, -63.3f, -189.0f, -63.8f,
1282 -187.1f, -64.8f, -186.2f, -65.2f, -185.2f, -65.7f, -184.3f, -66.2f, -183.3f, -66.7f,
1283 -182.4f, -67.1f, -181.4f, -67.6f, -180.5f, -68.1f, -179.5f, -68.6f, -178.6f, -69.0f,
1284 -177.6f, -69.5f, -176.7f, -70.0f, -175.7f, -70.5f, -174.8f, -70.9f, -173.8f, -71.4f,
1285 -172.9f, -71.9f, -171.9f, -72.4f, -171.0f, -72.8f, -170.0f, -73.3f, -169.1f, -73.8f,
1286 -168.1f, -74.3f, -167.2f, -74.7f, -166.2f, -75.2f, -165.3f, -75.7f, -164.3f, -76.2f,
1287 -163.4f, -76.6f, -162.4f, -77.1f, -161.5f, -77.6f, -160.5f, -78.1f, -159.6f, -78.5f,
1288 -158.7f, -79.0f, -157.7f, -79.5f, -156.8f, -80.0f, -155.8f, -80.4f, -154.9f, -80.9f,
1289 -154.2f, -81.6f, -154.3f, -82.6f, -155.2f, -83.3f, -156.2f, -83.3f,
1290};
1291
1292constexpr std::array<float, 70 * 2> handheld_body = {
1293 -137.3f, -81.9f, -137.6f, -81.8f, -137.8f, -81.6f, -138.0f, -81.3f, -138.1f, -81.1f,
1294 -138.1f, -80.8f, -138.2f, -78.7f, -138.2f, -78.4f, -138.3f, -78.1f, -138.7f, -77.3f,
1295 -138.9f, -77.0f, -139.0f, -76.8f, -139.2f, -76.5f, -139.5f, -76.3f, -139.7f, -76.1f,
1296 -139.9f, -76.0f, -140.2f, -75.8f, -140.5f, -75.7f, -140.7f, -75.6f, -141.0f, -75.5f,
1297 -141.9f, -75.3f, -142.2f, -75.3f, -142.5f, -75.2f, -143.0f, -74.9f, -143.2f, -74.7f,
1298 -143.3f, -74.4f, -143.0f, -74.1f, -143.0f, 85.3f, -143.0f, 85.6f, -142.7f, 85.8f,
1299 -142.4f, 85.9f, -142.2f, 85.9f, 143.0f, 85.6f, 143.1f, 85.4f, 143.3f, 85.1f,
1300 143.0f, 84.8f, 143.0f, -74.9f, 142.8f, -75.1f, 142.5f, -75.2f, 141.9f, -75.3f,
1301 141.6f, -75.3f, 141.3f, -75.4f, 141.1f, -75.4f, 140.8f, -75.5f, 140.5f, -75.7f,
1302 140.2f, -75.8f, 140.0f, -76.0f, 139.7f, -76.1f, 139.5f, -76.3f, 139.1f, -76.8f,
1303 138.9f, -77.0f, 138.6f, -77.5f, 138.4f, -77.8f, 138.3f, -78.1f, 138.3f, -78.3f,
1304 138.2f, -78.6f, 138.2f, -78.9f, 138.1f, -79.2f, 138.1f, -79.5f, 138.0f, -81.3f,
1305 137.8f, -81.6f, 137.6f, -81.8f, 137.3f, -81.9f, 137.1f, -81.9f, 120.0f, -70.0f,
1306 -120.0f, -70.0f, -120.0f, 70.0f, 120.0f, 70.0f, 120.0f, -70.0f, 137.1f, -81.9f,
1307};
1308
1309constexpr std::array<float, 40 * 2> handheld_bezel = {
1310 -131.4f, -75.9f, -132.2f, -75.7f, -132.9f, -75.3f, -134.2f, -74.3f, -134.7f, -73.6f,
1311 -135.1f, -72.8f, -135.4f, -72.0f, -135.5f, -71.2f, -135.5f, -70.4f, -135.2f, 76.7f,
1312 -134.8f, 77.5f, -134.3f, 78.1f, -133.7f, 78.8f, -133.1f, 79.2f, -132.3f, 79.6f,
1313 -131.5f, 79.9f, -130.7f, 80.0f, -129.8f, 80.0f, 132.2f, 79.7f, 133.0f, 79.3f,
1314 133.7f, 78.8f, 134.3f, 78.3f, 134.8f, 77.6f, 135.1f, 76.8f, 135.5f, 75.2f,
1315 135.5f, 74.3f, 135.2f, -72.7f, 134.8f, -73.5f, 134.4f, -74.2f, 133.8f, -74.8f,
1316 133.1f, -75.3f, 132.3f, -75.6f, 130.7f, -76.0f, 129.8f, -76.0f, -112.9f, -62.2f,
1317 112.9f, -62.2f, 112.9f, 62.2f, -112.9f, 62.2f, -112.9f, -62.2f, 129.8f, -76.0f,
1318};
1319
1320constexpr std::array<float, 58 * 2> handheld_buttons = {
1321 -82.48f, -82.95f, -82.53f, -82.95f, -106.69f, -82.96f, -106.73f, -82.98f, -106.78f, -83.01f,
1322 -106.81f, -83.05f, -106.83f, -83.1f, -106.83f, -83.15f, -106.82f, -83.93f, -106.81f, -83.99f,
1323 -106.8f, -84.04f, -106.78f, -84.08f, -106.76f, -84.13f, -106.73f, -84.18f, -106.7f, -84.22f,
1324 -106.6f, -84.34f, -106.56f, -84.37f, -106.51f, -84.4f, -106.47f, -84.42f, -106.42f, -84.45f,
1325 -106.37f, -84.47f, -106.32f, -84.48f, -106.17f, -84.5f, -98.9f, -84.48f, -98.86f, -84.45f,
1326 -98.83f, -84.41f, -98.81f, -84.36f, -98.8f, -84.31f, -98.8f, -84.26f, -98.79f, -84.05f,
1327 -90.26f, -84.1f, -90.26f, -84.15f, -90.25f, -84.36f, -90.23f, -84.41f, -90.2f, -84.45f,
1328 -90.16f, -84.48f, -90.11f, -84.5f, -82.79f, -84.49f, -82.74f, -84.48f, -82.69f, -84.46f,
1329 -82.64f, -84.45f, -82.59f, -84.42f, -82.55f, -84.4f, -82.5f, -84.37f, -82.46f, -84.33f,
1330 -82.42f, -84.3f, -82.39f, -84.26f, -82.3f, -84.13f, -82.28f, -84.08f, -82.25f, -83.98f,
1331 -82.24f, -83.93f, -82.23f, -83.83f, -82.23f, -83.78f, -82.24f, -83.1f, -82.26f, -83.05f,
1332 -82.29f, -83.01f, -82.33f, -82.97f, -82.38f, -82.95f,
1333};
1334
1335constexpr std::array<float, 47 * 2> left_joycon_slider = {
1336 -23.7f, -118.2f, -23.7f, -117.3f, -23.7f, 96.6f, -22.8f, 96.6f, -21.5f, 97.2f, -21.5f,
1337 98.1f, -21.2f, 106.7f, -20.8f, 107.5f, -20.1f, 108.2f, -19.2f, 108.2f, -16.4f, 108.1f,
1338 -15.8f, 107.5f, -15.8f, 106.5f, -15.8f, 62.8f, -16.3f, 61.9f, -15.8f, 61.0f, -17.3f,
1339 60.3f, -19.1f, 58.9f, -19.1f, 58.1f, -19.1f, 57.2f, -19.1f, 34.5f, -17.9f, 33.9f,
1340 -17.2f, 33.2f, -16.6f, 32.4f, -16.2f, 31.6f, -15.8f, 30.7f, -15.8f, 29.7f, -15.8f,
1341 28.8f, -15.8f, -46.4f, -16.3f, -47.3f, -15.8f, -48.1f, -17.4f, -48.8f, -19.1f, -49.4f,
1342 -19.1f, -50.1f, -19.1f, -51.0f, -19.1f, -51.9f, -19.1f, -73.7f, -19.1f, -74.5f, -17.5f,
1343 -75.2f, -16.4f, -76.7f, -16.0f, -77.6f, -15.8f, -78.5f, -15.8f, -79.4f, -15.8f, -80.4f,
1344 -15.8f, -118.2f, -15.8f, -118.2f, -18.3f, -118.2f,
1345};
1346
1347constexpr std::array<float, 66 * 2> left_joycon_sideview = {
1348 -158.8f, -133.5f, -159.8f, -133.5f, -173.5f, -133.3f, -174.5f, -133.0f, -175.4f, -132.6f,
1349 -176.2f, -132.1f, -177.0f, -131.5f, -177.7f, -130.9f, -178.3f, -130.1f, -179.4f, -128.5f,
1350 -179.8f, -127.6f, -180.4f, -125.7f, -180.6f, -124.7f, -180.7f, -123.8f, -180.7f, -122.8f,
1351 -180.0f, 128.8f, -179.6f, 129.7f, -179.1f, 130.5f, -177.9f, 132.1f, -177.2f, 132.7f,
1352 -176.4f, 133.3f, -175.6f, 133.8f, -174.7f, 134.3f, -173.8f, 134.6f, -172.8f, 134.8f,
1353 -170.9f, 135.0f, -169.9f, 135.0f, -156.1f, 134.8f, -155.2f, 134.6f, -154.2f, 134.3f,
1354 -153.3f, 134.0f, -152.4f, 133.6f, -151.6f, 133.1f, -150.7f, 132.6f, -149.9f, 132.0f,
1355 -149.2f, 131.4f, -148.5f, 130.7f, -147.1f, 129.2f, -146.5f, 128.5f, -146.0f, 127.7f,
1356 -145.5f, 126.8f, -145.0f, 126.0f, -144.6f, 125.1f, -144.2f, 124.1f, -143.9f, 123.2f,
1357 -143.7f, 122.2f, -143.6f, 121.3f, -143.5f, 120.3f, -143.5f, 119.3f, -144.4f, -123.4f,
1358 -144.8f, -124.3f, -145.3f, -125.1f, -145.8f, -126.0f, -146.3f, -126.8f, -147.0f, -127.5f,
1359 -147.6f, -128.3f, -148.3f, -129.0f, -149.0f, -129.6f, -149.8f, -130.3f, -150.6f, -130.8f,
1360 -151.4f, -131.4f, -152.2f, -131.9f, -153.1f, -132.3f, -155.9f, -133.3f, -156.8f, -133.5f,
1361 -157.8f, -133.5f,
1362};
1363
1364constexpr std::array<float, 40 * 2> left_joycon_body_trigger = {
1365 -146.1f, -124.3f, -146.0f, -122.0f, -145.8f, -119.7f, -145.7f, -117.4f, -145.4f, -112.8f,
1366 -145.3f, -110.5f, -145.0f, -105.9f, -144.9f, -103.6f, -144.6f, -99.1f, -144.5f, -96.8f,
1367 -144.5f, -89.9f, -144.5f, -87.6f, -144.5f, -83.0f, -144.5f, -80.7f, -144.5f, -80.3f,
1368 -142.4f, -82.4f, -141.4f, -84.5f, -140.2f, -86.4f, -138.8f, -88.3f, -137.4f, -90.1f,
1369 -134.5f, -93.6f, -133.0f, -95.3f, -130.0f, -98.8f, -128.5f, -100.6f, -127.1f, -102.4f,
1370 -125.8f, -104.3f, -124.7f, -106.3f, -123.9f, -108.4f, -125.1f, -110.2f, -127.4f, -110.3f,
1371 -129.7f, -110.3f, -134.2f, -110.5f, -136.4f, -111.4f, -138.1f, -112.8f, -139.4f, -114.7f,
1372 -140.5f, -116.8f, -141.4f, -118.9f, -143.3f, -123.1f, -144.6f, -124.9f, -146.2f, -126.0f,
1373};
1374
1375constexpr std::array<float, 49 * 2> left_joycon_topview = {
1376 -184.8f, -20.8f, -185.6f, -21.1f, -186.4f, -21.5f, -187.1f, -22.1f, -187.8f, -22.6f,
1377 -188.4f, -23.2f, -189.6f, -24.5f, -190.2f, -25.2f, -190.7f, -25.9f, -191.1f, -26.7f,
1378 -191.4f, -27.5f, -191.6f, -28.4f, -191.7f, -29.2f, -191.7f, -30.1f, -191.5f, -47.7f,
1379 -191.2f, -48.5f, -191.0f, -49.4f, -190.7f, -50.2f, -190.3f, -51.0f, -190.0f, -51.8f,
1380 -189.6f, -52.6f, -189.1f, -53.4f, -188.6f, -54.1f, -187.5f, -55.4f, -186.9f, -56.1f,
1381 -186.2f, -56.7f, -185.5f, -57.2f, -184.0f, -58.1f, -183.3f, -58.5f, -182.5f, -58.9f,
1382 -181.6f, -59.2f, -180.8f, -59.5f, -179.9f, -59.7f, -179.1f, -59.9f, -178.2f, -60.0f,
1383 -174.7f, -60.1f, -168.5f, -60.2f, -162.4f, -60.3f, -156.2f, -60.4f, -149.2f, -60.5f,
1384 -143.0f, -60.6f, -136.9f, -60.7f, -130.7f, -60.8f, -123.7f, -60.9f, -117.5f, -61.0f,
1385 -110.5f, -61.1f, -94.4f, -60.4f, -94.4f, -59.5f, -94.4f, -20.6f,
1386};
1387
1388constexpr std::array<float, 41 * 2> left_joycon_slider_topview = {
1389 -95.1f, -51.5f, -95.0f, -51.5f, -91.2f, -51.6f, -91.2f, -51.7f, -91.1f, -52.4f, -91.1f, -52.6f,
1390 -91.0f, -54.1f, -86.3f, -54.0f, -86.0f, -53.9f, -85.9f, -53.8f, -85.6f, -53.4f, -85.5f, -53.2f,
1391 -85.5f, -53.1f, -85.4f, -52.9f, -85.4f, -52.8f, -85.3f, -52.4f, -85.3f, -52.3f, -85.4f, -27.2f,
1392 -85.4f, -27.1f, -85.5f, -27.0f, -85.5f, -26.9f, -85.6f, -26.7f, -85.6f, -26.6f, -85.7f, -26.5f,
1393 -85.9f, -26.4f, -86.0f, -26.3f, -86.4f, -26.0f, -86.5f, -25.9f, -86.7f, -25.8f, -87.1f, -25.7f,
1394 -90.4f, -25.8f, -90.7f, -25.9f, -90.8f, -26.0f, -90.9f, -26.3f, -91.0f, -26.4f, -91.0f, -26.5f,
1395 -91.1f, -26.7f, -91.1f, -26.9f, -91.2f, -28.9f, -95.2f, -29.1f, -95.2f, -29.2f,
1396};
1397
1398constexpr std::array<float, 42 * 2> left_joycon_sideview_zl = {
1399 -148.9f, -128.2f, -148.7f, -126.6f, -148.4f, -124.9f, -148.2f, -123.3f, -147.9f, -121.7f,
1400 -147.7f, -120.1f, -147.4f, -118.5f, -147.2f, -116.9f, -146.9f, -115.3f, -146.4f, -112.1f,
1401 -146.1f, -110.5f, -145.9f, -108.9f, -145.6f, -107.3f, -144.2f, -107.3f, -142.6f, -107.5f,
1402 -141.0f, -107.8f, -137.8f, -108.3f, -136.2f, -108.6f, -131.4f, -109.4f, -129.8f, -109.7f,
1403 -125.6f, -111.4f, -124.5f, -112.7f, -123.9f, -114.1f, -123.8f, -115.8f, -123.8f, -117.4f,
1404 -123.9f, -120.6f, -124.5f, -122.1f, -125.8f, -123.1f, -127.4f, -123.4f, -129.0f, -123.6f,
1405 -130.6f, -124.0f, -132.1f, -124.4f, -133.7f, -124.8f, -135.3f, -125.3f, -136.8f, -125.9f,
1406 -138.3f, -126.4f, -139.9f, -126.9f, -141.4f, -127.5f, -142.9f, -128.0f, -144.5f, -128.5f,
1407 -146.0f, -129.0f, -147.6f, -129.4f,
1408};
1409
1410constexpr std::array<float, 72 * 2> left_joystick_sideview = {
1411 -14.7f, -3.8f, -15.2f, -5.6f, -15.2f, -7.6f, -15.5f, -17.6f, -17.4f, -18.3f, -19.4f, -18.2f,
1412 -21.3f, -17.6f, -22.8f, -16.4f, -23.4f, -14.5f, -23.4f, -12.5f, -24.1f, -8.6f, -24.8f, -6.7f,
1413 -25.3f, -4.8f, -25.7f, -2.8f, -25.9f, -0.8f, -26.0f, 1.2f, -26.0f, 3.2f, -25.8f, 5.2f,
1414 -25.5f, 7.2f, -25.0f, 9.2f, -24.4f, 11.1f, -23.7f, 13.0f, -23.4f, 14.9f, -23.4f, 16.9f,
1415 -23.3f, 18.9f, -22.0f, 20.5f, -20.2f, 21.3f, -18.3f, 21.6f, -16.3f, 21.4f, -15.3f, 19.9f,
1416 -15.3f, 17.8f, -15.2f, 7.8f, -13.5f, 6.4f, -12.4f, 7.2f, -11.4f, 8.9f, -10.2f, 10.5f,
1417 -8.7f, 11.8f, -7.1f, 13.0f, -5.3f, 14.0f, -3.5f, 14.7f, -1.5f, 15.0f, 0.5f, 15.0f,
1418 2.5f, 14.7f, 4.4f, 14.2f, 6.3f, 13.4f, 8.0f, 12.4f, 9.6f, 11.1f, 10.9f, 9.6f,
1419 12.0f, 7.9f, 12.7f, 6.0f, 13.2f, 4.1f, 13.3f, 2.1f, 13.2f, 0.1f, 12.9f, -1.9f,
1420 12.2f, -3.8f, 11.3f, -5.6f, 10.2f, -7.2f, 8.8f, -8.6f, 7.1f, -9.8f, 5.4f, -10.8f,
1421 3.5f, -11.5f, 1.5f, -11.9f, -0.5f, -12.0f, -2.5f, -11.8f, -4.4f, -11.3f, -6.2f, -10.4f,
1422 -8.0f, -9.4f, -9.6f, -8.2f, -10.9f, -6.7f, -11.9f, -4.9f, -12.8f, -3.2f, -13.5f, -3.8f,
1423};
1424
1425constexpr std::array<float, 63 * 2> left_joystick_L_topview = {
1426 -186.7f, -43.7f, -186.4f, -43.7f, -110.6f, -43.4f, -110.6f, -43.1f, -110.7f, -34.3f,
1427 -110.7f, -34.0f, -110.8f, -33.7f, -111.1f, -32.9f, -111.2f, -32.6f, -111.4f, -32.3f,
1428 -111.5f, -32.1f, -111.7f, -31.8f, -111.8f, -31.5f, -112.0f, -31.3f, -112.2f, -31.0f,
1429 -112.4f, -30.8f, -112.8f, -30.3f, -113.0f, -30.1f, -114.1f, -29.1f, -114.3f, -28.9f,
1430 -114.6f, -28.7f, -114.8f, -28.6f, -115.1f, -28.4f, -115.3f, -28.3f, -115.6f, -28.1f,
1431 -115.9f, -28.0f, -116.4f, -27.8f, -116.7f, -27.7f, -117.3f, -27.6f, -117.6f, -27.5f,
1432 -182.9f, -27.6f, -183.5f, -27.7f, -183.8f, -27.8f, -184.4f, -27.9f, -184.6f, -28.1f,
1433 -184.9f, -28.2f, -185.4f, -28.5f, -185.7f, -28.7f, -185.9f, -28.8f, -186.2f, -29.0f,
1434 -186.4f, -29.2f, -187.0f, -29.9f, -187.2f, -30.1f, -187.6f, -30.6f, -187.8f, -30.8f,
1435 -187.9f, -31.1f, -188.1f, -31.3f, -188.2f, -31.6f, -188.4f, -31.9f, -188.5f, -32.1f,
1436 -188.6f, -32.4f, -188.8f, -33.3f, -188.9f, -33.6f, -188.9f, -33.9f, -188.8f, -39.9f,
1437 -188.8f, -40.2f, -188.7f, -41.1f, -188.7f, -41.4f, -188.6f, -41.7f, -188.0f, -43.1f,
1438 -187.9f, -43.4f, -187.6f, -43.6f, -187.3f, -43.7f,
1439};
1440
1441constexpr std::array<float, 44 * 2> left_joystick_ZL_topview = {
1442 -179.4f, -53.3f, -177.4f, -53.3f, -111.2f, -53.3f, -111.3f, -53.3f, -111.5f, -58.6f,
1443 -111.8f, -60.5f, -112.2f, -62.4f, -113.1f, -66.1f, -113.8f, -68.0f, -114.5f, -69.8f,
1444 -115.3f, -71.5f, -116.3f, -73.2f, -117.3f, -74.8f, -118.5f, -76.4f, -119.8f, -77.8f,
1445 -121.2f, -79.1f, -122.8f, -80.2f, -124.4f, -81.2f, -126.2f, -82.0f, -128.1f, -82.6f,
1446 -130.0f, -82.9f, -131.9f, -83.0f, -141.5f, -82.9f, -149.3f, -82.8f, -153.1f, -82.6f,
1447 -155.0f, -82.1f, -156.8f, -81.6f, -158.7f, -80.9f, -160.4f, -80.2f, -162.2f, -79.3f,
1448 -163.8f, -78.3f, -165.4f, -77.2f, -166.9f, -76.0f, -168.4f, -74.7f, -169.7f, -73.3f,
1449 -172.1f, -70.3f, -173.2f, -68.7f, -174.2f, -67.1f, -175.2f, -65.4f, -176.1f, -63.7f,
1450 -178.7f, -58.5f, -179.6f, -56.8f, -180.4f, -55.1f, -181.3f, -53.3f,
1451};
1452
1453void PlayerControlPreview::DrawProBody(QPainter& p, const QPointF center) {
1454 std::array<QPointF, pro_left_handle.size() / 2> qleft_handle;
1455 std::array<QPointF, pro_left_handle.size() / 2> qright_handle;
1456 std::array<QPointF, pro_body.size()> qbody;
1457 constexpr int radius1 = 32;
1458
1459 for (std::size_t point = 0; point < pro_left_handle.size() / 2; ++point) {
1460 qleft_handle[point] =
1461 center + QPointF(pro_left_handle[point * 2], pro_left_handle[point * 2 + 1]);
1462 qright_handle[point] =
1463 center + QPointF(-pro_left_handle[point * 2], pro_left_handle[point * 2 + 1]);
1464 }
1465 for (std::size_t point = 0; point < pro_body.size() / 2; ++point) {
1466 qbody[point] = center + QPointF(pro_body[point * 2], pro_body[point * 2 + 1]);
1467 qbody[pro_body.size() - 1 - point] =
1468 center + QPointF(-pro_body[point * 2], pro_body[point * 2 + 1]);
1469 }
1470
1471 // Draw left handle body
1472 p.setPen(colors.outline);
1473 p.setBrush(colors.left);
1474 DrawPolygon(p, qleft_handle);
1475
1476 // Draw right handle body
1477 p.setBrush(colors.right);
1478 DrawPolygon(p, qright_handle);
1479
1480 // Draw body
1481 p.setBrush(colors.primary);
1482 DrawPolygon(p, qbody);
1483
1484 // Draw joycon circles
1485 p.setBrush(colors.transparent);
1486 p.drawEllipse(center + QPoint(-111, -55), radius1, radius1);
1487 p.drawEllipse(center + QPoint(51, 0), radius1, radius1);
1488}
1489
1490void PlayerControlPreview::DrawGCBody(QPainter& p, const QPointF center) {
1491 std::array<QPointF, gc_left_body.size() / 2> qleft_handle;
1492 std::array<QPointF, gc_left_body.size() / 2> qright_handle;
1493 std::array<QPointF, gc_body.size()> qbody;
1494 std::array<QPointF, 8> left_hex;
1495 std::array<QPointF, 8> right_hex;
1496 constexpr float angle = 2 * 3.1415f / 8;
1497
1498 for (std::size_t point = 0; point < gc_left_body.size() / 2; ++point) {
1499 qleft_handle[point] =
1500 center + QPointF(gc_left_body[point * 2], gc_left_body[point * 2 + 1]);
1501 qright_handle[point] =
1502 center + QPointF(-gc_left_body[point * 2], gc_left_body[point * 2 + 1]);
1503 }
1504 for (std::size_t point = 0; point < gc_body.size() / 2; ++point) {
1505 qbody[point] = center + QPointF(gc_body[point * 2], gc_body[point * 2 + 1]);
1506 qbody[gc_body.size() - 1 - point] =
1507 center + QPointF(-gc_body[point * 2], gc_body[point * 2 + 1]);
1508 }
1509 for (std::size_t point = 0; point < 8; ++point) {
1510 left_hex[point] =
1511 center + QPointF(34 * std::cos(point * angle) - 111, 34 * std::sin(point * angle) - 44);
1512 right_hex[point] =
1513 center + QPointF(26 * std::cos(point * angle) + 61, 26 * std::sin(point * angle) + 37);
1514 }
1515
1516 // Draw body
1517 p.setPen(colors.outline);
1518 p.setBrush(colors.primary);
1519 DrawPolygon(p, qbody);
1520
1521 // Draw left handle body
1522 p.setBrush(colors.left);
1523 DrawPolygon(p, qleft_handle);
1524
1525 // Draw right handle body
1526 p.setBrush(colors.right);
1527 DrawPolygon(p, qright_handle);
1528
1529 DrawText(p, center + QPoint(0, -58), 4.7f, tr("START/PAUSE"));
1530
1531 // Draw right joystick body
1532 p.setBrush(colors.button);
1533 DrawCircle(p, center + QPointF(61, 37), 23.5f);
1534
1535 // Draw joystick details
1536 p.setBrush(colors.transparent);
1537 DrawPolygon(p, left_hex);
1538 DrawPolygon(p, right_hex);
1539}
1540
1541void PlayerControlPreview::DrawHandheldBody(QPainter& p, const QPointF center) {
1542 const std::size_t body_outline_end = handheld_body.size() / 2 - 6;
1543 const std::size_t bezel_outline_end = handheld_bezel.size() / 2 - 6;
1544 const std::size_t bezel_inline_size = 4;
1545 const std::size_t bezel_inline_start = 35;
1546 std::array<QPointF, left_joycon_body.size() / 2> left_joycon;
1547 std::array<QPointF, left_joycon_body.size() / 2> right_joycon;
1548 std::array<QPointF, handheld_body.size() / 2> qhandheld_body;
1549 std::array<QPointF, body_outline_end> qhandheld_body_outline;
1550 std::array<QPointF, handheld_bezel.size() / 2> qhandheld_bezel;
1551 std::array<QPointF, bezel_inline_size> qhandheld_bezel_inline;
1552 std::array<QPointF, bezel_outline_end> qhandheld_bezel_outline;
1553 std::array<QPointF, handheld_buttons.size() / 2> qhandheld_buttons;
1554
1555 for (std::size_t point = 0; point < left_joycon_body.size() / 2; ++point) {
1556 left_joycon[point] =
1557 center + QPointF(left_joycon_body[point * 2], left_joycon_body[point * 2 + 1]);
1558 right_joycon[point] =
1559 center + QPointF(-left_joycon_body[point * 2], left_joycon_body[point * 2 + 1]);
1560 }
1561 for (std::size_t point = 0; point < body_outline_end; ++point) {
1562 qhandheld_body_outline[point] =
1563 center + QPointF(handheld_body[point * 2], handheld_body[point * 2 + 1]);
1564 }
1565 for (std::size_t point = 0; point < handheld_body.size() / 2; ++point) {
1566 qhandheld_body[point] =
1567 center + QPointF(handheld_body[point * 2], handheld_body[point * 2 + 1]);
1568 }
1569 for (std::size_t point = 0; point < handheld_bezel.size() / 2; ++point) {
1570 qhandheld_bezel[point] =
1571 center + QPointF(handheld_bezel[point * 2], handheld_bezel[point * 2 + 1]);
1572 }
1573 for (std::size_t point = 0; point < bezel_outline_end; ++point) {
1574 qhandheld_bezel_outline[point] =
1575 center + QPointF(handheld_bezel[point * 2], handheld_bezel[point * 2 + 1]);
1576 }
1577 for (std::size_t point = 0; point < bezel_inline_size; ++point) {
1578 qhandheld_bezel_inline[point] =
1579 center + QPointF(handheld_bezel[(point + bezel_inline_start) * 2],
1580 handheld_bezel[(point + bezel_inline_start) * 2 + 1]);
1581 }
1582 for (std::size_t point = 0; point < handheld_buttons.size() / 2; ++point) {
1583 qhandheld_buttons[point] =
1584 center + QPointF(handheld_buttons[point * 2], handheld_buttons[point * 2 + 1]);
1585 }
1586
1587 // Draw left joycon
1588 p.setPen(colors.outline);
1589 p.setBrush(colors.left);
1590 DrawPolygon(p, left_joycon);
1591
1592 // Draw right joycon
1593 p.setPen(colors.outline);
1594 p.setBrush(colors.right);
1595 DrawPolygon(p, right_joycon);
1596
1597 // Draw Handheld buttons
1598 p.setPen(colors.outline);
1599 p.setBrush(colors.button);
1600 DrawPolygon(p, qhandheld_buttons);
1601
1602 // Draw handheld body
1603 p.setPen(colors.transparent);
1604 p.setBrush(colors.primary);
1605 DrawPolygon(p, qhandheld_body);
1606 p.setPen(colors.outline);
1607 p.setBrush(colors.transparent);
1608 DrawPolygon(p, qhandheld_body_outline);
1609
1610 // Draw Handheld bezel
1611 p.setPen(colors.transparent);
1612 p.setBrush(colors.button);
1613 DrawPolygon(p, qhandheld_bezel);
1614 p.setPen(colors.outline);
1615 p.setBrush(colors.transparent);
1616 DrawPolygon(p, qhandheld_bezel_outline);
1617 DrawPolygon(p, qhandheld_bezel_inline);
1618}
1619
1620void PlayerControlPreview::DrawDualBody(QPainter& p, const QPointF center) {
1621 std::array<QPointF, left_joycon_body.size() / 2> left_joycon;
1622 std::array<QPointF, left_joycon_body.size() / 2> right_joycon;
1623 std::array<QPointF, left_joycon_slider.size() / 2> qleft_joycon_slider;
1624 std::array<QPointF, left_joycon_slider.size() / 2> qright_joycon_slider;
1625 std::array<QPointF, left_joycon_slider_topview.size() / 2> qleft_joycon_slider_topview;
1626 std::array<QPointF, left_joycon_slider_topview.size() / 2> qright_joycon_slider_topview;
1627 std::array<QPointF, left_joycon_topview.size() / 2> qleft_joycon_topview;
1628 std::array<QPointF, left_joycon_topview.size() / 2> qright_joycon_topview;
1629 constexpr float size = 1.61f;
1630 constexpr float size2 = 0.9f;
1631 constexpr float offset = 209.3f;
1632
1633 for (std::size_t point = 0; point < left_joycon_body.size() / 2; ++point) {
1634 left_joycon[point] = center + QPointF(left_joycon_body[point * 2] * size + offset,
1635 left_joycon_body[point * 2 + 1] * size - 1);
1636 right_joycon[point] = center + QPointF(-left_joycon_body[point * 2] * size - offset,
1637 left_joycon_body[point * 2 + 1] * size - 1);
1638 }
1639 for (std::size_t point = 0; point < left_joycon_slider.size() / 2; ++point) {
1640 qleft_joycon_slider[point] =
1641 center + QPointF(left_joycon_slider[point * 2], left_joycon_slider[point * 2 + 1]);
1642 qright_joycon_slider[point] =
1643 center + QPointF(-left_joycon_slider[point * 2], left_joycon_slider[point * 2 + 1]);
1644 }
1645 for (std::size_t point = 0; point < left_joycon_topview.size() / 2; ++point) {
1646 qleft_joycon_topview[point] =
1647 center + QPointF(left_joycon_topview[point * 2] * size2 - 52,
1648 left_joycon_topview[point * 2 + 1] * size2 - 52);
1649 qright_joycon_topview[point] =
1650 center + QPointF(-left_joycon_topview[point * 2] * size2 + 52,
1651 left_joycon_topview[point * 2 + 1] * size2 - 52);
1652 }
1653 for (std::size_t point = 0; point < left_joycon_slider_topview.size() / 2; ++point) {
1654 qleft_joycon_slider_topview[point] =
1655 center + QPointF(left_joycon_slider_topview[point * 2] * size2 - 52,
1656 left_joycon_slider_topview[point * 2 + 1] * size2 - 52);
1657 qright_joycon_slider_topview[point] =
1658 center + QPointF(-left_joycon_slider_topview[point * 2] * size2 + 52,
1659 left_joycon_slider_topview[point * 2 + 1] * size2 - 52);
1660 }
1661
1662 // right joycon body
1663 p.setPen(colors.outline);
1664 p.setBrush(colors.right);
1665 DrawPolygon(p, right_joycon);
1666
1667 // Left joycon body
1668 p.setPen(colors.outline);
1669 p.setBrush(colors.left);
1670 DrawPolygon(p, left_joycon);
1671
1672 // Slider release button top view
1673 p.setBrush(colors.button);
1674 DrawRoundRectangle(p, center + QPoint(-149, -108), 12, 11, 2);
1675 DrawRoundRectangle(p, center + QPoint(149, -108), 12, 11, 2);
1676
1677 // Joycon slider top view
1678 p.setBrush(colors.slider);
1679 DrawPolygon(p, qleft_joycon_slider_topview);
1680 p.drawLine(center + QPointF(-133.8f, -99.0f), center + QPointF(-133.8f, -78.5f));
1681 DrawPolygon(p, qright_joycon_slider_topview);
1682 p.drawLine(center + QPointF(133.8f, -99.0f), center + QPointF(133.8f, -78.5f));
1683
1684 // Joycon body top view
1685 p.setBrush(colors.left);
1686 DrawPolygon(p, qleft_joycon_topview);
1687 p.setBrush(colors.right);
1688 DrawPolygon(p, qright_joycon_topview);
1689
1690 // Right SR and SL sideview buttons
1691 p.setPen(colors.outline);
1692 p.setBrush(colors.slider_button);
1693 DrawRoundRectangle(p, center + QPoint(19, 47), 7, 22, 1);
1694 DrawRoundRectangle(p, center + QPoint(19, -62), 7, 22, 1);
1695
1696 // Left SR and SL sideview buttons
1697 DrawRoundRectangle(p, center + QPoint(-19, 47), 7, 22, 1);
1698 DrawRoundRectangle(p, center + QPoint(-19, -62), 7, 22, 1);
1699
1700 // Right Sideview body
1701 p.setBrush(colors.slider);
1702 DrawPolygon(p, qright_joycon_slider);
1703
1704 // Left Sideview body
1705 p.setBrush(colors.slider);
1706 DrawPolygon(p, qleft_joycon_slider);
1707}
1708
1709void PlayerControlPreview::DrawLeftBody(QPainter& p, const QPointF center) {
1710 std::array<QPointF, left_joycon_body.size() / 2> left_joycon;
1711 std::array<QPointF, left_joycon_sideview.size() / 2> qleft_joycon_sideview;
1712 std::array<QPointF, left_joycon_body_trigger.size() / 2> qleft_joycon_trigger;
1713 std::array<QPointF, left_joycon_slider.size() / 2> qleft_joycon_slider;
1714 std::array<QPointF, left_joycon_slider_topview.size() / 2> qleft_joycon_slider_topview;
1715 std::array<QPointF, left_joycon_topview.size() / 2> qleft_joycon_topview;
1716 constexpr float size = 1.78f;
1717 constexpr float size2 = 1.1115f;
1718 constexpr float offset = 312.39f;
1719 constexpr float offset2 = 335;
1720
1721 for (std::size_t point = 0; point < left_joycon_body.size() / 2; ++point) {
1722 left_joycon[point] = center + QPointF(left_joycon_body[point * 2] * size + offset,
1723 left_joycon_body[point * 2 + 1] * size - 1);
1724 }
1725
1726 for (std::size_t point = 0; point < left_joycon_sideview.size() / 2; ++point) {
1727 qleft_joycon_sideview[point] =
1728 center + QPointF(left_joycon_sideview[point * 2] * size2 + offset2,
1729 left_joycon_sideview[point * 2 + 1] * size2 + 2);
1730 }
1731 for (std::size_t point = 0; point < left_joycon_slider.size() / 2; ++point) {
1732 qleft_joycon_slider[point] = center + QPointF(left_joycon_slider[point * 2] * size2 + 81,
1733 left_joycon_slider[point * 2 + 1] * size2);
1734 }
1735 for (std::size_t point = 0; point < left_joycon_body_trigger.size() / 2; ++point) {
1736 qleft_joycon_trigger[point] =
1737 center + QPointF(left_joycon_body_trigger[point * 2] * size2 + offset2,
1738 left_joycon_body_trigger[point * 2 + 1] * size2 + 2);
1739 }
1740 for (std::size_t point = 0; point < left_joycon_topview.size() / 2; ++point) {
1741 qleft_joycon_topview[point] =
1742 center + QPointF(left_joycon_topview[point * 2], left_joycon_topview[point * 2 + 1]);
1743 }
1744 for (std::size_t point = 0; point < left_joycon_slider_topview.size() / 2; ++point) {
1745 qleft_joycon_slider_topview[point] =
1746 center + QPointF(left_joycon_slider_topview[point * 2],
1747 left_joycon_slider_topview[point * 2 + 1]);
1748 }
1749
1750 // Joycon body
1751 p.setPen(colors.outline);
1752 p.setBrush(colors.left);
1753 DrawPolygon(p, left_joycon);
1754 DrawPolygon(p, qleft_joycon_trigger);
1755
1756 // Slider release button top view
1757 p.setBrush(colors.button);
1758 DrawRoundRectangle(p, center + QPoint(-107, -62), 14, 12, 2);
1759
1760 // Joycon slider top view
1761 p.setBrush(colors.slider);
1762 DrawPolygon(p, qleft_joycon_slider_topview);
1763 p.drawLine(center + QPointF(-91.1f, -51.7f), center + QPointF(-91.1f, -26.5f));
1764
1765 // Joycon body top view
1766 p.setBrush(colors.left);
1767 DrawPolygon(p, qleft_joycon_topview);
1768
1769 // Slider release button
1770 p.setBrush(colors.button);
1771 DrawRoundRectangle(p, center + QPoint(175, -110), 12, 14, 2);
1772
1773 // Sideview body
1774 p.setBrush(colors.left);
1775 DrawPolygon(p, qleft_joycon_sideview);
1776 p.setBrush(colors.slider);
1777 DrawPolygon(p, qleft_joycon_slider);
1778
1779 const QPointF sideview_center = QPointF(155, 0) + center;
1780
1781 // Sideview slider body
1782 p.setBrush(colors.slider);
1783 DrawRoundRectangle(p, sideview_center + QPointF(0, -5), 28, 253, 3);
1784 p.setBrush(colors.button2);
1785 DrawRoundRectangle(p, sideview_center + QPointF(0, 97), 22.44f, 44.66f, 3);
1786
1787 // Slider decorations
1788 p.setPen(colors.outline);
1789 p.setBrush(colors.slider_arrow);
1790 DrawArrow(p, sideview_center + QPoint(0, 83), Direction::Down, 2.2f);
1791 DrawArrow(p, sideview_center + QPoint(0, 96), Direction::Down, 2.2f);
1792 DrawArrow(p, sideview_center + QPoint(0, 109), Direction::Down, 2.2f);
1793 DrawCircle(p, sideview_center + QPointF(0, 19), 4.44f);
1794
1795 // LED indicators
1796 const float led_size = 5.0f;
1797 const QPointF led_position = sideview_center + QPointF(0, -36);
1798 int led_count = 0;
1799 for (const auto color : led_color) {
1800 p.setBrush(color);
1801 DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
1802 }
1803}
1804
1805void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) {
1806 std::array<QPointF, left_joycon_body.size() / 2> right_joycon;
1807 std::array<QPointF, left_joycon_sideview.size() / 2> qright_joycon_sideview;
1808 std::array<QPointF, left_joycon_body_trigger.size() / 2> qright_joycon_trigger;
1809 std::array<QPointF, left_joycon_slider.size() / 2> qright_joycon_slider;
1810 std::array<QPointF, left_joycon_slider_topview.size() / 2> qright_joycon_slider_topview;
1811 std::array<QPointF, left_joycon_topview.size() / 2> qright_joycon_topview;
1812 constexpr float size = 1.78f;
1813 constexpr float size2 = 1.1115f;
1814 constexpr float offset = 312.39f;
1815 constexpr float offset2 = 335;
1816
1817 for (std::size_t point = 0; point < left_joycon_body.size() / 2; ++point) {
1818 right_joycon[point] = center + QPointF(-left_joycon_body[point * 2] * size - offset,
1819 left_joycon_body[point * 2 + 1] * size - 1);
1820 }
1821
1822 for (std::size_t point = 0; point < left_joycon_sideview.size() / 2; ++point) {
1823 qright_joycon_sideview[point] =
1824 center + QPointF(-left_joycon_sideview[point * 2] * size2 - offset2,
1825 left_joycon_sideview[point * 2 + 1] * size2 + 2);
1826 }
1827 for (std::size_t point = 0; point < left_joycon_body_trigger.size() / 2; ++point) {
1828 qright_joycon_trigger[point] =
1829 center + QPointF(-left_joycon_body_trigger[point * 2] * size2 - offset2,
1830 left_joycon_body_trigger[point * 2 + 1] * size2 + 2);
1831 }
1832 for (std::size_t point = 0; point < left_joycon_slider.size() / 2; ++point) {
1833 qright_joycon_slider[point] = center + QPointF(-left_joycon_slider[point * 2] * size2 - 81,
1834 left_joycon_slider[point * 2 + 1] * size2);
1835 }
1836 for (std::size_t point = 0; point < left_joycon_topview.size() / 2; ++point) {
1837 qright_joycon_topview[point] =
1838 center + QPointF(-left_joycon_topview[point * 2], left_joycon_topview[point * 2 + 1]);
1839 }
1840 for (std::size_t point = 0; point < left_joycon_slider_topview.size() / 2; ++point) {
1841 qright_joycon_slider_topview[point] =
1842 center + QPointF(-left_joycon_slider_topview[point * 2],
1843 left_joycon_slider_topview[point * 2 + 1]);
1844 }
1845
1846 // Joycon body
1847 p.setPen(colors.outline);
1848 p.setBrush(colors.left);
1849 DrawPolygon(p, right_joycon);
1850 DrawPolygon(p, qright_joycon_trigger);
1851
1852 // Slider release button top view
1853 p.setBrush(colors.button);
1854 DrawRoundRectangle(p, center + QPoint(107, -62), 14, 12, 2);
1855
1856 // Joycon slider top view
1857 p.setBrush(colors.slider);
1858 DrawPolygon(p, qright_joycon_slider_topview);
1859 p.drawLine(center + QPointF(91.1f, -51.7f), center + QPointF(91.1f, -26.5f));
1860
1861 // Joycon body top view
1862 p.setBrush(colors.left);
1863 DrawPolygon(p, qright_joycon_topview);
1864
1865 // Slider release button
1866 p.setBrush(colors.button);
1867 DrawRoundRectangle(p, center + QPoint(-175, -110), 12, 14, 2);
1868
1869 // Sideview body
1870 p.setBrush(colors.left);
1871 DrawPolygon(p, qright_joycon_sideview);
1872 p.setBrush(colors.slider);
1873 DrawPolygon(p, qright_joycon_slider);
1874
1875 const QPointF sideview_center = QPointF(-155, 0) + center;
1876
1877 // Sideview slider body
1878 p.setBrush(colors.slider);
1879 DrawRoundRectangle(p, sideview_center + QPointF(0, -5), 28, 253, 3);
1880 p.setBrush(colors.button2);
1881 DrawRoundRectangle(p, sideview_center + QPointF(0, 97), 22.44f, 44.66f, 3);
1882
1883 // Slider decorations
1884 p.setPen(colors.outline);
1885 p.setBrush(colors.slider_arrow);
1886 DrawArrow(p, sideview_center + QPoint(0, 83), Direction::Down, 2.2f);
1887 DrawArrow(p, sideview_center + QPoint(0, 96), Direction::Down, 2.2f);
1888 DrawArrow(p, sideview_center + QPoint(0, 109), Direction::Down, 2.2f);
1889 DrawCircle(p, sideview_center + QPointF(0, 19), 4.44f);
1890
1891 // LED indicators
1892 const float led_size = 5.0f;
1893 const QPointF led_position = sideview_center + QPointF(0, -36);
1894 int led_count = 0;
1895 for (const auto color : led_color) {
1896 p.setBrush(color);
1897 DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
1898 }
1899}
1900
1901void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bool left_pressed,
1902 bool right_pressed) {
1903 std::array<QPointF, pro_left_trigger.size() / 2> qleft_trigger;
1904 std::array<QPointF, pro_left_trigger.size() / 2> qright_trigger;
1905 std::array<QPointF, pro_body_top.size()> qbody_top;
1906
1907 for (std::size_t point = 0; point < pro_left_trigger.size() / 2; ++point) {
1908 qleft_trigger[point] =
1909 center + QPointF(pro_left_trigger[point * 2],
1910 pro_left_trigger[point * 2 + 1] + (left_pressed ? 2 : 0));
1911 qright_trigger[point] =
1912 center + QPointF(-pro_left_trigger[point * 2],
1913 pro_left_trigger[point * 2 + 1] + (right_pressed ? 2 : 0));
1914 }
1915
1916 for (std::size_t point = 0; point < pro_body_top.size() / 2; ++point) {
1917 qbody_top[pro_body_top.size() - 1 - point] =
1918 center + QPointF(-pro_body_top[point * 2], pro_body_top[point * 2 + 1]);
1919 qbody_top[point] = center + QPointF(pro_body_top[point * 2], pro_body_top[point * 2 + 1]);
1920 }
1921
1922 // Pro body detail
1923 p.setPen(colors.outline);
1924 p.setBrush(colors.primary);
1925 DrawPolygon(p, qbody_top);
1926
1927 // Left trigger
1928 p.setBrush(left_pressed ? colors.highlight : colors.button);
1929 DrawPolygon(p, qleft_trigger);
1930
1931 // Right trigger
1932 p.setBrush(right_pressed ? colors.highlight : colors.button);
1933 DrawPolygon(p, qright_trigger);
1934}
1935
1936void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, bool left_pressed,
1937 bool right_pressed) {
1938 std::array<QPointF, left_gc_trigger.size() / 2> qleft_trigger;
1939 std::array<QPointF, left_gc_trigger.size() / 2> qright_trigger;
1940
1941 for (std::size_t point = 0; point < left_gc_trigger.size() / 2; ++point) {
1942 qleft_trigger[point] =
1943 center + QPointF(left_gc_trigger[point * 2],
1944 left_gc_trigger[point * 2 + 1] + (left_pressed ? 10 : 0));
1945 qright_trigger[point] =
1946 center + QPointF(-left_gc_trigger[point * 2],
1947 left_gc_trigger[point * 2 + 1] + (right_pressed ? 10 : 0));
1948 }
1949
1950 // Left trigger
1951 p.setPen(colors.outline);
1952 p.setBrush(left_pressed ? colors.highlight : colors.button);
1953 DrawPolygon(p, qleft_trigger);
1954
1955 // Right trigger
1956 p.setBrush(right_pressed ? colors.highlight : colors.button);
1957 DrawPolygon(p, qright_trigger);
1958
1959 // Draw L text
1960 p.setPen(colors.transparent);
1961 p.setBrush(colors.font);
1962 DrawSymbol(p, center + QPointF(-132, -119 + (left_pressed ? 10 : 0)), Symbol::L, 1.7f);
1963
1964 // Draw R text
1965 p.setPen(colors.transparent);
1966 p.setBrush(colors.font);
1967 DrawSymbol(p, center + QPointF(121.5f, -119 + (right_pressed ? 10 : 0)), Symbol::R, 1.7f);
1968}
1969
1970void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF center,
1971 bool left_pressed, bool right_pressed) {
1972 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
1973 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
1974
1975 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
1976 qleft_trigger[point] =
1977 center + QPointF(left_joycon_trigger[point * 2],
1978 left_joycon_trigger[point * 2 + 1] + (left_pressed ? 0.5f : 0));
1979 qright_trigger[point] =
1980 center + QPointF(-left_joycon_trigger[point * 2],
1981 left_joycon_trigger[point * 2 + 1] + (right_pressed ? 0.5f : 0));
1982 }
1983
1984 // Left trigger
1985 p.setPen(colors.outline);
1986 p.setBrush(left_pressed ? colors.highlight : colors.button);
1987 DrawPolygon(p, qleft_trigger);
1988
1989 // Right trigger
1990 p.setBrush(right_pressed ? colors.highlight : colors.button);
1991 DrawPolygon(p, qright_trigger);
1992}
1993
1994void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, bool left_pressed,
1995 bool right_pressed) {
1996 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
1997 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
1998 constexpr float size = 1.62f;
1999 constexpr float offset = 210.6f;
2000 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
2001 qleft_trigger[point] =
2002 center + QPointF(left_joycon_trigger[point * 2] * size + offset,
2003 left_joycon_trigger[point * 2 + 1] * size + (left_pressed ? 0.5f : 0));
2004 qright_trigger[point] = center + QPointF(-left_joycon_trigger[point * 2] * size - offset,
2005 left_joycon_trigger[point * 2 + 1] * size +
2006 (right_pressed ? 0.5f : 0));
2007 }
2008
2009 // Left trigger
2010 p.setPen(colors.outline);
2011 p.setBrush(left_pressed ? colors.highlight : colors.button);
2012 DrawPolygon(p, qleft_trigger);
2013
2014 // Right trigger
2015 p.setBrush(right_pressed ? colors.highlight : colors.button);
2016 DrawPolygon(p, qright_trigger);
2017}
2018
2019void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF center,
2020 bool left_pressed, bool right_pressed) {
2021 std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger;
2022 std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger;
2023 constexpr float size = 0.9f;
2024
2025 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
2026 qleft_trigger[point] = center + QPointF(left_joystick_L_topview[point * 2] * size - 50,
2027 left_joystick_L_topview[point * 2 + 1] * size - 52);
2028 }
2029 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
2030 qright_trigger[point] =
2031 center + QPointF(-left_joystick_L_topview[point * 2] * size + 50,
2032 left_joystick_L_topview[point * 2 + 1] * size - 52);
2033 }
2034
2035 p.setPen(colors.outline);
2036 p.setBrush(left_pressed ? colors.highlight : colors.button);
2037 DrawPolygon(p, qleft_trigger);
2038 p.setBrush(right_pressed ? colors.highlight : colors.button);
2039 DrawPolygon(p, qright_trigger);
2040
2041 // Draw L text
2042 p.setPen(colors.transparent);
2043 p.setBrush(colors.font2);
2044 DrawSymbol(p, center + QPointF(-183, -84), Symbol::L, 1.0f);
2045
2046 // Draw R text
2047 p.setPen(colors.transparent);
2048 p.setBrush(colors.font2);
2049 DrawSymbol(p, center + QPointF(177, -84), Symbol::R, 1.0f);
2050}
2051
2052void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF center,
2053 bool left_pressed, bool right_pressed) {
2054 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger;
2055 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger;
2056 constexpr float size = 0.9f;
2057
2058 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
2059 qleft_trigger[point] =
2060 center + QPointF(left_joystick_ZL_topview[point * 2] * size - 52,
2061 left_joystick_ZL_topview[point * 2 + 1] * size - 52);
2062 }
2063 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
2064 qright_trigger[point] =
2065 center + QPointF(-left_joystick_ZL_topview[point * 2] * size + 52,
2066 left_joystick_ZL_topview[point * 2 + 1] * size - 52);
2067 }
2068
2069 p.setPen(colors.outline);
2070 p.setBrush(left_pressed ? colors.highlight : colors.button);
2071 DrawPolygon(p, qleft_trigger);
2072 p.setBrush(right_pressed ? colors.highlight : colors.button);
2073 DrawPolygon(p, qright_trigger);
2074
2075 // Draw ZL text
2076 p.setPen(colors.transparent);
2077 p.setBrush(colors.font2);
2078 DrawSymbol(p, center + QPointF(-180, -113), Symbol::ZL, 1.0f);
2079
2080 // Draw ZR text
2081 p.setPen(colors.transparent);
2082 p.setBrush(colors.font2);
2083 DrawSymbol(p, center + QPointF(180, -113), Symbol::ZR, 1.0f);
2084}
2085
2086void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, bool left_pressed) {
2087 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
2088 constexpr float size = 1.78f;
2089 constexpr float offset = 311.5f;
2090
2091 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
2092 qleft_trigger[point] = center + QPointF(left_joycon_trigger[point * 2] * size + offset,
2093 left_joycon_trigger[point * 2 + 1] * size -
2094 (left_pressed ? 0.5f : 1.0f));
2095 }
2096
2097 p.setPen(colors.outline);
2098 p.setBrush(left_pressed ? colors.highlight : colors.button);
2099 DrawPolygon(p, qleft_trigger);
2100}
2101
2102void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center, bool left_pressed) {
2103 std::array<QPointF, left_joycon_sideview_zl.size() / 2> qleft_trigger;
2104 constexpr float size = 1.1115f;
2105 constexpr float offset2 = 335;
2106
2107 for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) {
2108 qleft_trigger[point] = center + QPointF(left_joycon_sideview_zl[point * 2] * size + offset2,
2109 left_joycon_sideview_zl[point * 2 + 1] * size +
2110 (left_pressed ? 1.5f : 1.0f));
2111 }
2112
2113 p.setPen(colors.outline);
2114 p.setBrush(left_pressed ? colors.highlight : colors.button);
2115 DrawPolygon(p, qleft_trigger);
2116 p.drawArc(center.x() + 158, center.y() + (left_pressed ? -203.5f : -204.0f), 77, 77, 225 * 16,
2117 44 * 16);
2118}
2119
2120void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF center,
2121 bool left_pressed) {
2122 std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger;
2123
2124 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
2125 qleft_trigger[point] = center + QPointF(left_joystick_L_topview[point * 2],
2126 left_joystick_L_topview[point * 2 + 1]);
2127 }
2128
2129 p.setPen(colors.outline);
2130 p.setBrush(left_pressed ? colors.highlight : colors.button);
2131 DrawPolygon(p, qleft_trigger);
2132
2133 // Draw L text
2134 p.setPen(colors.transparent);
2135 p.setBrush(colors.font2);
2136 DrawSymbol(p, center + QPointF(-143, -36), Symbol::L, 1.0f);
2137}
2138
2139void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF center,
2140 bool left_pressed) {
2141 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger;
2142
2143 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
2144 qleft_trigger[point] = center + QPointF(left_joystick_ZL_topview[point * 2],
2145 left_joystick_ZL_topview[point * 2 + 1]);
2146 }
2147
2148 p.setPen(colors.outline);
2149 p.setBrush(left_pressed ? colors.highlight : colors.button);
2150 DrawPolygon(p, qleft_trigger);
2151
2152 // Draw ZL text
2153 p.setPen(colors.transparent);
2154 p.setBrush(colors.font2);
2155 DrawSymbol(p, center + QPointF(-140, -68), Symbol::ZL, 1.0f);
2156}
2157
2158void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center,
2159 bool right_pressed) {
2160 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
2161 constexpr float size = 1.78f;
2162 constexpr float offset = 311.5f;
2163
2164 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
2165 qright_trigger[point] = center + QPointF(-left_joycon_trigger[point * 2] * size - offset,
2166 left_joycon_trigger[point * 2 + 1] * size -
2167 (right_pressed ? 0.5f : 1.0f));
2168 }
2169
2170 p.setPen(colors.outline);
2171 p.setBrush(right_pressed ? colors.highlight : colors.button);
2172 DrawPolygon(p, qright_trigger);
2173}
2174
2175void PlayerControlPreview::DrawRightZTriggers(QPainter& p, const QPointF center,
2176 bool right_pressed) {
2177 std::array<QPointF, left_joycon_sideview_zl.size() / 2> qright_trigger;
2178 constexpr float size = 1.1115f;
2179 constexpr float offset2 = 335;
2180
2181 for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) {
2182 qright_trigger[point] =
2183 center +
2184 QPointF(-left_joycon_sideview_zl[point * 2] * size - offset2,
2185 left_joycon_sideview_zl[point * 2 + 1] * size + (right_pressed ? 0.5f : 0) + 1);
2186 }
2187
2188 p.setPen(colors.outline);
2189 p.setBrush(right_pressed ? colors.highlight : colors.button);
2190 DrawPolygon(p, qright_trigger);
2191 p.drawArc(center.x() - 236, center.y() + (right_pressed ? -203.5f : -204.0f), 77, 77, 271 * 16,
2192 44 * 16);
2193}
2194
2195void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF center,
2196 bool right_pressed) {
2197 std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger;
2198
2199 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
2200 qright_trigger[point] = center + QPointF(-left_joystick_L_topview[point * 2],
2201 left_joystick_L_topview[point * 2 + 1]);
2202 }
2203
2204 p.setPen(colors.outline);
2205 p.setBrush(right_pressed ? colors.highlight : colors.button);
2206 DrawPolygon(p, qright_trigger);
2207
2208 // Draw R text
2209 p.setPen(colors.transparent);
2210 p.setBrush(colors.font2);
2211 DrawSymbol(p, center + QPointF(137, -36), Symbol::R, 1.0f);
2212}
2213
2214void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF center,
2215 bool right_pressed) {
2216 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger;
2217
2218 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
2219 qright_trigger[point] = center + QPointF(-left_joystick_ZL_topview[point * 2],
2220 left_joystick_ZL_topview[point * 2 + 1]);
2221 }
2222
2223 p.setPen(colors.outline);
2224 p.setBrush(right_pressed ? colors.highlight : colors.button);
2225 DrawPolygon(p, qright_trigger);
2226
2227 // Draw ZR text
2228 p.setPen(colors.transparent);
2229 p.setBrush(colors.font2);
2230 DrawSymbol(p, center + QPointF(140, -68), Symbol::ZR, 1.0f);
2231}
2232
2233void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float size,
2234 bool pressed) {
2235 const float radius1 = 13.0f * size;
2236 const float radius2 = 9.0f * size;
2237
2238 // Outer circle
2239 p.setPen(colors.outline);
2240 p.setBrush(pressed ? colors.highlight : colors.button);
2241 DrawCircle(p, center, radius1);
2242
2243 // Cross
2244 p.drawLine(center - QPoint(radius1, 0), center + QPoint(radius1, 0));
2245 p.drawLine(center - QPoint(0, radius1), center + QPoint(0, radius1));
2246
2247 // Inner circle
2248 p.setBrush(pressed ? colors.highlight2 : colors.button2);
2249 DrawCircle(p, center, radius2);
2250}
2251
2252void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF center, float angle,
2253 float size, bool pressed) {
2254 QVector<QPointF> joystick;
2255 joystick.reserve(static_cast<int>(left_joystick_sideview.size() / 2));
2256
2257 for (std::size_t point = 0; point < left_joystick_sideview.size() / 2; ++point) {
2258 joystick.append(QPointF(left_joystick_sideview[point * 2] * size + (pressed ? 1 : 0),
2259 left_joystick_sideview[point * 2 + 1] * size - 1));
2260 }
2261
2262 // Rotate joystick
2263 QTransform t;
2264 t.translate(center.x(), center.y());
2265 t.rotate(18 * angle);
2266 QPolygonF p2 = t.map(QPolygonF(joystick));
2267
2268 // Draw joystick
2269 p.setPen(colors.outline);
2270 p.setBrush(pressed ? colors.highlight : colors.button);
2271 p.drawPolygon(p2);
2272 p.drawLine(p2.at(1), p2.at(30));
2273 p.drawLine(p2.at(32), p2.at(71));
2274}
2275
2276void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, bool pressed) {
2277 // Outer circle
2278 p.setPen(colors.outline);
2279 p.setBrush(pressed ? colors.highlight : colors.button);
2280 DrawCircle(p, center, 24.0f);
2281
2282 // Inner circle
2283 p.setBrush(pressed ? colors.highlight2 : colors.button2);
2284 DrawCircle(p, center, 17.0f);
2285}
2286
2287void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, bool pressed) {
2288 // Outer circle
2289 p.setPen(colors.outline);
2290 p.setBrush(pressed ? colors.highlight : colors.button);
2291 DrawCircle(p, center, 26.0f);
2292
2293 // Inner circle
2294 p.setBrush(pressed ? colors.highlight2 : colors.button2);
2295 DrawCircle(p, center, 19.0f);
2296 p.setBrush(colors.transparent);
2297 DrawCircle(p, center, 13.5f);
2298 DrawCircle(p, center, 7.5f);
2299}
2300
2301void PlayerControlPreview::DrawRawJoystick(QPainter& p, const QPointF center, const QPointF value,
2302 const Input::AnalogProperties properties) {
2303 constexpr float size = 45.0f;
2304 const float range = size * properties.range;
2305 const float deadzone = size * properties.deadzone;
2306
2307 // Max range zone circle
2308 p.setPen(colors.outline);
2309 p.setBrush(colors.transparent);
2310 QPen pen = p.pen();
2311 pen.setStyle(Qt::DotLine);
2312 p.setPen(pen);
2313 DrawCircle(p, center, range);
2314
2315 // Deadzone circle
2316 pen.setColor(colors.deadzone);
2317 p.setPen(pen);
2318 DrawCircle(p, center, deadzone);
2319
2320 // Dot pointer
2321 p.setPen(colors.indicator);
2322 p.setBrush(colors.indicator);
2323 DrawCircle(p, center + (value * range), 2);
2324}
2325
2326void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width,
2327 float height, Direction direction, float radius) {
2328 p.setBrush(button_color);
2329 if (pressed) {
2330 switch (direction) {
2331 case Direction::Left:
2332 center.setX(center.x() - 1);
2333 break;
2334 case Direction::Right:
2335 center.setX(center.x() + 1);
2336 break;
2337 case Direction::Down:
2338 center.setY(center.y() + 1);
2339 break;
2340 case Direction::Up:
2341 center.setY(center.y() - 1);
2342 break;
2343 case Direction::None:
2344 break;
2345 }
2346 p.setBrush(colors.highlight);
2347 }
2348 QRectF rect = {center.x() - width, center.y() - height, width * 2.0f, height * 2.0f};
2349 p.drawRoundedRect(rect, radius, radius);
2350}
2351void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center, bool pressed,
2352 int button_size) {
2353 p.setPen(colors.outline);
2354 p.setBrush(pressed ? colors.highlight : colors.button);
2355 DrawRectangle(p, center, button_size, button_size / 3.0f);
2356}
2357void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, bool pressed,
2358 int button_size) {
2359 // Draw outer line
2360 p.setPen(colors.outline);
2361 p.setBrush(pressed ? colors.highlight : colors.button);
2362 DrawRectangle(p, center, button_size, button_size / 3.0f);
2363 DrawRectangle(p, center, button_size / 3.0f, button_size);
2364
2365 // Scale down size
2366 button_size *= 0.88f;
2367
2368 // Draw inner color
2369 p.setPen(colors.transparent);
2370 DrawRectangle(p, center, button_size, button_size / 3.0f);
2371 DrawRectangle(p, center, button_size / 3.0f, button_size);
2372}
2373
2374void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, bool pressed) {
2375 std::array<QPointF, gc_button_x.size() / 2> button_x;
2376
2377 for (std::size_t point = 0; point < gc_button_x.size() / 2; ++point) {
2378 button_x[point] = center + QPointF(gc_button_x[point * 2], gc_button_x[point * 2 + 1]);
2379 }
2380
2381 p.setPen(colors.outline);
2382 p.setBrush(pressed ? colors.highlight : colors.button);
2383 DrawPolygon(p, button_x);
2384}
2385
2386void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, bool pressed) {
2387 std::array<QPointF, gc_button_y.size() / 2> button_x;
2388
2389 for (std::size_t point = 0; point < gc_button_y.size() / 2; ++point) {
2390 button_x[point] = center + QPointF(gc_button_y[point * 2], gc_button_y[point * 2 + 1]);
2391 }
2392
2393 p.setPen(colors.outline);
2394 p.setBrush(pressed ? colors.highlight : colors.button);
2395 DrawPolygon(p, button_x);
2396}
2397
2398void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center, bool pressed) {
2399 std::array<QPointF, gc_button_z.size() / 2> button_x;
2400
2401 for (std::size_t point = 0; point < gc_button_z.size() / 2; ++point) {
2402 button_x[point] = center + QPointF(gc_button_z[point * 2],
2403 gc_button_z[point * 2 + 1] + (pressed ? 1 : 0));
2404 }
2405
2406 p.setPen(colors.outline);
2407 p.setBrush(pressed ? colors.highlight : colors.button2);
2408 DrawPolygon(p, button_x);
2409}
2410
2411void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center, bool pressed,
2412 float button_size) {
2413 p.setBrush(button_color);
2414 if (pressed) {
2415 p.setBrush(colors.highlight);
2416 }
2417 p.drawEllipse(center, button_size, button_size);
2418}
2419
2420void PlayerControlPreview::DrawArrowButtonOutline(QPainter& p, const QPointF center, float size) {
2421 const std::size_t arrow_points = up_arrow_button.size() / 2;
2422 std::array<QPointF, (arrow_points - 1) * 4> arrow_button_outline;
2423
2424 for (std::size_t point = 0; point < arrow_points - 1; ++point) {
2425 arrow_button_outline[point] = center + QPointF(up_arrow_button[point * 2] * size,
2426 up_arrow_button[point * 2 + 1] * size);
2427 arrow_button_outline[(arrow_points - 1) * 2 - point - 1] =
2428 center +
2429 QPointF(up_arrow_button[point * 2 + 1] * size, up_arrow_button[point * 2] * size);
2430 arrow_button_outline[(arrow_points - 1) * 2 + point] =
2431 center +
2432 QPointF(-up_arrow_button[point * 2] * size, -up_arrow_button[point * 2 + 1] * size);
2433 arrow_button_outline[(arrow_points - 1) * 4 - point - 1] =
2434 center +
2435 QPointF(-up_arrow_button[point * 2 + 1] * size, -up_arrow_button[point * 2] * size);
2436 }
2437 // Draw arrow button outline
2438 p.setPen(colors.outline);
2439 p.setBrush(colors.transparent);
2440 DrawPolygon(p, arrow_button_outline);
2441}
2442
2443void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
2444 const Direction direction, bool pressed, float size) {
2445 std::array<QPointF, up_arrow_button.size() / 2> arrow_button;
2446 QPoint offset;
2447
2448 for (std::size_t point = 0; point < up_arrow_button.size() / 2; ++point) {
2449 switch (direction) {
2450 case Direction::Up:
2451 arrow_button[point] = center + QPointF(up_arrow_button[point * 2] * size,
2452 up_arrow_button[point * 2 + 1] * size);
2453 break;
2454 case Direction::Left:
2455 arrow_button[point] = center + QPointF(up_arrow_button[point * 2 + 1] * size,
2456 up_arrow_button[point * 2] * size);
2457 break;
2458 case Direction::Right:
2459 arrow_button[point] = center + QPointF(-up_arrow_button[point * 2 + 1] * size,
2460 up_arrow_button[point * 2] * size);
2461 break;
2462 case Direction::Down:
2463 arrow_button[point] = center + QPointF(up_arrow_button[point * 2] * size,
2464 -up_arrow_button[point * 2 + 1] * size);
2465 break;
2466 case Direction::None:
2467 break;
2468 }
2469 }
2470
2471 // Draw arrow button
2472 p.setPen(pressed ? colors.highlight : colors.button);
2473 p.setBrush(pressed ? colors.highlight : colors.button);
2474 DrawPolygon(p, arrow_button);
2475
2476 switch (direction) {
2477 case Direction::Up:
2478 offset = QPoint(0, -20 * size);
2479 break;
2480 case Direction::Left:
2481 offset = QPoint(-20 * size, 0);
2482 break;
2483 case Direction::Right:
2484 offset = QPoint(20 * size, 0);
2485 break;
2486 case Direction::Down:
2487 offset = QPoint(0, 20 * size);
2488 break;
2489 case Direction::None:
2490 offset = QPoint(0, 0);
2491 break;
2492 }
2493
2494 // Draw arrow icon
2495 p.setPen(colors.font2);
2496 p.setBrush(colors.font2);
2497 DrawArrow(p, center + offset, direction, size);
2498}
2499
2500void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
2501 const Direction direction, bool pressed) {
2502 std::array<QPointF, trigger_button.size() / 2> qtrigger_button;
2503 QPoint offset;
2504
2505 for (std::size_t point = 0; point < trigger_button.size() / 2; ++point) {
2506 switch (direction) {
2507 case Direction::Left:
2508 qtrigger_button[point] =
2509 center + QPointF(-trigger_button[point * 2], trigger_button[point * 2 + 1]);
2510 break;
2511 case Direction::Right:
2512 qtrigger_button[point] =
2513 center + QPointF(trigger_button[point * 2], trigger_button[point * 2 + 1]);
2514 break;
2515 case Direction::Up:
2516 case Direction::Down:
2517 case Direction::None:
2518 break;
2519 }
2520 }
2521
2522 // Draw arrow button
2523 p.setPen(colors.outline);
2524 p.setBrush(pressed ? colors.highlight : colors.button);
2525 DrawPolygon(p, qtrigger_button);
2526}
2527
2528void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol symbol,
2529 float icon_size) {
2530 std::array<QPointF, house.size() / 2> house_icon;
2531 std::array<QPointF, symbol_a.size() / 2> a_icon;
2532 std::array<QPointF, symbol_b.size() / 2> b_icon;
2533 std::array<QPointF, symbol_x.size() / 2> x_icon;
2534 std::array<QPointF, symbol_y.size() / 2> y_icon;
2535 std::array<QPointF, symbol_l.size() / 2> l_icon;
2536 std::array<QPointF, symbol_r.size() / 2> r_icon;
2537 std::array<QPointF, symbol_c.size() / 2> c_icon;
2538 std::array<QPointF, symbol_zl.size() / 2> zl_icon;
2539 std::array<QPointF, symbol_sl.size() / 2> sl_icon;
2540 std::array<QPointF, symbol_zr.size() / 2> zr_icon;
2541 std::array<QPointF, symbol_sr.size() / 2> sr_icon;
2542 switch (symbol) {
2543 case Symbol::House:
2544 for (std::size_t point = 0; point < house.size() / 2; ++point) {
2545 house_icon[point] = center + QPointF(house[point * 2] * icon_size,
2546 (house[point * 2 + 1] - 0.025f) * icon_size);
2547 }
2548 p.drawPolygon(house_icon.data(), static_cast<int>(house_icon.size()));
2549 break;
2550 case Symbol::A:
2551 for (std::size_t point = 0; point < symbol_a.size() / 2; ++point) {
2552 a_icon[point] = center + QPointF(symbol_a[point * 2] * icon_size,
2553 symbol_a[point * 2 + 1] * icon_size);
2554 }
2555 p.drawPolygon(a_icon.data(), static_cast<int>(a_icon.size()));
2556 break;
2557 case Symbol::B:
2558 for (std::size_t point = 0; point < symbol_b.size() / 2; ++point) {
2559 b_icon[point] = center + QPointF(symbol_b[point * 2] * icon_size,
2560 symbol_b[point * 2 + 1] * icon_size);
2561 }
2562 p.drawPolygon(b_icon.data(), static_cast<int>(b_icon.size()));
2563 break;
2564 case Symbol::X:
2565 for (std::size_t point = 0; point < symbol_x.size() / 2; ++point) {
2566 x_icon[point] = center + QPointF(symbol_x[point * 2] * icon_size,
2567 symbol_x[point * 2 + 1] * icon_size);
2568 }
2569 p.drawPolygon(x_icon.data(), static_cast<int>(x_icon.size()));
2570 break;
2571 case Symbol::Y:
2572 for (std::size_t point = 0; point < symbol_y.size() / 2; ++point) {
2573 y_icon[point] = center + QPointF(symbol_y[point * 2] * icon_size,
2574 (symbol_y[point * 2 + 1] - 1.0f) * icon_size);
2575 }
2576 p.drawPolygon(y_icon.data(), static_cast<int>(y_icon.size()));
2577 break;
2578 case Symbol::L:
2579 for (std::size_t point = 0; point < symbol_l.size() / 2; ++point) {
2580 l_icon[point] = center + QPointF(symbol_l[point * 2] * icon_size,
2581 (symbol_l[point * 2 + 1] - 1.0f) * icon_size);
2582 }
2583 p.drawPolygon(l_icon.data(), static_cast<int>(l_icon.size()));
2584 break;
2585 case Symbol::R:
2586 for (std::size_t point = 0; point < symbol_r.size() / 2; ++point) {
2587 r_icon[point] = center + QPointF(symbol_r[point * 2] * icon_size,
2588 (symbol_r[point * 2 + 1] - 1.0f) * icon_size);
2589 }
2590 p.drawPolygon(r_icon.data(), static_cast<int>(r_icon.size()));
2591 break;
2592 case Symbol::C:
2593 for (std::size_t point = 0; point < symbol_c.size() / 2; ++point) {
2594 c_icon[point] = center + QPointF(symbol_c[point * 2] * icon_size,
2595 (symbol_c[point * 2 + 1] - 1.0f) * icon_size);
2596 }
2597 p.drawPolygon(c_icon.data(), static_cast<int>(c_icon.size()));
2598 break;
2599 case Symbol::ZL:
2600 for (std::size_t point = 0; point < symbol_zl.size() / 2; ++point) {
2601 zl_icon[point] = center + QPointF(symbol_zl[point * 2] * icon_size,
2602 symbol_zl[point * 2 + 1] * icon_size);
2603 }
2604 p.drawPolygon(zl_icon.data(), static_cast<int>(zl_icon.size()));
2605 break;
2606 case Symbol::SL:
2607 for (std::size_t point = 0; point < symbol_sl.size() / 2; ++point) {
2608 sl_icon[point] = center + QPointF(symbol_sl[point * 2] * icon_size,
2609 symbol_sl[point * 2 + 1] * icon_size);
2610 }
2611 p.drawPolygon(sl_icon.data(), static_cast<int>(sl_icon.size()));
2612 break;
2613 case Symbol::ZR:
2614 for (std::size_t point = 0; point < symbol_zr.size() / 2; ++point) {
2615 zr_icon[point] = center + QPointF(symbol_zr[point * 2] * icon_size,
2616 symbol_zr[point * 2 + 1] * icon_size);
2617 }
2618 p.drawPolygon(zr_icon.data(), static_cast<int>(zr_icon.size()));
2619 break;
2620 case Symbol::SR:
2621 for (std::size_t point = 0; point < symbol_sr.size() / 2; ++point) {
2622 sr_icon[point] = center + QPointF(symbol_sr[point * 2] * icon_size,
2623 symbol_sr[point * 2 + 1] * icon_size);
2624 }
2625 p.drawPolygon(sr_icon.data(), static_cast<int>(sr_icon.size()));
2626 break;
2627 }
2628}
2629
2630void PlayerControlPreview::DrawArrow(QPainter& p, const QPointF center, const Direction direction,
2631 float size) {
2632
2633 std::array<QPointF, up_arrow_symbol.size() / 2> arrow_symbol;
2634
2635 for (std::size_t point = 0; point < up_arrow_symbol.size() / 2; ++point) {
2636 switch (direction) {
2637 case Direction::Up:
2638 arrow_symbol[point] = center + QPointF(up_arrow_symbol[point * 2] * size,
2639 up_arrow_symbol[point * 2 + 1] * size);
2640 break;
2641 case Direction::Left:
2642 arrow_symbol[point] = center + QPointF(up_arrow_symbol[point * 2 + 1] * size,
2643 up_arrow_symbol[point * 2] * size);
2644 break;
2645 case Direction::Right:
2646 arrow_symbol[point] = center + QPointF(-up_arrow_symbol[point * 2 + 1] * size,
2647 up_arrow_symbol[point * 2] * size);
2648 break;
2649 case Direction::Down:
2650 arrow_symbol[point] = center + QPointF(up_arrow_symbol[point * 2] * size,
2651 -up_arrow_symbol[point * 2 + 1] * size);
2652 break;
2653 case Direction::None:
2654 break;
2655 }
2656 }
2657
2658 DrawPolygon(p, arrow_symbol);
2659}
2660
2661template <size_t N>
2662void PlayerControlPreview::DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon) {
2663 p.drawPolygon(polygon.data(), static_cast<int>(polygon.size()));
2664}
2665
2666void PlayerControlPreview::DrawCircle(QPainter& p, const QPointF center, float size) {
2667 p.drawEllipse(center, size, size);
2668}
2669
2670void PlayerControlPreview::DrawRectangle(QPainter& p, const QPointF center, float width,
2671 float height) {
2672 const QRectF rect = QRectF(center.x() - (width / 2), center.y() - (height / 2), width, height);
2673 p.drawRect(rect);
2674}
2675void PlayerControlPreview::DrawRoundRectangle(QPainter& p, const QPointF center, float width,
2676 float height, float round) {
2677 const QRectF rect = QRectF(center.x() - (width / 2), center.y() - (height / 2), width, height);
2678 p.drawRoundedRect(rect, round, round);
2679}
2680
2681void PlayerControlPreview::DrawText(QPainter& p, const QPointF center, float text_size,
2682 const QString& text) {
2683 SetTextFont(p, text_size);
2684 const QFontMetrics fm(p.font());
2685 const QPointF offset = {fm.horizontalAdvance(text) / 2.0f, -text_size / 2.0f};
2686 p.drawText(center - offset, text);
2687}
2688
2689void PlayerControlPreview::SetTextFont(QPainter& p, float text_size, const QString& font_family) {
2690 QFont font = p.font();
2691 font.setPointSizeF(text_size);
2692 font.setFamily(font_family);
2693 p.setFont(font);
2694}
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
new file mode 100644
index 000000000..39565f795
--- /dev/null
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -0,0 +1,192 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <QFrame>
9#include <QPointer>
10#include "core/frontend/input.h"
11#include "core/settings.h"
12
13class QLabel;
14
15using AnalogParam = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
16using ButtonParam = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
17
18// Widget for representing controller animations
19class PlayerControlPreview : public QFrame {
20 Q_OBJECT
21
22public:
23 explicit PlayerControlPreview(QWidget* parent);
24 ~PlayerControlPreview() override;
25
26 void SetPlayerInput(std::size_t index, const ButtonParam& buttons_param,
27 const AnalogParam& analogs_param);
28 void SetPlayerInputRaw(std::size_t index, const Settings::ButtonsRaw buttons_,
29 Settings::AnalogsRaw analogs_);
30 void SetConnectedStatus(bool checked);
31 void SetControllerType(Settings::ControllerType type);
32 void BeginMappingButton(std::size_t button_id);
33 void BeginMappingAnalog(std::size_t button_id);
34 void EndMapping();
35 void UpdateInput();
36
37protected:
38 void paintEvent(QPaintEvent* event) override;
39
40private:
41 enum class Direction : std::size_t {
42 None,
43 Up,
44 Right,
45 Down,
46 Left,
47 };
48
49 enum class Symbol {
50 House,
51 A,
52 B,
53 X,
54 Y,
55 L,
56 R,
57 C,
58 SL,
59 ZL,
60 ZR,
61 SR,
62 };
63
64 struct AxisValue {
65 QPointF value{};
66 QPointF raw_value{};
67 Input::AnalogProperties properties{};
68 int size{};
69 QPoint offset{};
70 bool active{};
71 };
72
73 struct LedPattern {
74 bool position1;
75 bool position2;
76 bool position3;
77 bool position4;
78 };
79
80 struct ColorMapping {
81 QColor outline{};
82 QColor primary{};
83 QColor left{};
84 QColor right{};
85 QColor button{};
86 QColor button2{};
87 QColor font{};
88 QColor font2{};
89 QColor highlight{};
90 QColor highlight2{};
91 QColor transparent{};
92 QColor indicator{};
93 QColor led_on{};
94 QColor led_off{};
95 QColor slider{};
96 QColor slider_button{};
97 QColor slider_arrow{};
98 QColor deadzone{};
99 };
100
101 static LedPattern GetColorPattern(std::size_t index, bool player_on);
102 void UpdateColors();
103
104 // Draw controller functions
105 void DrawHandheldController(QPainter& p, QPointF center);
106 void DrawDualController(QPainter& p, QPointF center);
107 void DrawLeftController(QPainter& p, QPointF center);
108 void DrawRightController(QPainter& p, QPointF center);
109 void DrawProController(QPainter& p, QPointF center);
110 void DrawGCController(QPainter& p, QPointF center);
111
112 // Draw body functions
113 void DrawHandheldBody(QPainter& p, QPointF center);
114 void DrawDualBody(QPainter& p, QPointF center);
115 void DrawLeftBody(QPainter& p, QPointF center);
116 void DrawRightBody(QPainter& p, QPointF center);
117 void DrawProBody(QPainter& p, QPointF center);
118 void DrawGCBody(QPainter& p, QPointF center);
119
120 // Draw triggers functions
121 void DrawProTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
122 void DrawGCTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
123 void DrawHandheldTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
124 void DrawDualTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
125 void DrawDualTriggersTopView(QPainter& p, QPointF center, bool left_pressed,
126 bool right_pressed);
127 void DrawDualZTriggersTopView(QPainter& p, QPointF center, bool left_pressed,
128 bool right_pressed);
129 void DrawLeftTriggers(QPainter& p, QPointF center, bool left_pressed);
130 void DrawLeftZTriggers(QPainter& p, QPointF center, bool left_pressed);
131 void DrawLeftTriggersTopView(QPainter& p, QPointF center, bool left_pressed);
132 void DrawLeftZTriggersTopView(QPainter& p, QPointF center, bool left_pressed);
133 void DrawRightTriggers(QPainter& p, QPointF center, bool right_pressed);
134 void DrawRightZTriggers(QPainter& p, QPointF center, bool right_pressed);
135 void DrawRightTriggersTopView(QPainter& p, QPointF center, bool right_pressed);
136 void DrawRightZTriggersTopView(QPainter& p, QPointF center, bool right_pressed);
137
138 // Draw joystick functions
139 void DrawJoystick(QPainter& p, QPointF center, float size, bool pressed);
140 void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size, bool pressed);
141 void DrawRawJoystick(QPainter& p, QPointF center, const QPointF value,
142 const Input::AnalogProperties properties);
143 void DrawProJoystick(QPainter& p, QPointF center, bool pressed);
144 void DrawGCJoystick(QPainter& p, QPointF center, bool pressed);
145
146 // Draw button functions
147 void DrawCircleButton(QPainter& p, QPointF center, bool pressed, float button_size);
148 void DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width, float height,
149 Direction direction = Direction::None, float radius = 2);
150 void DrawMinusButton(QPainter& p, QPointF center, bool pressed, int button_size);
151 void DrawPlusButton(QPainter& p, QPointF center, bool pressed, int button_size);
152 void DrawGCButtonX(QPainter& p, QPointF center, bool pressed);
153 void DrawGCButtonY(QPainter& p, QPointF center, bool pressed);
154 void DrawGCButtonZ(QPainter& p, QPointF center, bool pressed);
155 void DrawArrowButtonOutline(QPainter& p, const QPointF center, float size = 1.0f);
156 void DrawArrowButton(QPainter& p, QPointF center, Direction direction, bool pressed,
157 float size = 1.0f);
158 void DrawTriggerButton(QPainter& p, QPointF center, Direction direction, bool pressed);
159
160 // Draw icon functions
161 void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size);
162 void DrawArrow(QPainter& p, QPointF center, Direction direction, float size);
163
164 // Draw primitive types
165 template <size_t N>
166 void DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon);
167 void DrawCircle(QPainter& p, QPointF center, float size);
168 void DrawRectangle(QPainter& p, QPointF center, float width, float height);
169 void DrawRoundRectangle(QPainter& p, QPointF center, float width, float height, float round);
170 void DrawText(QPainter& p, QPointF center, float text_size, const QString& text);
171 void SetTextFont(QPainter& p, float text_size,
172 const QString& font_family = QStringLiteral("sans-serif"));
173
174 using ButtonArray =
175 std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::BUTTON_NS_END>;
176 using StickArray =
177 std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>;
178
179 bool mapping_active{};
180 int blink_counter{};
181 QColor button_color{};
182 ColorMapping colors{};
183 std::array<QColor, 4> led_color{};
184 ButtonArray buttons{};
185 StickArray sticks{};
186 std::size_t player_index{};
187 std::size_t button_mapping_index{Settings::NativeButton::BUTTON_NS_END};
188 std::size_t analog_mapping_index{Settings::NativeAnalog::NUM_STICKS_HID};
189 std::array<AxisValue, Settings::NativeAnalog::NUM_STICKS_HID> axis_values{};
190 std::array<bool, Settings::NativeButton::NumButtons> button_values{};
191 Settings::ControllerType controller_type{Settings::ControllerType::ProController};
192};
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
new file mode 100644
index 000000000..85724a8f3
--- /dev/null
+++ b/src/yuzu/debugger/controller.cpp
@@ -0,0 +1,66 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <QAction>
6#include <QLayout>
7#include <QString>
8#include "core/settings.h"
9#include "yuzu/configuration/configure_input_player_widget.h"
10#include "yuzu/debugger/controller.h"
11
12ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) {
13 setObjectName(QStringLiteral("Controller"));
14 setWindowTitle(tr("Controller P1"));
15 resize(500, 350);
16 setMinimumSize(500, 350);
17 // Remove the "?" button from the titlebar and enable the maximize button
18 setWindowFlags((windowFlags() & ~Qt::WindowContextHelpButtonHint) |
19 Qt::WindowMaximizeButtonHint);
20
21 widget = new PlayerControlPreview(this);
22 refreshConfiguration();
23 QLayout* layout = new QVBoxLayout(this);
24 layout->setContentsMargins(0, 0, 0, 0);
25 layout->addWidget(widget);
26 setLayout(layout);
27
28 // Configure focus so that widget is focusable and the dialog automatically forwards focus to
29 // it.
30 setFocusProxy(widget);
31 widget->setFocusPolicy(Qt::StrongFocus);
32 widget->setFocus();
33}
34
35void ControllerDialog::refreshConfiguration() {
36 const auto& players = Settings::values.players.GetValue();
37 constexpr std::size_t player = 0;
38 widget->SetPlayerInputRaw(player, players[player].buttons, players[player].analogs);
39 widget->SetConnectedStatus(players[player].connected);
40 widget->SetControllerType(players[player].controller_type);
41}
42
43QAction* ControllerDialog::toggleViewAction() {
44 if (toggle_view_action == nullptr) {
45 toggle_view_action = new QAction(windowTitle(), this);
46 toggle_view_action->setCheckable(true);
47 toggle_view_action->setChecked(isVisible());
48 connect(toggle_view_action, &QAction::toggled, this, &ControllerDialog::setVisible);
49 }
50
51 return toggle_view_action;
52}
53
54void ControllerDialog::showEvent(QShowEvent* ev) {
55 if (toggle_view_action) {
56 toggle_view_action->setChecked(isVisible());
57 }
58 QWidget::showEvent(ev);
59}
60
61void ControllerDialog::hideEvent(QHideEvent* ev) {
62 if (toggle_view_action) {
63 toggle_view_action->setChecked(isVisible());
64 }
65 QWidget::hideEvent(ev);
66}
diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h
new file mode 100644
index 000000000..c54750070
--- /dev/null
+++ b/src/yuzu/debugger/controller.h
@@ -0,0 +1,31 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <QWidget>
8
9class QAction;
10class QHideEvent;
11class QShowEvent;
12class PlayerControlPreview;
13
14class ControllerDialog : public QWidget {
15 Q_OBJECT
16
17public:
18 explicit ControllerDialog(QWidget* parent = nullptr);
19
20 /// Returns a QAction that can be used to toggle visibility of this dialog.
21 QAction* toggleViewAction();
22 void refreshConfiguration();
23
24protected:
25 void showEvent(QShowEvent* ev) override;
26 void hideEvent(QHideEvent* ev) override;
27
28private:
29 QAction* toggle_view_action = nullptr;
30 PlayerControlPreview* widget;
31};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 886e6e9d2..ef92c25bc 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -109,6 +109,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
109#include "yuzu/configuration/config.h" 109#include "yuzu/configuration/config.h"
110#include "yuzu/configuration/configure_dialog.h" 110#include "yuzu/configuration/configure_dialog.h"
111#include "yuzu/debugger/console.h" 111#include "yuzu/debugger/console.h"
112#include "yuzu/debugger/controller.h"
112#include "yuzu/debugger/profiler.h" 113#include "yuzu/debugger/profiler.h"
113#include "yuzu/debugger/wait_tree.h" 114#include "yuzu/debugger/wait_tree.h"
114#include "yuzu/discord.h" 115#include "yuzu/discord.h"
@@ -688,6 +689,11 @@ void GMainWindow::InitializeDebugWidgets() {
688 addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget); 689 addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget);
689 waitTreeWidget->hide(); 690 waitTreeWidget->hide();
690 debug_menu->addAction(waitTreeWidget->toggleViewAction()); 691 debug_menu->addAction(waitTreeWidget->toggleViewAction());
692
693 controller_dialog = new ControllerDialog(this);
694 controller_dialog->hide();
695 debug_menu->addAction(controller_dialog->toggleViewAction());
696
691 connect(this, &GMainWindow::EmulationStarting, waitTreeWidget, 697 connect(this, &GMainWindow::EmulationStarting, waitTreeWidget,
692 &WaitTreeWidget::OnEmulationStarting); 698 &WaitTreeWidget::OnEmulationStarting);
693 connect(this, &GMainWindow::EmulationStopping, waitTreeWidget, 699 connect(this, &GMainWindow::EmulationStopping, waitTreeWidget,
@@ -2336,6 +2342,7 @@ void GMainWindow::OnConfigure() {
2336 } 2342 }
2337 2343
2338 configure_dialog.ApplyConfiguration(); 2344 configure_dialog.ApplyConfiguration();
2345 controller_dialog->refreshConfiguration();
2339 InitializeHotkeys(); 2346 InitializeHotkeys();
2340 if (UISettings::values.theme != old_theme) { 2347 if (UISettings::values.theme != old_theme) {
2341 UpdateUITheme(); 2348 UpdateUITheme();
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 31788ea62..04d37d4ae 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -27,6 +27,7 @@ class GRenderWindow;
27class LoadingScreen; 27class LoadingScreen;
28class MicroProfileDialog; 28class MicroProfileDialog;
29class ProfilerWidget; 29class ProfilerWidget;
30class ControllerDialog;
30class QLabel; 31class QLabel;
31class QPushButton; 32class QPushButton;
32class QProgressDialog; 33class QProgressDialog;
@@ -313,6 +314,7 @@ private:
313 ProfilerWidget* profilerWidget; 314 ProfilerWidget* profilerWidget;
314 MicroProfileDialog* microProfileDialog; 315 MicroProfileDialog* microProfileDialog;
315 WaitTreeWidget* waitTreeWidget; 316 WaitTreeWidget* waitTreeWidget;
317 ControllerDialog* controller_dialog;
316 318
317 QAction* actions_recent_files[max_recent_files_item]; 319 QAction* actions_recent_files[max_recent_files_item];
318 320