diff options
137 files changed, 11252 insertions, 3534 deletions
diff --git a/dist/icons/controller/controller.qrc b/dist/icons/controller/controller.qrc new file mode 100644 index 000000000..f44725d8f --- /dev/null +++ b/dist/icons/controller/controller.qrc | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | <RCC> | ||
| 2 | <qresource prefix="controller"> | ||
| 3 | <file alias="dual_joycon">dual_joycon.png</file> | ||
| 4 | <file alias="dual_joycon_dark">dual_joycon_dark.png</file> | ||
| 5 | <file alias="dual_joycon_midnight">dual_joycon_midnight.png</file> | ||
| 6 | <file alias="handheld">handheld.png</file> | ||
| 7 | <file alias="handheld_dark">handheld_dark.png</file> | ||
| 8 | <file alias="handheld_midnight">handheld_midnight.png</file> | ||
| 9 | <file alias="pro_controller">pro_controller.png</file> | ||
| 10 | <file alias="pro_controller_dark">pro_controller_dark.png</file> | ||
| 11 | <file alias="pro_controller_midnight">pro_controller_midnight.png</file> | ||
| 12 | <file alias="single_joycon_left">single_joycon_left.png</file> | ||
| 13 | <file alias="single_joycon_left_dark">single_joycon_left_dark.png</file> | ||
| 14 | <file alias="single_joycon_left_midnight">single_joycon_left_midnight.png</file> | ||
| 15 | <file alias="single_joycon_right">single_joycon_right.png</file> | ||
| 16 | <file alias="single_joycon_right_dark">single_joycon_right_dark.png</file> | ||
| 17 | <file alias="single_joycon_right_midnight">single_joycon_right_midnight.png</file> | ||
| 18 | <file alias="single_joycon_left_vertical">single_joycon_left_vertical.png</file> | ||
| 19 | <file alias="single_joycon_left_vertical_dark">single_joycon_left_vertical_dark.png</file> | ||
| 20 | <file alias="single_joycon_left_vertical_midnight">single_joycon_left_vertical_midnight.png</file> | ||
| 21 | <file alias="single_joycon_right_vertical">single_joycon_right_vertical.png</file> | ||
| 22 | <file alias="single_joycon_right_vertical_dark">single_joycon_right_vertical_dark.png</file> | ||
| 23 | <file alias="single_joycon_right_vertical_midnight">single_joycon_right_vertical_midnight.png</file> | ||
| 24 | </qresource> | ||
| 25 | </RCC> | ||
diff --git a/dist/icons/controller/dual_joycon.png b/dist/icons/controller/dual_joycon.png new file mode 100644 index 000000000..4230f5f7b --- /dev/null +++ b/dist/icons/controller/dual_joycon.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/dual_joycon_dark.png b/dist/icons/controller/dual_joycon_dark.png new file mode 100644 index 000000000..4445db489 --- /dev/null +++ b/dist/icons/controller/dual_joycon_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/dual_joycon_midnight.png b/dist/icons/controller/dual_joycon_midnight.png new file mode 100644 index 000000000..aac8e5321 --- /dev/null +++ b/dist/icons/controller/dual_joycon_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/handheld.png b/dist/icons/controller/handheld.png new file mode 100644 index 000000000..d009b4a47 --- /dev/null +++ b/dist/icons/controller/handheld.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/handheld_dark.png b/dist/icons/controller/handheld_dark.png new file mode 100644 index 000000000..c80ca9259 --- /dev/null +++ b/dist/icons/controller/handheld_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/handheld_midnight.png b/dist/icons/controller/handheld_midnight.png new file mode 100644 index 000000000..19de4629b --- /dev/null +++ b/dist/icons/controller/handheld_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/pro_controller.png b/dist/icons/controller/pro_controller.png new file mode 100644 index 000000000..07d65e94a --- /dev/null +++ b/dist/icons/controller/pro_controller.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/pro_controller_dark.png b/dist/icons/controller/pro_controller_dark.png new file mode 100644 index 000000000..73efe18f4 --- /dev/null +++ b/dist/icons/controller/pro_controller_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/pro_controller_midnight.png b/dist/icons/controller/pro_controller_midnight.png new file mode 100644 index 000000000..8d7e63f0d --- /dev/null +++ b/dist/icons/controller/pro_controller_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left.png b/dist/icons/controller/single_joycon_left.png new file mode 100644 index 000000000..547153034 --- /dev/null +++ b/dist/icons/controller/single_joycon_left.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left_dark.png b/dist/icons/controller/single_joycon_left_dark.png new file mode 100644 index 000000000..b6ee073cb --- /dev/null +++ b/dist/icons/controller/single_joycon_left_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left_midnight.png b/dist/icons/controller/single_joycon_left_midnight.png new file mode 100644 index 000000000..34a485c81 --- /dev/null +++ b/dist/icons/controller/single_joycon_left_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left_vertical.png b/dist/icons/controller/single_joycon_left_vertical.png new file mode 100644 index 000000000..1e6282ad8 --- /dev/null +++ b/dist/icons/controller/single_joycon_left_vertical.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left_vertical_dark.png b/dist/icons/controller/single_joycon_left_vertical_dark.png new file mode 100644 index 000000000..a615d995d --- /dev/null +++ b/dist/icons/controller/single_joycon_left_vertical_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_left_vertical_midnight.png b/dist/icons/controller/single_joycon_left_vertical_midnight.png new file mode 100644 index 000000000..4cc578216 --- /dev/null +++ b/dist/icons/controller/single_joycon_left_vertical_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right.png b/dist/icons/controller/single_joycon_right.png new file mode 100644 index 000000000..8d29173f6 --- /dev/null +++ b/dist/icons/controller/single_joycon_right.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right_dark.png b/dist/icons/controller/single_joycon_right_dark.png new file mode 100644 index 000000000..ead2c44e0 --- /dev/null +++ b/dist/icons/controller/single_joycon_right_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right_midnight.png b/dist/icons/controller/single_joycon_right_midnight.png new file mode 100644 index 000000000..89afe022d --- /dev/null +++ b/dist/icons/controller/single_joycon_right_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right_vertical.png b/dist/icons/controller/single_joycon_right_vertical.png new file mode 100644 index 000000000..4d7d06547 --- /dev/null +++ b/dist/icons/controller/single_joycon_right_vertical.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right_vertical_dark.png b/dist/icons/controller/single_joycon_right_vertical_dark.png new file mode 100644 index 000000000..9a6eb3013 --- /dev/null +++ b/dist/icons/controller/single_joycon_right_vertical_dark.png | |||
| Binary files differ | |||
diff --git a/dist/icons/controller/single_joycon_right_vertical_midnight.png b/dist/icons/controller/single_joycon_right_vertical_midnight.png new file mode 100644 index 000000000..685249b68 --- /dev/null +++ b/dist/icons/controller/single_joycon_right_vertical_midnight.png | |||
| Binary files differ | |||
diff --git a/dist/license.md b/dist/license.md index f1ff35c95..e9bc87656 100644 --- a/dist/license.md +++ b/dist/license.md | |||
| @@ -5,6 +5,7 @@ Icon Name | License | Origin/Author | |||
| 5 | qt_themes/default/icons/16x16/checked.png | CC BY-ND 3.0 | https://icons8.com | 5 | qt_themes/default/icons/16x16/checked.png | CC BY-ND 3.0 | https://icons8.com |
| 6 | qt_themes/default/icons/16x16/failed.png | CC BY-ND 3.0 | https://icons8.com | 6 | qt_themes/default/icons/16x16/failed.png | CC BY-ND 3.0 | https://icons8.com |
| 7 | qt_themes/default/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com | 7 | qt_themes/default/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com |
| 8 | qt_themes/default/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io | ||
| 8 | qt_themes/default/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com | 9 | qt_themes/default/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 9 | qt_themes/default/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com | 10 | qt_themes/default/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 10 | qt_themes/default/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com | 11 | qt_themes/default/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com |
| @@ -12,6 +13,7 @@ qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com | |||
| 12 | qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team | 13 | qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team |
| 13 | qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com | 14 | qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com |
| 14 | qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com | 15 | qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com |
| 16 | qt_themes/qdarkstyle/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io | ||
| 15 | qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com | 17 | qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 16 | qt_themes/qdarkstyle/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com | 18 | qt_themes/qdarkstyle/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 17 | qt_themes/qdarkstyle/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com | 19 | qt_themes/qdarkstyle/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com |
| @@ -19,6 +21,7 @@ qt_themes/qdarkstyle/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com | |||
| 19 | qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team | 21 | qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team |
| 20 | qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com | 22 | qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com |
| 21 | qt_themes/colorful/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com | 23 | qt_themes/colorful/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com |
| 24 | qt_themes/colorful/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io | ||
| 22 | qt_themes/colorful/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com | 25 | qt_themes/colorful/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 23 | qt_themes/colorful/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com | 26 | qt_themes/colorful/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com |
| 24 | qt_themes/colorful/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com | 27 | qt_themes/colorful/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com |
diff --git a/dist/qt_themes/colorful_dark/icons/16x16/refresh.png b/dist/qt_themes/colorful_dark/icons/16x16/refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/colorful_dark/icons/16x16/refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/colorful_dark/icons/16x16/view-refresh.png b/dist/qt_themes/colorful_dark/icons/16x16/view-refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/colorful_dark/icons/16x16/view-refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/colorful_dark/style.qrc b/dist/qt_themes/colorful_dark/style.qrc index 27a6cc87d..0abcb4e83 100644 --- a/dist/qt_themes/colorful_dark/style.qrc +++ b/dist/qt_themes/colorful_dark/style.qrc | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | <qresource prefix="icons/colorful_dark"> | 2 | <qresource prefix="icons/colorful_dark"> |
| 3 | <file alias="index.theme">icons/index.theme</file> | 3 | <file alias="index.theme">icons/index.theme</file> |
| 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> | 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> |
| 5 | <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> | ||
| 5 | <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file> | 6 | <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file> |
| 6 | <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file> | 7 | <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file> |
| 7 | <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> | 8 | <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> |
diff --git a/dist/qt_themes/colorful_midnight_blue/icons/16x16/refresh.png b/dist/qt_themes/colorful_midnight_blue/icons/16x16/refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/colorful_midnight_blue/icons/16x16/refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/colorful_midnight_blue/icons/16x16/view-refresh.png b/dist/qt_themes/colorful_midnight_blue/icons/16x16/view-refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/colorful_midnight_blue/icons/16x16/view-refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/colorful_midnight_blue/style.qrc b/dist/qt_themes/colorful_midnight_blue/style.qrc index fd33bc850..bf367099a 100644 --- a/dist/qt_themes/colorful_midnight_blue/style.qrc +++ b/dist/qt_themes/colorful_midnight_blue/style.qrc | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | <qresource prefix="icons/colorful_midnight_blue"> | 2 | <qresource prefix="icons/colorful_midnight_blue"> |
| 3 | <file alias="index.theme">icons/index.theme</file> | 3 | <file alias="index.theme">icons/index.theme</file> |
| 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> | 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> |
| 5 | <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> | ||
| 5 | <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file> | 6 | <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file> |
| 6 | <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file> | 7 | <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file> |
| 7 | <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> | 8 | <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> |
diff --git a/dist/qt_themes/default/default.qrc b/dist/qt_themes/default/default.qrc index c51fdb26c..2182f33f3 100644 --- a/dist/qt_themes/default/default.qrc +++ b/dist/qt_themes/default/default.qrc | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | <file alias="16x16/checked.png">icons/16x16/checked.png</file> | 4 | <file alias="16x16/checked.png">icons/16x16/checked.png</file> |
| 5 | <file alias="16x16/failed.png">icons/16x16/failed.png</file> | 5 | <file alias="16x16/failed.png">icons/16x16/failed.png</file> |
| 6 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> | 6 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> |
| 7 | <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> | ||
| 7 | <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> | 8 | <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> |
| 8 | <file alias="48x48/chip.png">icons/48x48/chip.png</file> | 9 | <file alias="48x48/chip.png">icons/48x48/chip.png</file> |
| 9 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> | 10 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> |
diff --git a/dist/qt_themes/default/icons/16x16/refresh.png b/dist/qt_themes/default/icons/16x16/refresh.png new file mode 100644 index 000000000..69f9474ac --- /dev/null +++ b/dist/qt_themes/default/icons/16x16/refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/default/icons/16x16/view-refresh.png b/dist/qt_themes/default/icons/16x16/view-refresh.png new file mode 100644 index 000000000..69f9474ac --- /dev/null +++ b/dist/qt_themes/default/icons/16x16/view-refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/default/style.qss b/dist/qt_themes/default/style.qss index 6b5953e38..5da56520b 100644 --- a/dist/qt_themes/default/style.qss +++ b/dist/qt_themes/default/style.qss | |||
| @@ -30,6 +30,66 @@ QPushButton#RendererStatusBarButton:checked { | |||
| 30 | color: #e85c00; | 30 | color: #e85c00; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | QPushButton#RendererStatusBarButton:!checked{ | 33 | QPushButton#RendererStatusBarButton:!checked { |
| 34 | color: #0066ff; | 34 | color: #0066ff; |
| 35 | } | 35 | } |
| 36 | |||
| 37 | QPushButton#buttonRefreshDevices { | ||
| 38 | min-width: 20px; | ||
| 39 | min-height: 20px; | ||
| 40 | max-width: 20px; | ||
| 41 | max-height: 20px; | ||
| 42 | } | ||
| 43 | |||
| 44 | QCheckBox#checkboxPlayer1Connected, | ||
| 45 | QCheckBox#checkboxPlayer2Connected, | ||
| 46 | QCheckBox#checkboxPlayer3Connected, | ||
| 47 | QCheckBox#checkboxPlayer4Connected, | ||
| 48 | QCheckBox#checkboxPlayer5Connected, | ||
| 49 | QCheckBox#checkboxPlayer6Connected, | ||
| 50 | QCheckBox#checkboxPlayer7Connected, | ||
| 51 | QCheckBox#checkboxPlayer8Connected { | ||
| 52 | spacing: 0px; | ||
| 53 | } | ||
| 54 | |||
| 55 | QCheckBox#checkboxPlayer1Connected::indicator, | ||
| 56 | QCheckBox#checkboxPlayer2Connected::indicator, | ||
| 57 | QCheckBox#checkboxPlayer3Connected::indicator, | ||
| 58 | QCheckBox#checkboxPlayer4Connected::indicator, | ||
| 59 | QCheckBox#checkboxPlayer5Connected::indicator, | ||
| 60 | QCheckBox#checkboxPlayer6Connected::indicator, | ||
| 61 | QCheckBox#checkboxPlayer7Connected::indicator, | ||
| 62 | QCheckBox#checkboxPlayer8Connected::indicator { | ||
| 63 | width: 14px; | ||
| 64 | height: 14px; | ||
| 65 | } | ||
| 66 | |||
| 67 | QCheckBox#checkboxPlayer1Connected::indicator:checked, | ||
| 68 | QCheckBox#checkboxPlayer2Connected::indicator:checked, | ||
| 69 | QCheckBox#checkboxPlayer3Connected::indicator:checked, | ||
| 70 | QCheckBox#checkboxPlayer4Connected::indicator:checked, | ||
| 71 | QCheckBox#checkboxPlayer5Connected::indicator:checked, | ||
| 72 | QCheckBox#checkboxPlayer6Connected::indicator:checked, | ||
| 73 | QCheckBox#checkboxPlayer7Connected::indicator:checked, | ||
| 74 | QCheckBox#checkboxPlayer8Connected::indicator:checked, | ||
| 75 | QGroupBox#groupConnectedController::indicator:checked { | ||
| 76 | border-radius: 2px; | ||
| 77 | border: 1px solid black; | ||
| 78 | background: #39ff14; | ||
| 79 | image: none; | ||
| 80 | } | ||
| 81 | |||
| 82 | QCheckBox#checkboxPlayer1Connected::indicator:unchecked, | ||
| 83 | QCheckBox#checkboxPlayer2Connected::indicator:unchecked, | ||
| 84 | QCheckBox#checkboxPlayer3Connected::indicator:unchecked, | ||
| 85 | QCheckBox#checkboxPlayer4Connected::indicator:unchecked, | ||
| 86 | QCheckBox#checkboxPlayer5Connected::indicator:unchecked, | ||
| 87 | QCheckBox#checkboxPlayer6Connected::indicator:unchecked, | ||
| 88 | QCheckBox#checkboxPlayer7Connected::indicator:unchecked, | ||
| 89 | QCheckBox#checkboxPlayer8Connected::indicator:unchecked, | ||
| 90 | QGroupBox#groupConnectedController::indicator:unchecked { | ||
| 91 | border-radius: 2px; | ||
| 92 | border: 1px solid black; | ||
| 93 | background: transparent; | ||
| 94 | image: none; | ||
| 95 | } | ||
diff --git a/dist/qt_themes/qdarkstyle/icons/16x16/refresh.png b/dist/qt_themes/qdarkstyle/icons/16x16/refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/qdarkstyle/icons/16x16/refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/qdarkstyle/icons/16x16/view-refresh.png b/dist/qt_themes/qdarkstyle/icons/16x16/view-refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/qdarkstyle/icons/16x16/view-refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/qdarkstyle/style.qrc b/dist/qt_themes/qdarkstyle/style.qrc index c2c14c28a..ec07ba160 100644 --- a/dist/qt_themes/qdarkstyle/style.qrc +++ b/dist/qt_themes/qdarkstyle/style.qrc | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | <qresource prefix="icons/qdarkstyle"> | 2 | <qresource prefix="icons/qdarkstyle"> |
| 3 | <file alias="index.theme">icons/index.theme</file> | 3 | <file alias="index.theme">icons/index.theme</file> |
| 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> | 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> |
| 5 | <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> | ||
| 5 | <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> | 6 | <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> |
| 6 | <file alias="48x48/chip.png">icons/48x48/chip.png</file> | 7 | <file alias="48x48/chip.png">icons/48x48/chip.png</file> |
| 7 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> | 8 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> |
diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss index 2926a05fa..16218f0c2 100644 --- a/dist/qt_themes/qdarkstyle/style.qss +++ b/dist/qt_themes/qdarkstyle/style.qss | |||
| @@ -40,8 +40,8 @@ QCheckBox:disabled { | |||
| 40 | 40 | ||
| 41 | QCheckBox::indicator, | 41 | QCheckBox::indicator, |
| 42 | QGroupBox::indicator { | 42 | QGroupBox::indicator { |
| 43 | width: 18px; | 43 | width: 16px; |
| 44 | height: 18px; | 44 | height: 16px; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | QGroupBox::indicator { | 47 | QGroupBox::indicator { |
| @@ -1237,6 +1237,7 @@ QPlainTextEdit:disabled { | |||
| 1237 | background-color: #2b2e31; | 1237 | background-color: #2b2e31; |
| 1238 | } | 1238 | } |
| 1239 | 1239 | ||
| 1240 | |||
| 1240 | QPushButton#TogglableStatusBarButton { | 1241 | QPushButton#TogglableStatusBarButton { |
| 1241 | min-width: 0px; | 1242 | min-width: 0px; |
| 1242 | color: #656565; | 1243 | color: #656565; |
| @@ -1271,6 +1272,107 @@ QPushButton#RendererStatusBarButton:checked { | |||
| 1271 | color: #e85c00; | 1272 | color: #e85c00; |
| 1272 | } | 1273 | } |
| 1273 | 1274 | ||
| 1274 | QPushButton#RendererStatusBarButton:!checked{ | 1275 | QPushButton#RendererStatusBarButton:!checked { |
| 1275 | color: #00ccdd; | 1276 | color: #00ccdd; |
| 1277 | } | ||
| 1278 | |||
| 1279 | QPushButton#buttonRefreshDevices { | ||
| 1280 | min-width: 24px; | ||
| 1281 | min-height: 24px; | ||
| 1282 | max-width: 24px; | ||
| 1283 | max-height: 24px; | ||
| 1284 | padding: 0px 0px; | ||
| 1285 | } | ||
| 1286 | |||
| 1287 | QCheckBox#checkboxPlayer1Connected, | ||
| 1288 | QCheckBox#checkboxPlayer2Connected, | ||
| 1289 | QCheckBox#checkboxPlayer3Connected, | ||
| 1290 | QCheckBox#checkboxPlayer4Connected, | ||
| 1291 | QCheckBox#checkboxPlayer5Connected, | ||
| 1292 | QCheckBox#checkboxPlayer6Connected, | ||
| 1293 | QCheckBox#checkboxPlayer7Connected, | ||
| 1294 | QCheckBox#checkboxPlayer8Connected { | ||
| 1295 | spacing: 0px; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | QCheckBox#checkboxPlayer1Connected::indicator, | ||
| 1299 | QCheckBox#checkboxPlayer2Connected::indicator, | ||
| 1300 | QCheckBox#checkboxPlayer3Connected::indicator, | ||
| 1301 | QCheckBox#checkboxPlayer4Connected::indicator, | ||
| 1302 | QCheckBox#checkboxPlayer5Connected::indicator, | ||
| 1303 | QCheckBox#checkboxPlayer6Connected::indicator, | ||
| 1304 | QCheckBox#checkboxPlayer7Connected::indicator, | ||
| 1305 | QCheckBox#checkboxPlayer8Connected::indicator { | ||
| 1306 | width: 14px; | ||
| 1307 | height: 14px; | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | QCheckBox#checkboxPlayer1Connected::indicator:checked, | ||
| 1311 | QCheckBox#checkboxPlayer2Connected::indicator:checked, | ||
| 1312 | QCheckBox#checkboxPlayer3Connected::indicator:checked, | ||
| 1313 | QCheckBox#checkboxPlayer4Connected::indicator:checked, | ||
| 1314 | QCheckBox#checkboxPlayer5Connected::indicator:checked, | ||
| 1315 | QCheckBox#checkboxPlayer6Connected::indicator:checked, | ||
| 1316 | QCheckBox#checkboxPlayer7Connected::indicator:checked, | ||
| 1317 | QCheckBox#checkboxPlayer8Connected::indicator:checked, | ||
| 1318 | QGroupBox#groupConnectedController::indicator:checked { | ||
| 1319 | border-radius: 2px; | ||
| 1320 | border: 1px solid #929192; | ||
| 1321 | background: #39ff14; | ||
| 1322 | image: none; | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | QCheckBox#checkboxPlayer1Connected::indicator:unchecked, | ||
| 1326 | QCheckBox#checkboxPlayer2Connected::indicator:unchecked, | ||
| 1327 | QCheckBox#checkboxPlayer3Connected::indicator:unchecked, | ||
| 1328 | QCheckBox#checkboxPlayer4Connected::indicator:unchecked, | ||
| 1329 | QCheckBox#checkboxPlayer5Connected::indicator:unchecked, | ||
| 1330 | QCheckBox#checkboxPlayer6Connected::indicator:unchecked, | ||
| 1331 | QCheckBox#checkboxPlayer7Connected::indicator:unchecked, | ||
| 1332 | QCheckBox#checkboxPlayer8Connected::indicator:unchecked, | ||
| 1333 | QGroupBox#groupConnectedController::indicator:unchecked { | ||
| 1334 | border-radius: 2px; | ||
| 1335 | border: 1px solid #929192; | ||
| 1336 | background: transparent; | ||
| 1337 | image: none; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | QSpinBox#spinboxLStickRange, | ||
| 1341 | QSpinBox#spinboxRStickRange { | ||
| 1342 | padding: 4px 0px 5px 0px; | ||
| 1343 | min-width: 63px; | ||
| 1344 | } | ||
| 1345 | |||
| 1346 | QSpinBox#vibrationSpin { | ||
| 1347 | padding: 4px 0px 5px 0px; | ||
| 1348 | min-width: 63px; | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | QSpinBox#spinboxLStickRange:up-button, | ||
| 1352 | QSpinBox#spinboxRStickRange:up-button, | ||
| 1353 | QSpinBox#vibrationSpin:up-button { | ||
| 1354 | left: -2px; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | QSpinBox#spinboxLStickRange:down-button, | ||
| 1358 | QSpinBox#spinboxRStickRange:down-button, | ||
| 1359 | QSpinBox#vibrationSpin:down-button { | ||
| 1360 | right: -1px; | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | QGroupBox#motionGroup::indicator, | ||
| 1364 | QGroupBox#vibrationGroup::indicator { | ||
| 1365 | margin-left: 0px; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | QGroupBox#motionGroup::title, | ||
| 1369 | QGroupBox#vibrationGroup::title { | ||
| 1370 | spacing: 2px; | ||
| 1371 | padding-left: 1px; | ||
| 1372 | padding-right: 1px; | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | /* touchscreen mapping widget */ | ||
| 1376 | TouchScreenPreview { | ||
| 1377 | qproperty-dotHighlightColor: #3daee9; | ||
| 1276 | } | 1378 | } |
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/refresh.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/view-refresh.png b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/view-refresh.png new file mode 100644 index 000000000..d4afd76f9 --- /dev/null +++ b/dist/qt_themes/qdarkstyle_midnight_blue/icons/16x16/view-refresh.png | |||
| Binary files differ | |||
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc b/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc index 1b7686f15..616aace73 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | <qresource prefix="icons/qdarkstyle_midnight_blue"> | 2 | <qresource prefix="icons/qdarkstyle_midnight_blue"> |
| 3 | <file alias="index.theme">icons/index.theme</file> | 3 | <file alias="index.theme">icons/index.theme</file> |
| 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> | 4 | <file alias="16x16/lock.png">icons/16x16/lock.png</file> |
| 5 | <file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> | ||
| 5 | <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> | 6 | <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> |
| 6 | <file alias="48x48/chip.png">icons/48x48/chip.png</file> | 7 | <file alias="48x48/chip.png">icons/48x48/chip.png</file> |
| 7 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> | 8 | <file alias="48x48/folder.png">icons/48x48/folder.png</file> |
diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss index 9c24b0d07..a714e1475 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss | |||
| @@ -138,8 +138,6 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar | |||
| 138 | 138 | ||
| 139 | --------------------------------------------------------------------------- */ | 139 | --------------------------------------------------------------------------- */ |
| 140 | QStatusBar { | 140 | QStatusBar { |
| 141 | border: 1px solid #32414B; | ||
| 142 | /* Fixes Spyder #9120, #9121 */ | ||
| 143 | background: #32414B; | 141 | background: #32414B; |
| 144 | /* Fixes #205, white vertical borders separating items */ | 142 | /* Fixes #205, white vertical borders separating items */ |
| 145 | } | 143 | } |
| @@ -161,6 +159,7 @@ QStatusBar QToolTip { | |||
| 161 | QStatusBar QLabel { | 159 | QStatusBar QLabel { |
| 162 | /* Fixes Spyder #9120, #9121 */ | 160 | /* Fixes Spyder #9120, #9121 */ |
| 163 | background: transparent; | 161 | background: transparent; |
| 162 | padding: 0px; | ||
| 164 | } | 163 | } |
| 165 | 164 | ||
| 166 | /* QCheckBox -------------------------------------------------------------- | 165 | /* QCheckBox -------------------------------------------------------------- |
| @@ -236,21 +235,19 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox | |||
| 236 | 235 | ||
| 237 | --------------------------------------------------------------------------- */ | 236 | --------------------------------------------------------------------------- */ |
| 238 | QGroupBox { | 237 | QGroupBox { |
| 239 | font-weight: bold; | 238 | font-weight: bold; |
| 240 | border: 1px solid #32414B; | 239 | border: 1px solid #32414B; |
| 241 | border-radius: 4px; | 240 | border-radius: 4px; |
| 242 | padding: 4px; | 241 | margin-top: 12px; |
| 243 | margin-top: 16px; | 242 | padding: 4px; |
| 244 | } | 243 | } |
| 245 | 244 | ||
| 246 | QGroupBox::title { | 245 | QGroupBox::title { |
| 247 | subcontrol-origin: margin; | 246 | subcontrol-origin: margin; |
| 248 | subcontrol-position: top left; | 247 | subcontrol-position: top left; |
| 249 | left: 3px; | 248 | padding-left: 3px; |
| 250 | padding-left: 3px; | 249 | padding-right: 5px; |
| 251 | padding-right: 5px; | 250 | padding-top: 4px; |
| 252 | padding-top: 8px; | ||
| 253 | padding-bottom: 16px; | ||
| 254 | } | 251 | } |
| 255 | 252 | ||
| 256 | QGroupBox::indicator { | 253 | QGroupBox::indicator { |
| @@ -367,28 +364,19 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar | |||
| 367 | --------------------------------------------------------------------------- */ | 364 | --------------------------------------------------------------------------- */ |
| 368 | QMenuBar { | 365 | QMenuBar { |
| 369 | background-color: #32414B; | 366 | background-color: #32414B; |
| 370 | padding: 2px; | ||
| 371 | border: 1px solid #19232D; | ||
| 372 | color: #F0F0F0; | 367 | color: #F0F0F0; |
| 373 | } | 368 | } |
| 374 | 369 | ||
| 375 | QMenuBar:focus { | ||
| 376 | border: 1px solid #148CD2; | ||
| 377 | } | ||
| 378 | |||
| 379 | QMenuBar::item { | 370 | QMenuBar::item { |
| 380 | background: transparent; | 371 | background: transparent; |
| 381 | padding: 4px; | ||
| 382 | } | 372 | } |
| 383 | 373 | ||
| 384 | QMenuBar::item:selected { | 374 | QMenuBar::item:selected { |
| 385 | padding: 4px; | ||
| 386 | background: transparent; | 375 | background: transparent; |
| 387 | border: 0px solid #32414B; | 376 | border: 0px solid #32414B; |
| 388 | } | 377 | } |
| 389 | 378 | ||
| 390 | QMenuBar::item:pressed { | 379 | QMenuBar::item:pressed { |
| 391 | padding: 4px; | ||
| 392 | border: 0px solid #32414B; | 380 | border: 0px solid #32414B; |
| 393 | background-color: #148CD2; | 381 | background-color: #148CD2; |
| 394 | color: #F0F0F0; | 382 | color: #F0F0F0; |
| @@ -396,6 +384,7 @@ QMenuBar::item:pressed { | |||
| 396 | padding-bottom: 0px; | 384 | padding-bottom: 0px; |
| 397 | } | 385 | } |
| 398 | 386 | ||
| 387 | |||
| 399 | /* QMenu ------------------------------------------------------------------ | 388 | /* QMenu ------------------------------------------------------------------ |
| 400 | 389 | ||
| 401 | https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu | 390 | https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu |
| @@ -482,7 +471,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox | |||
| 482 | 471 | ||
| 483 | --------------------------------------------------------------------------- */ | 472 | --------------------------------------------------------------------------- */ |
| 484 | QAbstractItemView { | 473 | QAbstractItemView { |
| 485 | alternate-background-color: #19232D; | 474 | alternate-background-color: #1f2933; |
| 486 | color: #F0F0F0; | 475 | color: #F0F0F0; |
| 487 | border: 1px solid #32414B; | 476 | border: 1px solid #32414B; |
| 488 | border-radius: 4px; | 477 | border-radius: 4px; |
| @@ -501,13 +490,13 @@ QAbstractScrollArea { | |||
| 501 | background-color: #19232D; | 490 | background-color: #19232D; |
| 502 | border: 1px solid #32414B; | 491 | border: 1px solid #32414B; |
| 503 | border-radius: 4px; | 492 | border-radius: 4px; |
| 504 | padding: 2px; | ||
| 505 | /* fix #159 */ | 493 | /* fix #159 */ |
| 506 | min-height: 1.25em; | 494 | min-height: 1.25em; |
| 507 | /* fix #159 */ | 495 | /* fix #159 */ |
| 508 | color: #F0F0F0; | 496 | color: #F0F0F0; |
| 509 | } | 497 | } |
| 510 | 498 | ||
| 499 | |||
| 511 | QAbstractScrollArea:disabled { | 500 | QAbstractScrollArea:disabled { |
| 512 | color: #787878; | 501 | color: #787878; |
| 513 | } | 502 | } |
| @@ -807,20 +796,22 @@ QAbstractSpinBox { | |||
| 807 | } | 796 | } |
| 808 | 797 | ||
| 809 | QAbstractSpinBox:up-button { | 798 | QAbstractSpinBox:up-button { |
| 810 | background-color: transparent #19232D; | 799 | background-color: #505F69; |
| 811 | subcontrol-origin: border; | 800 | subcontrol-origin: border; |
| 812 | subcontrol-position: top right; | 801 | subcontrol-position: top right; |
| 813 | border-left: 1px solid #32414B; | 802 | border-left: 1px solid #32414B; |
| 814 | border-bottom: 1px solid #32414B; | 803 | border-top: 1px solid #32414B; |
| 804 | border-right: 1px solid #32414B; | ||
| 805 | border-top-right-radius: 4px; | ||
| 815 | border-top-left-radius: 0; | 806 | border-top-left-radius: 0; |
| 816 | border-bottom-left-radius: 0; | 807 | border-bottom-left-radius: 0; |
| 817 | margin: 1px; | 808 | margin: 0px; |
| 818 | width: 12px; | 809 | width: 12px; |
| 819 | margin-bottom: -1px; | 810 | margin-bottom: 0px; |
| 820 | } | 811 | } |
| 821 | 812 | ||
| 822 | QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { | 813 | QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { |
| 823 | image: url(":/qss_icons/rc/arrow_up_disabled.png"); | 814 | image: url(":/qss_icons/rc/up_arrow.png"); |
| 824 | height: 8px; | 815 | height: 8px; |
| 825 | width: 8px; | 816 | width: 8px; |
| 826 | } | 817 | } |
| @@ -830,20 +821,23 @@ QAbstractSpinBox::up-arrow:hover { | |||
| 830 | } | 821 | } |
| 831 | 822 | ||
| 832 | QAbstractSpinBox:down-button { | 823 | QAbstractSpinBox:down-button { |
| 833 | background-color: transparent #19232D; | 824 | background-color: #505F69; |
| 834 | subcontrol-origin: border; | 825 | subcontrol-origin: border; |
| 835 | subcontrol-position: bottom right; | 826 | subcontrol-position: bottom right; |
| 836 | border-left: 1px solid #32414B; | 827 | border-left: 1px solid #32414B; |
| 828 | border-right: 1px solid #32414B; | ||
| 829 | border-bottom: 1px solid #32414B; | ||
| 837 | border-top: 1px solid #32414B; | 830 | border-top: 1px solid #32414B; |
| 838 | border-top-left-radius: 0; | 831 | border-top-left-radius: 0; |
| 839 | border-bottom-left-radius: 0; | 832 | border-bottom-left-radius: 0; |
| 840 | margin: 1px; | 833 | border-bottom-right-radius: 4px; |
| 834 | margin: 0px; | ||
| 841 | width: 12px; | 835 | width: 12px; |
| 842 | margin-top: -1px; | 836 | margin-top: 0px; |
| 843 | } | 837 | } |
| 844 | 838 | ||
| 845 | QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { | 839 | QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { |
| 846 | image: url(":/qss_icons/rc/arrow_down_disabled.png"); | 840 | image: url(":/qss_icons/rc/down_arrow.png"); |
| 847 | height: 8px; | 841 | height: 8px; |
| 848 | width: 8px; | 842 | width: 8px; |
| 849 | } | 843 | } |
| @@ -1199,6 +1193,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox | |||
| 1199 | 1193 | ||
| 1200 | --------------------------------------------------------------------------- */ | 1194 | --------------------------------------------------------------------------- */ |
| 1201 | QComboBox { | 1195 | QComboBox { |
| 1196 | background-color: #0f1922; | ||
| 1202 | border: 1px solid #32414B; | 1197 | border: 1px solid #32414B; |
| 1203 | border-radius: 4px; | 1198 | border-radius: 4px; |
| 1204 | selection-background-color: #1464A0; | 1199 | selection-background-color: #1464A0; |
| @@ -1216,7 +1211,7 @@ QComboBox { | |||
| 1216 | QComboBox QAbstractItemView { | 1211 | QComboBox QAbstractItemView { |
| 1217 | border: 1px solid #32414B; | 1212 | border: 1px solid #32414B; |
| 1218 | border-radius: 0; | 1213 | border-radius: 0; |
| 1219 | background-color: #19232D; | 1214 | background-color: #0f1922; |
| 1220 | selection-background-color: #1464A0; | 1215 | selection-background-color: #1464A0; |
| 1221 | } | 1216 | } |
| 1222 | 1217 | ||
| @@ -1285,7 +1280,12 @@ QComboBox::drop-down { | |||
| 1285 | } | 1280 | } |
| 1286 | 1281 | ||
| 1287 | QComboBox::down-arrow { | 1282 | QComboBox::down-arrow { |
| 1288 | image: url(":/qss_icons/rc/arrow_down_disabled.png"); | 1283 | image: url(":/qss_icons/rc/down_arrow.png"); |
| 1284 | background-color: #505F69; | ||
| 1285 | padding: 6px 2px; | ||
| 1286 | border: 1px solid #32414B; | ||
| 1287 | border-top-right-radius: 4px; | ||
| 1288 | border-bottom-right-radius: 4px; | ||
| 1289 | height: 8px; | 1289 | height: 8px; |
| 1290 | width: 8px; | 1290 | width: 8px; |
| 1291 | } | 1291 | } |
| @@ -1559,12 +1559,12 @@ QTabBar::tab:right:!selected { | |||
| 1559 | QTabBar::tab:top { | 1559 | QTabBar::tab:top { |
| 1560 | background-color: #32414B; | 1560 | background-color: #32414B; |
| 1561 | color: #F0F0F0; | 1561 | color: #F0F0F0; |
| 1562 | min-width: 36px; | ||
| 1562 | margin-left: 2px; | 1563 | margin-left: 2px; |
| 1563 | padding-left: 4px; | 1564 | padding-left: 8px; |
| 1564 | padding-right: 4px; | 1565 | padding-right: 8px; |
| 1565 | padding-top: 2px; | 1566 | padding-top: 2px; |
| 1566 | padding-bottom: 2px; | 1567 | padding-bottom: 2px; |
| 1567 | min-width: 5px; | ||
| 1568 | border-bottom: 3px solid #32414B; | 1568 | border-bottom: 3px solid #32414B; |
| 1569 | border-top-left-radius: 3px; | 1569 | border-top-left-radius: 3px; |
| 1570 | border-top-right-radius: 3px; | 1570 | border-top-right-radius: 3px; |
| @@ -1588,16 +1588,16 @@ QTabBar::tab:top:!selected:hover { | |||
| 1588 | 1588 | ||
| 1589 | QTabBar::tab:bottom { | 1589 | QTabBar::tab:bottom { |
| 1590 | color: #F0F0F0; | 1590 | color: #F0F0F0; |
| 1591 | min-width: 36px; | ||
| 1591 | border-top: 3px solid #32414B; | 1592 | border-top: 3px solid #32414B; |
| 1592 | background-color: #32414B; | 1593 | background-color: #32414B; |
| 1593 | margin-left: 2px; | 1594 | margin-left: 2px; |
| 1594 | padding-left: 4px; | 1595 | padding-left: 8px; |
| 1595 | padding-right: 4px; | 1596 | padding-right: 8px; |
| 1596 | padding-top: 2px; | 1597 | padding-top: 2px; |
| 1597 | padding-bottom: 2px; | 1598 | padding-bottom: 2px; |
| 1598 | border-bottom-left-radius: 3px; | 1599 | border-bottom-left-radius: 3px; |
| 1599 | border-bottom-right-radius: 3px; | 1600 | border-bottom-right-radius: 3px; |
| 1600 | min-width: 5px; | ||
| 1601 | } | 1601 | } |
| 1602 | 1602 | ||
| 1603 | QTabBar::tab:bottom:selected { | 1603 | QTabBar::tab:bottom:selected { |
| @@ -1752,21 +1752,6 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview | |||
| 1752 | https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview | 1752 | https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview |
| 1753 | 1753 | ||
| 1754 | --------------------------------------------------------------------------- */ | 1754 | --------------------------------------------------------------------------- */ |
| 1755 | QTreeView:branch:selected, QTreeView:branch:hover { | ||
| 1756 | background: url(":/qss_icons/rc/transparent.png"); | ||
| 1757 | } | ||
| 1758 | |||
| 1759 | QTreeView:branch:has-siblings:!adjoins-item { | ||
| 1760 | border-image: url(":/qss_icons/rc/branch_line.png") 0; | ||
| 1761 | } | ||
| 1762 | |||
| 1763 | QTreeView:branch:has-siblings:adjoins-item { | ||
| 1764 | border-image: url(":/qss_icons/rc/branch_more.png") 0; | ||
| 1765 | } | ||
| 1766 | |||
| 1767 | QTreeView:branch:!has-children:!has-siblings:adjoins-item { | ||
| 1768 | border-image: url(":/qss_icons/rc/branch_end.png") 0; | ||
| 1769 | } | ||
| 1770 | 1755 | ||
| 1771 | QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { | 1756 | QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { |
| 1772 | border-image: none; | 1757 | border-image: none; |
| @@ -1900,21 +1885,21 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview | |||
| 1900 | 1885 | ||
| 1901 | --------------------------------------------------------------------------- */ | 1886 | --------------------------------------------------------------------------- */ |
| 1902 | QHeaderView { | 1887 | QHeaderView { |
| 1903 | background-color: #32414B; | 1888 | background-color: #19232D; |
| 1904 | border: 0px transparent #32414B; | 1889 | border: 0px transparent #19232D; |
| 1905 | padding: 0px; | 1890 | padding: 0px; |
| 1906 | margin: 0px; | 1891 | margin: 0px; |
| 1907 | border-radius: 0px; | 1892 | border-radius: 0px; |
| 1908 | } | 1893 | } |
| 1909 | 1894 | ||
| 1910 | QHeaderView:disabled { | 1895 | QHeaderView:disabled { |
| 1911 | background-color: #32414B; | 1896 | background-color: #19232D; |
| 1912 | border: 1px transparent #32414B; | 1897 | border: 1px transparent #19232D; |
| 1913 | padding: 2px; | 1898 | padding: 2px; |
| 1914 | } | 1899 | } |
| 1915 | 1900 | ||
| 1916 | QHeaderView::section { | 1901 | QHeaderView::section { |
| 1917 | background-color: #32414B; | 1902 | background-color: #19232D; |
| 1918 | color: #F0F0F0; | 1903 | color: #F0F0F0; |
| 1919 | padding: 2px; | 1904 | padding: 2px; |
| 1920 | border-radius: 0px; | 1905 | border-radius: 0px; |
| @@ -1934,11 +1919,11 @@ QHeaderView::section:checked:disabled { | |||
| 1934 | QHeaderView::section::horizontal { | 1919 | QHeaderView::section::horizontal { |
| 1935 | padding-left: 4px; | 1920 | padding-left: 4px; |
| 1936 | padding-right: 4px; | 1921 | padding-right: 4px; |
| 1937 | border-left: 1px solid #19232D; | 1922 | border-left: 1px solid #32414B; |
| 1938 | } | 1923 | } |
| 1939 | 1924 | ||
| 1940 | QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { | 1925 | QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { |
| 1941 | border-left: 1px solid #32414B; | 1926 | border-left: 1px solid #19232D; |
| 1942 | } | 1927 | } |
| 1943 | 1928 | ||
| 1944 | QHeaderView::section::horizontal:disabled { | 1929 | QHeaderView::section::horizontal:disabled { |
| @@ -1948,7 +1933,7 @@ QHeaderView::section::horizontal:disabled { | |||
| 1948 | QHeaderView::section::vertical { | 1933 | QHeaderView::section::vertical { |
| 1949 | padding-left: 4px; | 1934 | padding-left: 4px; |
| 1950 | padding-right: 4px; | 1935 | padding-right: 4px; |
| 1951 | border-top: 1px solid #19232D; | 1936 | border-top: 1px solid #32414B; |
| 1952 | } | 1937 | } |
| 1953 | 1938 | ||
| 1954 | QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { | 1939 | QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { |
| @@ -1962,7 +1947,7 @@ QHeaderView::section::vertical:disabled { | |||
| 1962 | QHeaderView::down-arrow { | 1947 | QHeaderView::down-arrow { |
| 1963 | /* Those settings (border/width/height/background-color) solve bug */ | 1948 | /* Those settings (border/width/height/background-color) solve bug */ |
| 1964 | /* transparent arrow background and size */ | 1949 | /* transparent arrow background and size */ |
| 1965 | background-color: #32414B; | 1950 | background-color: #19232D; |
| 1966 | border: none; | 1951 | border: none; |
| 1967 | height: 12px; | 1952 | height: 12px; |
| 1968 | width: 12px; | 1953 | width: 12px; |
| @@ -1972,7 +1957,7 @@ QHeaderView::down-arrow { | |||
| 1972 | } | 1957 | } |
| 1973 | 1958 | ||
| 1974 | QHeaderView::up-arrow { | 1959 | QHeaderView::up-arrow { |
| 1975 | background-color: #32414B; | 1960 | background-color: #19232D; |
| 1976 | border: none; | 1961 | border: none; |
| 1977 | height: 12px; | 1962 | height: 12px; |
| 1978 | width: 12px; | 1963 | width: 12px; |
| @@ -2172,3 +2157,132 @@ PlotWidget { | |||
| 2172 | /* Fix cut labels in plots #134 */ | 2157 | /* Fix cut labels in plots #134 */ |
| 2173 | padding: 0px; | 2158 | padding: 0px; |
| 2174 | } | 2159 | } |
| 2160 | |||
| 2161 | |||
| 2162 | QPushButton#TogglableStatusBarButton { | ||
| 2163 | min-width: 0px; | ||
| 2164 | color: #656565; | ||
| 2165 | border: 1px solid transparent; | ||
| 2166 | background-color: transparent; | ||
| 2167 | padding: 0px 3px 0px 3px; | ||
| 2168 | text-align: center; | ||
| 2169 | } | ||
| 2170 | |||
| 2171 | QPushButton#TogglableStatusBarButton:checked { | ||
| 2172 | color: #ffffff; | ||
| 2173 | } | ||
| 2174 | |||
| 2175 | QPushButton#TogglableStatusBarButton:hover { | ||
| 2176 | border: 1px solid #76797C; | ||
| 2177 | } | ||
| 2178 | |||
| 2179 | QPushButton#RendererStatusBarButton { | ||
| 2180 | min-width: 0px; | ||
| 2181 | color: #656565; | ||
| 2182 | border: 1px solid transparent; | ||
| 2183 | background-color: transparent; | ||
| 2184 | padding: 0px 3px 0px 3px; | ||
| 2185 | text-align: center; | ||
| 2186 | } | ||
| 2187 | |||
| 2188 | QPushButton#RendererStatusBarButton:hover { | ||
| 2189 | border: 1px solid #76797C; | ||
| 2190 | } | ||
| 2191 | |||
| 2192 | QPushButton#RendererStatusBarButton:checked { | ||
| 2193 | color: #e85c00; | ||
| 2194 | } | ||
| 2195 | |||
| 2196 | QPushButton#RendererStatusBarButton:!checked { | ||
| 2197 | color: #00ccdd; | ||
| 2198 | } | ||
| 2199 | |||
| 2200 | QPushButton#buttonRefreshDevices { | ||
| 2201 | min-width: 20px; | ||
| 2202 | min-height: 20px; | ||
| 2203 | max-width: 20px; | ||
| 2204 | max-height: 20px; | ||
| 2205 | padding: 0px 0px; | ||
| 2206 | } | ||
| 2207 | |||
| 2208 | |||
| 2209 | QCheckBox#checkboxPlayer1Connected, | ||
| 2210 | QCheckBox#checkboxPlayer2Connected, | ||
| 2211 | QCheckBox#checkboxPlayer3Connected, | ||
| 2212 | QCheckBox#checkboxPlayer4Connected, | ||
| 2213 | QCheckBox#checkboxPlayer5Connected, | ||
| 2214 | QCheckBox#checkboxPlayer6Connected, | ||
| 2215 | QCheckBox#checkboxPlayer7Connected, | ||
| 2216 | QCheckBox#checkboxPlayer8Connected { | ||
| 2217 | spacing: 0px; | ||
| 2218 | } | ||
| 2219 | |||
| 2220 | QCheckBox#checkboxPlayer1Connected::indicator, | ||
| 2221 | QCheckBox#checkboxPlayer2Connected::indicator, | ||
| 2222 | QCheckBox#checkboxPlayer3Connected::indicator, | ||
| 2223 | QCheckBox#checkboxPlayer4Connected::indicator, | ||
| 2224 | QCheckBox#checkboxPlayer5Connected::indicator, | ||
| 2225 | QCheckBox#checkboxPlayer6Connected::indicator, | ||
| 2226 | QCheckBox#checkboxPlayer7Connected::indicator, | ||
| 2227 | QCheckBox#checkboxPlayer8Connected::indicator { | ||
| 2228 | width: 14px; | ||
| 2229 | height: 14px; | ||
| 2230 | } | ||
| 2231 | |||
| 2232 | QCheckBox#checkboxPlayer1Connected::indicator:checked, | ||
| 2233 | QCheckBox#checkboxPlayer2Connected::indicator:checked, | ||
| 2234 | QCheckBox#checkboxPlayer3Connected::indicator:checked, | ||
| 2235 | QCheckBox#checkboxPlayer4Connected::indicator:checked, | ||
| 2236 | QCheckBox#checkboxPlayer5Connected::indicator:checked, | ||
| 2237 | QCheckBox#checkboxPlayer6Connected::indicator:checked, | ||
| 2238 | QCheckBox#checkboxPlayer7Connected::indicator:checked, | ||
| 2239 | QCheckBox#checkboxPlayer8Connected::indicator:checked, | ||
| 2240 | QGroupBox#groupConnectedController::indicator:checked { | ||
| 2241 | border-radius: 2px; | ||
| 2242 | border: 1px solid #929192; | ||
| 2243 | background: #39ff14; | ||
| 2244 | image: none; | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | QCheckBox#checkboxPlayer1Connected::indicator:unchecked, | ||
| 2248 | QCheckBox#checkboxPlayer2Connected::indicator:unchecked, | ||
| 2249 | QCheckBox#checkboxPlayer3Connected::indicator:unchecked, | ||
| 2250 | QCheckBox#checkboxPlayer4Connected::indicator:unchecked, | ||
| 2251 | QCheckBox#checkboxPlayer5Connected::indicator:unchecked, | ||
| 2252 | QCheckBox#checkboxPlayer6Connected::indicator:unchecked, | ||
| 2253 | QCheckBox#checkboxPlayer7Connected::indicator:unchecked, | ||
| 2254 | QCheckBox#checkboxPlayer8Connected::indicator:unchecked, | ||
| 2255 | QGroupBox#groupConnectedController::indicator:unchecked { | ||
| 2256 | border-radius: 2px; | ||
| 2257 | border: 1px solid #929192; | ||
| 2258 | background: transparent; | ||
| 2259 | image: none; | ||
| 2260 | } | ||
| 2261 | |||
| 2262 | QSpinBox#spinboxLStickRange, | ||
| 2263 | QSpinBox#spinboxRStickRange { | ||
| 2264 | min-width: 38px; | ||
| 2265 | } | ||
| 2266 | |||
| 2267 | QGroupBox#motionGroup::indicator, | ||
| 2268 | QGroupBox#vibrationGroup::indicator { | ||
| 2269 | margin-left: 0px; | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | QGroupBox#motionGroup::title, | ||
| 2273 | QGroupBox#vibrationGroup::title { | ||
| 2274 | spacing: 2px; | ||
| 2275 | padding-left: 1px; | ||
| 2276 | padding-right: 1px; | ||
| 2277 | } | ||
| 2278 | |||
| 2279 | QListWidget#selectorList { | ||
| 2280 | background-color: #0f1922; | ||
| 2281 | } | ||
| 2282 | |||
| 2283 | QSpinBox, | ||
| 2284 | QLineEdit, | ||
| 2285 | QTreeView#hotkey_list, | ||
| 2286 | QScrollArea#scrollArea QTreeView { | ||
| 2287 | background-color: #0f1922; | ||
| 2288 | } \ No newline at end of file | ||
diff --git a/externals/microprofile/microprofile.h b/externals/microprofile/microprofile.h index 6dae65a66..85d5bd5de 100644 --- a/externals/microprofile/microprofile.h +++ b/externals/microprofile/microprofile.h | |||
| @@ -1037,7 +1037,7 @@ static void MicroProfileCreateThreadLogKey() | |||
| 1037 | #else | 1037 | #else |
| 1038 | MP_THREAD_LOCAL MicroProfileThreadLog* g_MicroProfileThreadLog = 0; | 1038 | MP_THREAD_LOCAL MicroProfileThreadLog* g_MicroProfileThreadLog = 0; |
| 1039 | #endif | 1039 | #endif |
| 1040 | static bool g_bUseLock = false; /// This is used because windows does not support using mutexes under dll init(which is where global initialization is handled) | 1040 | static std::atomic<bool> g_bUseLock{false}; /// This is used because windows does not support using mutexes under dll init(which is where global initialization is handled) |
| 1041 | 1041 | ||
| 1042 | 1042 | ||
| 1043 | MICROPROFILE_DEFINE(g_MicroProfileFlip, "MicroProfile", "MicroProfileFlip", 0x3355ee); | 1043 | MICROPROFILE_DEFINE(g_MicroProfileFlip, "MicroProfile", "MicroProfileFlip", 0x3355ee); |
diff --git a/src/common/assert.h b/src/common/assert.h index 5b67c5c52..06d7b5612 100644 --- a/src/common/assert.h +++ b/src/common/assert.h | |||
| @@ -17,11 +17,12 @@ | |||
| 17 | // enough for our purposes. | 17 | // enough for our purposes. |
| 18 | template <typename Fn> | 18 | template <typename Fn> |
| 19 | #if defined(_MSC_VER) | 19 | #if defined(_MSC_VER) |
| 20 | __declspec(noinline, noreturn) | 20 | [[msvc::noinline, noreturn]] |
| 21 | #elif defined(__GNUC__) | 21 | #elif defined(__GNUC__) |
| 22 | __attribute__((noinline, noreturn, cold)) | 22 | [[gnu::cold, gnu::noinline, noreturn]] |
| 23 | #endif | 23 | #endif |
| 24 | static void assert_noinline_call(const Fn& fn) { | 24 | static void |
| 25 | assert_noinline_call(const Fn& fn) { | ||
| 25 | fn(); | 26 | fn(); |
| 26 | Crash(); | 27 | Crash(); |
| 27 | exit(1); // Keeps GCC's mouth shut about this actually returning | 28 | exit(1); // Keeps GCC's mouth shut about this actually returning |
diff --git a/src/common/param_package.h b/src/common/param_package.h index c8a70bfa9..c13e45479 100644 --- a/src/common/param_package.h +++ b/src/common/param_package.h | |||
| @@ -19,7 +19,7 @@ public: | |||
| 19 | explicit ParamPackage(const std::string& serialized); | 19 | explicit ParamPackage(const std::string& serialized); |
| 20 | ParamPackage(std::initializer_list<DataType::value_type> list); | 20 | ParamPackage(std::initializer_list<DataType::value_type> list); |
| 21 | ParamPackage(const ParamPackage& other) = default; | 21 | ParamPackage(const ParamPackage& other) = default; |
| 22 | ParamPackage(ParamPackage&& other) = default; | 22 | ParamPackage(ParamPackage&& other) noexcept = default; |
| 23 | 23 | ||
| 24 | ParamPackage& operator=(const ParamPackage& other) = default; | 24 | ParamPackage& operator=(const ParamPackage& other) = default; |
| 25 | ParamPackage& operator=(ParamPackage&& other) = default; | 25 | ParamPackage& operator=(ParamPackage&& other) = default; |
diff --git a/src/common/thread.cpp b/src/common/thread.cpp index 8e5935e6a..d2c1ac60d 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/common_funcs.h" | ||
| 6 | #include "common/logging/log.h" | ||
| 5 | #include "common/thread.h" | 7 | #include "common/thread.h" |
| 6 | #ifdef __APPLE__ | 8 | #ifdef __APPLE__ |
| 7 | #include <mach/mach.h> | 9 | #include <mach/mach.h> |
| @@ -19,6 +21,8 @@ | |||
| 19 | #include <unistd.h> | 21 | #include <unistd.h> |
| 20 | #endif | 22 | #endif |
| 21 | 23 | ||
| 24 | #include <string> | ||
| 25 | |||
| 22 | #ifdef __FreeBSD__ | 26 | #ifdef __FreeBSD__ |
| 23 | #define cpu_set_t cpuset_t | 27 | #define cpu_set_t cpuset_t |
| 24 | #endif | 28 | #endif |
| @@ -110,6 +114,14 @@ void SetCurrentThreadName(const char* name) { | |||
| 110 | pthread_set_name_np(pthread_self(), name); | 114 | pthread_set_name_np(pthread_self(), name); |
| 111 | #elif defined(__NetBSD__) | 115 | #elif defined(__NetBSD__) |
| 112 | pthread_setname_np(pthread_self(), "%s", (void*)name); | 116 | pthread_setname_np(pthread_self(), "%s", (void*)name); |
| 117 | #elif defined(__linux__) | ||
| 118 | // Linux limits thread names to 15 characters and will outright reject any | ||
| 119 | // attempt to set a longer name with ERANGE. | ||
| 120 | std::string truncated(name, std::min(strlen(name), static_cast<size_t>(15))); | ||
| 121 | if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) { | ||
| 122 | errno = e; | ||
| 123 | LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg()); | ||
| 124 | } | ||
| 113 | #else | 125 | #else |
| 114 | pthread_setname_np(pthread_self(), name); | 126 | pthread_setname_np(pthread_self(), name); |
| 115 | #endif | 127 | #endif |
diff --git a/src/common/thread.h b/src/common/thread.h index 52b359413..a8c17c71a 100644 --- a/src/common/thread.h +++ b/src/common/thread.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | ||
| 7 | #include <chrono> | 8 | #include <chrono> |
| 8 | #include <condition_variable> | 9 | #include <condition_variable> |
| 9 | #include <cstddef> | 10 | #include <cstddef> |
| @@ -25,13 +26,13 @@ public: | |||
| 25 | 26 | ||
| 26 | void Wait() { | 27 | void Wait() { |
| 27 | std::unique_lock lk{mutex}; | 28 | std::unique_lock lk{mutex}; |
| 28 | condvar.wait(lk, [&] { return is_set; }); | 29 | condvar.wait(lk, [&] { return is_set.load(); }); |
| 29 | is_set = false; | 30 | is_set = false; |
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | bool WaitFor(const std::chrono::nanoseconds& time) { | 33 | bool WaitFor(const std::chrono::nanoseconds& time) { |
| 33 | std::unique_lock lk{mutex}; | 34 | std::unique_lock lk{mutex}; |
| 34 | if (!condvar.wait_for(lk, time, [this] { return is_set; })) | 35 | if (!condvar.wait_for(lk, time, [this] { return is_set.load(); })) |
| 35 | return false; | 36 | return false; |
| 36 | is_set = false; | 37 | is_set = false; |
| 37 | return true; | 38 | return true; |
| @@ -40,7 +41,7 @@ public: | |||
| 40 | template <class Clock, class Duration> | 41 | template <class Clock, class Duration> |
| 41 | bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) { | 42 | bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) { |
| 42 | std::unique_lock lk{mutex}; | 43 | std::unique_lock lk{mutex}; |
| 43 | if (!condvar.wait_until(lk, time, [this] { return is_set; })) | 44 | if (!condvar.wait_until(lk, time, [this] { return is_set.load(); })) |
| 44 | return false; | 45 | return false; |
| 45 | is_set = false; | 46 | is_set = false; |
| 46 | return true; | 47 | return true; |
| @@ -54,9 +55,9 @@ public: | |||
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | private: | 57 | private: |
| 57 | bool is_set = false; | ||
| 58 | std::condition_variable condvar; | 58 | std::condition_variable condvar; |
| 59 | std::mutex mutex; | 59 | std::mutex mutex; |
| 60 | std::atomic_bool is_set{false}; | ||
| 60 | }; | 61 | }; |
| 61 | 62 | ||
| 62 | class Barrier { | 63 | class Barrier { |
diff --git a/src/core/arm/cpu_interrupt_handler.cpp b/src/core/arm/cpu_interrupt_handler.cpp index df0350881..9c8898700 100644 --- a/src/core/arm/cpu_interrupt_handler.cpp +++ b/src/core/arm/cpu_interrupt_handler.cpp | |||
| @@ -7,9 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | namespace Core { | 8 | namespace Core { |
| 9 | 9 | ||
| 10 | CPUInterruptHandler::CPUInterruptHandler() : is_interrupted{} { | 10 | CPUInterruptHandler::CPUInterruptHandler() : interrupt_event{std::make_unique<Common::Event>()} {} |
| 11 | interrupt_event = std::make_unique<Common::Event>(); | ||
| 12 | } | ||
| 13 | 11 | ||
| 14 | CPUInterruptHandler::~CPUInterruptHandler() = default; | 12 | CPUInterruptHandler::~CPUInterruptHandler() = default; |
| 15 | 13 | ||
| @@ -17,7 +15,7 @@ void CPUInterruptHandler::SetInterrupt(bool is_interrupted_) { | |||
| 17 | if (is_interrupted_) { | 15 | if (is_interrupted_) { |
| 18 | interrupt_event->Set(); | 16 | interrupt_event->Set(); |
| 19 | } | 17 | } |
| 20 | this->is_interrupted = is_interrupted_; | 18 | is_interrupted = is_interrupted_; |
| 21 | } | 19 | } |
| 22 | 20 | ||
| 23 | void CPUInterruptHandler::AwaitInterrupt() { | 21 | void CPUInterruptHandler::AwaitInterrupt() { |
diff --git a/src/core/arm/cpu_interrupt_handler.h b/src/core/arm/cpu_interrupt_handler.h index 3d062d326..71e582f79 100644 --- a/src/core/arm/cpu_interrupt_handler.h +++ b/src/core/arm/cpu_interrupt_handler.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | ||
| 7 | #include <memory> | 8 | #include <memory> |
| 8 | 9 | ||
| 9 | namespace Common { | 10 | namespace Common { |
| @@ -32,8 +33,8 @@ public: | |||
| 32 | void AwaitInterrupt(); | 33 | void AwaitInterrupt(); |
| 33 | 34 | ||
| 34 | private: | 35 | private: |
| 35 | bool is_interrupted{}; | ||
| 36 | std::unique_ptr<Common::Event> interrupt_event; | 36 | std::unique_ptr<Common::Event> interrupt_event; |
| 37 | std::atomic_bool is_interrupted{false}; | ||
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| 39 | } // namespace Core | 40 | } // namespace Core |
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index ef0bae556..688b99eba 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp | |||
| @@ -328,7 +328,7 @@ void CpuManager::RunThread(std::size_t core) { | |||
| 328 | system.RegisterCoreThread(core); | 328 | system.RegisterCoreThread(core); |
| 329 | std::string name; | 329 | std::string name; |
| 330 | if (is_multicore) { | 330 | if (is_multicore) { |
| 331 | name = "yuzu:CoreCPUThread_" + std::to_string(core); | 331 | name = "yuzu:CPUCore_" + std::to_string(core); |
| 332 | } else { | 332 | } else { |
| 333 | name = "yuzu:CPUThread"; | 333 | name = "yuzu:CPUThread"; |
| 334 | } | 334 | } |
diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index 91ecc30ab..e2e3bbbb3 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | ||
| 7 | #include "common/math_util.h" | 8 | #include "common/math_util.h" |
| 8 | 9 | ||
| 9 | namespace Layout { | 10 | namespace Layout { |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index cabe8d418..f2b0fe2fd 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -219,6 +219,7 @@ struct KernelCore::Impl { | |||
| 219 | return static_cast<u32>(system.GetCpuManager().CurrentCore()); | 219 | return static_cast<u32>(system.GetCpuManager().CurrentCore()); |
| 220 | } | 220 | } |
| 221 | } | 221 | } |
| 222 | std::unique_lock lock{register_thread_mutex}; | ||
| 222 | const auto it = host_thread_ids.find(this_id); | 223 | const auto it = host_thread_ids.find(this_id); |
| 223 | if (it == host_thread_ids.end()) { | 224 | if (it == host_thread_ids.end()) { |
| 224 | return Core::INVALID_HOST_THREAD_ID; | 225 | return Core::INVALID_HOST_THREAD_ID; |
| @@ -324,7 +325,7 @@ struct KernelCore::Impl { | |||
| 324 | std::unordered_map<std::thread::id, u32> host_thread_ids; | 325 | std::unordered_map<std::thread::id, u32> host_thread_ids; |
| 325 | u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; | 326 | u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; |
| 326 | std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads; | 327 | std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads; |
| 327 | std::mutex register_thread_mutex; | 328 | mutable std::mutex register_thread_mutex; |
| 328 | 329 | ||
| 329 | // Kernel memory management | 330 | // Kernel memory management |
| 330 | std::unique_ptr<Memory::MemoryManager> memory_manager; | 331 | std::unique_ptr<Memory::MemoryManager> memory_manager; |
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 0e7794dc7..45fde8df2 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -24,6 +24,7 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff; | |||
| 24 | constexpr std::size_t NPAD_OFFSET = 0x9A00; | 24 | constexpr std::size_t NPAD_OFFSET = 0x9A00; |
| 25 | constexpr u32 BATTERY_FULL = 2; | 25 | constexpr u32 BATTERY_FULL = 2; |
| 26 | constexpr u32 MAX_NPAD_ID = 7; | 26 | constexpr u32 MAX_NPAD_ID = 7; |
| 27 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 27 | constexpr std::array<u32, 10> npad_id_list{ | 28 | constexpr std::array<u32, 10> npad_id_list{ |
| 28 | 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, | 29 | 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, |
| 29 | }; | 30 | }; |
| @@ -33,19 +34,41 @@ enum class JoystickId : std::size_t { | |||
| 33 | Joystick_Right, | 34 | Joystick_Right, |
| 34 | }; | 35 | }; |
| 35 | 36 | ||
| 36 | static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type) { | 37 | Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad( |
| 38 | Settings::ControllerType type) { | ||
| 37 | switch (type) { | 39 | switch (type) { |
| 38 | case Settings::ControllerType::ProController: | 40 | case Settings::ControllerType::ProController: |
| 39 | return Controller_NPad::NPadControllerType::ProController; | 41 | return NPadControllerType::ProController; |
| 40 | case Settings::ControllerType::DualJoycon: | 42 | case Settings::ControllerType::DualJoyconDetached: |
| 41 | return Controller_NPad::NPadControllerType::JoyDual; | 43 | return NPadControllerType::JoyDual; |
| 42 | case Settings::ControllerType::LeftJoycon: | 44 | case Settings::ControllerType::LeftJoycon: |
| 43 | return Controller_NPad::NPadControllerType::JoyLeft; | 45 | return NPadControllerType::JoyLeft; |
| 44 | case Settings::ControllerType::RightJoycon: | 46 | case Settings::ControllerType::RightJoycon: |
| 45 | return Controller_NPad::NPadControllerType::JoyRight; | 47 | return NPadControllerType::JoyRight; |
| 48 | case Settings::ControllerType::Handheld: | ||
| 49 | return NPadControllerType::Handheld; | ||
| 46 | default: | 50 | default: |
| 47 | UNREACHABLE(); | 51 | UNREACHABLE(); |
| 48 | return Controller_NPad::NPadControllerType::JoyDual; | 52 | return NPadControllerType::ProController; |
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | Settings::ControllerType Controller_NPad::MapNPadToSettingsType( | ||
| 57 | Controller_NPad::NPadControllerType type) { | ||
| 58 | switch (type) { | ||
| 59 | case NPadControllerType::ProController: | ||
| 60 | return Settings::ControllerType::ProController; | ||
| 61 | case NPadControllerType::JoyDual: | ||
| 62 | return Settings::ControllerType::DualJoyconDetached; | ||
| 63 | case NPadControllerType::JoyLeft: | ||
| 64 | return Settings::ControllerType::LeftJoycon; | ||
| 65 | case NPadControllerType::JoyRight: | ||
| 66 | return Settings::ControllerType::RightJoycon; | ||
| 67 | case NPadControllerType::Handheld: | ||
| 68 | return Settings::ControllerType::Handheld; | ||
| 69 | default: | ||
| 70 | UNREACHABLE(); | ||
| 71 | return Settings::ControllerType::ProController; | ||
| 49 | } | 72 | } |
| 50 | } | 73 | } |
| 51 | 74 | ||
| @@ -60,9 +83,9 @@ std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { | |||
| 60 | case 6: | 83 | case 6: |
| 61 | case 7: | 84 | case 7: |
| 62 | return npad_id; | 85 | return npad_id; |
| 63 | case 8: | 86 | case HANDHELD_INDEX: |
| 64 | case NPAD_HANDHELD: | 87 | case NPAD_HANDHELD: |
| 65 | return 8; | 88 | return HANDHELD_INDEX; |
| 66 | case 9: | 89 | case 9: |
| 67 | case NPAD_UNKNOWN: | 90 | case NPAD_UNKNOWN: |
| 68 | return 9; | 91 | return 9; |
| @@ -83,7 +106,7 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { | |||
| 83 | case 6: | 106 | case 6: |
| 84 | case 7: | 107 | case 7: |
| 85 | return static_cast<u32>(index); | 108 | return static_cast<u32>(index); |
| 86 | case 8: | 109 | case HANDHELD_INDEX: |
| 87 | return NPAD_HANDHELD; | 110 | return NPAD_HANDHELD; |
| 88 | case 9: | 111 | case 9: |
| 89 | return NPAD_UNKNOWN; | 112 | return NPAD_UNKNOWN; |
| @@ -96,25 +119,35 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { | |||
| 96 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} | 119 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} |
| 97 | Controller_NPad::~Controller_NPad() = default; | 120 | Controller_NPad::~Controller_NPad() = default; |
| 98 | 121 | ||
| 99 | void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { | 122 | void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { |
| 100 | const auto controller_type = connected_controllers[controller_idx].type; | 123 | const auto controller_type = connected_controllers[controller_idx].type; |
| 101 | auto& controller = shared_memory_entries[controller_idx]; | 124 | auto& controller = shared_memory_entries[controller_idx]; |
| 102 | if (controller_type == NPadControllerType::None) { | 125 | if (controller_type == NPadControllerType::None) { |
| 126 | styleset_changed_events[controller_idx].writable->Signal(); | ||
| 103 | return; | 127 | return; |
| 104 | } | 128 | } |
| 105 | controller.joy_styles.raw = 0; // Zero out | 129 | controller.joy_styles.raw = 0; // Zero out |
| 106 | controller.device_type.raw = 0; | 130 | controller.device_type.raw = 0; |
| 131 | controller.properties.raw = 0; | ||
| 107 | switch (controller_type) { | 132 | switch (controller_type) { |
| 108 | case NPadControllerType::None: | 133 | case NPadControllerType::None: |
| 109 | UNREACHABLE(); | 134 | UNREACHABLE(); |
| 110 | break; | 135 | break; |
| 136 | case NPadControllerType::ProController: | ||
| 137 | controller.joy_styles.pro_controller.Assign(1); | ||
| 138 | controller.device_type.pro_controller.Assign(1); | ||
| 139 | controller.properties.is_vertical.Assign(1); | ||
| 140 | controller.properties.use_plus.Assign(1); | ||
| 141 | controller.properties.use_minus.Assign(1); | ||
| 142 | controller.pad_assignment = NPadAssignments::Single; | ||
| 143 | break; | ||
| 111 | case NPadControllerType::Handheld: | 144 | case NPadControllerType::Handheld: |
| 112 | controller.joy_styles.handheld.Assign(1); | 145 | controller.joy_styles.handheld.Assign(1); |
| 113 | controller.device_type.handheld.Assign(1); | 146 | controller.device_type.handheld.Assign(1); |
| 114 | controller.pad_assignment = NPadAssignments::Dual; | ||
| 115 | controller.properties.is_vertical.Assign(1); | 147 | controller.properties.is_vertical.Assign(1); |
| 116 | controller.properties.use_plus.Assign(1); | 148 | controller.properties.use_plus.Assign(1); |
| 117 | controller.properties.use_minus.Assign(1); | 149 | controller.properties.use_minus.Assign(1); |
| 150 | controller.pad_assignment = NPadAssignments::Dual; | ||
| 118 | break; | 151 | break; |
| 119 | case NPadControllerType::JoyDual: | 152 | case NPadControllerType::JoyDual: |
| 120 | controller.joy_styles.joycon_dual.Assign(1); | 153 | controller.joy_styles.joycon_dual.Assign(1); |
| @@ -144,14 +177,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { | |||
| 144 | controller.device_type.pokeball.Assign(1); | 177 | controller.device_type.pokeball.Assign(1); |
| 145 | controller.pad_assignment = NPadAssignments::Single; | 178 | controller.pad_assignment = NPadAssignments::Single; |
| 146 | break; | 179 | break; |
| 147 | case NPadControllerType::ProController: | ||
| 148 | controller.joy_styles.pro_controller.Assign(1); | ||
| 149 | controller.device_type.pro_controller.Assign(1); | ||
| 150 | controller.properties.is_vertical.Assign(1); | ||
| 151 | controller.properties.use_plus.Assign(1); | ||
| 152 | controller.properties.use_minus.Assign(1); | ||
| 153 | controller.pad_assignment = NPadAssignments::Single; | ||
| 154 | break; | ||
| 155 | } | 180 | } |
| 156 | 181 | ||
| 157 | controller.single_color_error = ColorReadError::ReadOk; | 182 | controller.single_color_error = ColorReadError::ReadOk; |
| @@ -192,36 +217,25 @@ void Controller_NPad::OnInit() { | |||
| 192 | style.pokeball.Assign(1); | 217 | style.pokeball.Assign(1); |
| 193 | } | 218 | } |
| 194 | 219 | ||
| 195 | std::transform( | 220 | std::transform(Settings::values.players.begin(), Settings::values.players.end(), |
| 196 | Settings::values.players.begin(), Settings::values.players.end(), | 221 | connected_controllers.begin(), [](const Settings::PlayerInput& player) { |
| 197 | connected_controllers.begin(), [](const Settings::PlayerInput& player) { | 222 | return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), |
| 198 | return ControllerHolder{MapSettingsTypeToNPad(player.type), player.connected}; | 223 | player.connected}; |
| 199 | }); | 224 | }); |
| 200 | |||
| 201 | std::stable_partition(connected_controllers.begin(), connected_controllers.begin() + 8, | ||
| 202 | [](const ControllerHolder& holder) { return holder.is_connected; }); | ||
| 203 | 225 | ||
| 204 | // Account for handheld | 226 | // Account for handheld |
| 205 | if (connected_controllers[8].is_connected) | 227 | if (connected_controllers[HANDHELD_INDEX].is_connected) { |
| 206 | connected_controllers[8].type = NPadControllerType::Handheld; | 228 | connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; |
| 229 | } | ||
| 207 | 230 | ||
| 208 | supported_npad_id_types.resize(npad_id_list.size()); | 231 | supported_npad_id_types.resize(npad_id_list.size()); |
| 209 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), | 232 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), |
| 210 | npad_id_list.size() * sizeof(u32)); | 233 | npad_id_list.size() * sizeof(u32)); |
| 211 | 234 | ||
| 212 | // Add a default dual joycon controller if none are present. | ||
| 213 | if (std::none_of(connected_controllers.begin(), connected_controllers.end(), | ||
| 214 | [](const ControllerHolder& controller) { return controller.is_connected; })) { | ||
| 215 | supported_npad_id_types.resize(npad_id_list.size()); | ||
| 216 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), | ||
| 217 | npad_id_list.size() * sizeof(u32)); | ||
| 218 | AddNewController(NPadControllerType::JoyDual); | ||
| 219 | } | ||
| 220 | |||
| 221 | for (std::size_t i = 0; i < connected_controllers.size(); ++i) { | 235 | for (std::size_t i = 0; i < connected_controllers.size(); ++i) { |
| 222 | const auto& controller = connected_controllers[i]; | 236 | const auto& controller = connected_controllers[i]; |
| 223 | if (controller.is_connected) { | 237 | if (controller.is_connected) { |
| 224 | AddNewControllerAt(controller.type, IndexToNPad(i)); | 238 | AddNewControllerAt(controller.type, i); |
| 225 | } | 239 | } |
| 226 | } | 240 | } |
| 227 | } | 241 | } |
| @@ -309,8 +323,9 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { | |||
| 309 | 323 | ||
| 310 | void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, | 324 | void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, |
| 311 | std::size_t data_len) { | 325 | std::size_t data_len) { |
| 312 | if (!IsControllerActivated()) | 326 | if (!IsControllerActivated()) { |
| 313 | return; | 327 | return; |
| 328 | } | ||
| 314 | for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { | 329 | for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { |
| 315 | auto& npad = shared_memory_entries[i]; | 330 | auto& npad = shared_memory_entries[i]; |
| 316 | const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, | 331 | const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, |
| @@ -360,13 +375,25 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 360 | auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; | 375 | auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; |
| 361 | 376 | ||
| 362 | libnx_entry.connection_status.raw = 0; | 377 | libnx_entry.connection_status.raw = 0; |
| 378 | libnx_entry.connection_status.IsConnected.Assign(1); | ||
| 363 | 379 | ||
| 364 | switch (controller_type) { | 380 | switch (controller_type) { |
| 365 | case NPadControllerType::None: | 381 | case NPadControllerType::None: |
| 366 | UNREACHABLE(); | 382 | UNREACHABLE(); |
| 367 | break; | 383 | break; |
| 384 | case NPadControllerType::ProController: | ||
| 385 | main_controller.connection_status.raw = 0; | ||
| 386 | main_controller.connection_status.IsConnected.Assign(1); | ||
| 387 | main_controller.connection_status.IsWired.Assign(1); | ||
| 388 | main_controller.pad.pad_states.raw = pad_state.pad_states.raw; | ||
| 389 | main_controller.pad.l_stick = pad_state.l_stick; | ||
| 390 | main_controller.pad.r_stick = pad_state.r_stick; | ||
| 391 | |||
| 392 | libnx_entry.connection_status.IsWired.Assign(1); | ||
| 393 | break; | ||
| 368 | case NPadControllerType::Handheld: | 394 | case NPadControllerType::Handheld: |
| 369 | handheld_entry.connection_status.raw = 0; | 395 | handheld_entry.connection_status.raw = 0; |
| 396 | handheld_entry.connection_status.IsConnected.Assign(1); | ||
| 370 | handheld_entry.connection_status.IsWired.Assign(1); | 397 | handheld_entry.connection_status.IsWired.Assign(1); |
| 371 | handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); | 398 | handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); |
| 372 | handheld_entry.connection_status.IsRightJoyConnected.Assign(1); | 399 | handheld_entry.connection_status.IsRightJoyConnected.Assign(1); |
| @@ -375,57 +402,52 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 375 | handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 402 | handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 376 | handheld_entry.pad.l_stick = pad_state.l_stick; | 403 | handheld_entry.pad.l_stick = pad_state.l_stick; |
| 377 | handheld_entry.pad.r_stick = pad_state.r_stick; | 404 | handheld_entry.pad.r_stick = pad_state.r_stick; |
| 405 | |||
| 406 | libnx_entry.connection_status.IsWired.Assign(1); | ||
| 407 | libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 408 | libnx_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 409 | libnx_entry.connection_status.IsLeftJoyWired.Assign(1); | ||
| 410 | libnx_entry.connection_status.IsRightJoyWired.Assign(1); | ||
| 378 | break; | 411 | break; |
| 379 | case NPadControllerType::JoyDual: | 412 | case NPadControllerType::JoyDual: |
| 380 | dual_entry.connection_status.raw = 0; | 413 | dual_entry.connection_status.raw = 0; |
| 381 | 414 | dual_entry.connection_status.IsConnected.Assign(1); | |
| 382 | dual_entry.connection_status.IsLeftJoyConnected.Assign(1); | 415 | dual_entry.connection_status.IsLeftJoyConnected.Assign(1); |
| 383 | dual_entry.connection_status.IsRightJoyConnected.Assign(1); | 416 | dual_entry.connection_status.IsRightJoyConnected.Assign(1); |
| 384 | dual_entry.connection_status.IsConnected.Assign(1); | ||
| 385 | |||
| 386 | libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 387 | libnx_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 388 | libnx_entry.connection_status.IsConnected.Assign(1); | ||
| 389 | |||
| 390 | dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 417 | dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 391 | dual_entry.pad.l_stick = pad_state.l_stick; | 418 | dual_entry.pad.l_stick = pad_state.l_stick; |
| 392 | dual_entry.pad.r_stick = pad_state.r_stick; | 419 | dual_entry.pad.r_stick = pad_state.r_stick; |
| 420 | |||
| 421 | libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 422 | libnx_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 393 | break; | 423 | break; |
| 394 | case NPadControllerType::JoyLeft: | 424 | case NPadControllerType::JoyLeft: |
| 395 | left_entry.connection_status.raw = 0; | 425 | left_entry.connection_status.raw = 0; |
| 396 | |||
| 397 | left_entry.connection_status.IsConnected.Assign(1); | 426 | left_entry.connection_status.IsConnected.Assign(1); |
| 427 | left_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 398 | left_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 428 | left_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 399 | left_entry.pad.l_stick = pad_state.l_stick; | 429 | left_entry.pad.l_stick = pad_state.l_stick; |
| 400 | left_entry.pad.r_stick = pad_state.r_stick; | 430 | left_entry.pad.r_stick = pad_state.r_stick; |
| 431 | |||
| 432 | libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 401 | break; | 433 | break; |
| 402 | case NPadControllerType::JoyRight: | 434 | case NPadControllerType::JoyRight: |
| 403 | right_entry.connection_status.raw = 0; | 435 | right_entry.connection_status.raw = 0; |
| 404 | |||
| 405 | right_entry.connection_status.IsConnected.Assign(1); | 436 | right_entry.connection_status.IsConnected.Assign(1); |
| 437 | right_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 406 | right_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 438 | right_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 407 | right_entry.pad.l_stick = pad_state.l_stick; | 439 | right_entry.pad.l_stick = pad_state.l_stick; |
| 408 | right_entry.pad.r_stick = pad_state.r_stick; | 440 | right_entry.pad.r_stick = pad_state.r_stick; |
| 441 | |||
| 442 | libnx_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 409 | break; | 443 | break; |
| 410 | case NPadControllerType::Pokeball: | 444 | case NPadControllerType::Pokeball: |
| 411 | pokeball_entry.connection_status.raw = 0; | 445 | pokeball_entry.connection_status.raw = 0; |
| 412 | |||
| 413 | pokeball_entry.connection_status.IsConnected.Assign(1); | 446 | pokeball_entry.connection_status.IsConnected.Assign(1); |
| 414 | pokeball_entry.connection_status.IsWired.Assign(1); | ||
| 415 | |||
| 416 | pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 447 | pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 417 | pokeball_entry.pad.l_stick = pad_state.l_stick; | 448 | pokeball_entry.pad.l_stick = pad_state.l_stick; |
| 418 | pokeball_entry.pad.r_stick = pad_state.r_stick; | 449 | pokeball_entry.pad.r_stick = pad_state.r_stick; |
| 419 | break; | 450 | break; |
| 420 | case NPadControllerType::ProController: | ||
| 421 | main_controller.connection_status.raw = 0; | ||
| 422 | |||
| 423 | main_controller.connection_status.IsConnected.Assign(1); | ||
| 424 | main_controller.connection_status.IsWired.Assign(1); | ||
| 425 | main_controller.pad.pad_states.raw = pad_state.pad_states.raw; | ||
| 426 | main_controller.pad.l_stick = pad_state.l_stick; | ||
| 427 | main_controller.pad.r_stick = pad_state.r_stick; | ||
| 428 | break; | ||
| 429 | } | 451 | } |
| 430 | 452 | ||
| 431 | // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate | 453 | // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate |
| @@ -453,26 +475,6 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { | |||
| 453 | supported_npad_id_types.clear(); | 475 | supported_npad_id_types.clear(); |
| 454 | supported_npad_id_types.resize(length / sizeof(u32)); | 476 | supported_npad_id_types.resize(length / sizeof(u32)); |
| 455 | std::memcpy(supported_npad_id_types.data(), data, length); | 477 | std::memcpy(supported_npad_id_types.data(), data, length); |
| 456 | for (std::size_t i = 0; i < connected_controllers.size(); i++) { | ||
| 457 | auto& controller = connected_controllers[i]; | ||
| 458 | if (!controller.is_connected) { | ||
| 459 | continue; | ||
| 460 | } | ||
| 461 | const auto requested_controller = | ||
| 462 | i <= MAX_NPAD_ID ? MapSettingsTypeToNPad(Settings::values.players[i].type) | ||
| 463 | : NPadControllerType::Handheld; | ||
| 464 | if (!IsControllerSupported(requested_controller)) { | ||
| 465 | const auto is_handheld = requested_controller == NPadControllerType::Handheld; | ||
| 466 | if (is_handheld) { | ||
| 467 | controller.type = NPadControllerType::None; | ||
| 468 | controller.is_connected = false; | ||
| 469 | AddNewController(requested_controller); | ||
| 470 | } else { | ||
| 471 | controller.type = requested_controller; | ||
| 472 | InitNewlyAddedControler(i); | ||
| 473 | } | ||
| 474 | } | ||
| 475 | } | ||
| 476 | } | 478 | } |
| 477 | 479 | ||
| 478 | void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { | 480 | void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { |
| @@ -504,7 +506,7 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | |||
| 504 | const std::vector<Vibration>& vibrations) { | 506 | const std::vector<Vibration>& vibrations) { |
| 505 | LOG_DEBUG(Service_HID, "(STUBBED) called"); | 507 | LOG_DEBUG(Service_HID, "(STUBBED) called"); |
| 506 | 508 | ||
| 507 | if (!can_controllers_vibrate) { | 509 | if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { |
| 508 | return; | 510 | return; |
| 509 | } | 511 | } |
| 510 | for (std::size_t i = 0; i < controller_ids.size(); i++) { | 512 | for (std::size_t i = 0; i < controller_ids.size(); i++) { |
| @@ -517,8 +519,6 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | |||
| 517 | } | 519 | } |
| 518 | 520 | ||
| 519 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { | 521 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { |
| 520 | // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should | ||
| 521 | // be signalled at least once, and signaled after a new controller is connected? | ||
| 522 | const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; | 522 | const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; |
| 523 | return styleset_event.readable; | 523 | return styleset_event.readable; |
| 524 | } | 524 | } |
| @@ -527,43 +527,43 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { | |||
| 527 | return last_processed_vibration; | 527 | return last_processed_vibration; |
| 528 | } | 528 | } |
| 529 | 529 | ||
| 530 | void Controller_NPad::AddNewController(NPadControllerType controller) { | 530 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { |
| 531 | controller = DecideBestController(controller); | 531 | UpdateControllerAt(controller, npad_index, true); |
| 532 | if (controller == NPadControllerType::Handheld) { | 532 | } |
| 533 | connected_controllers[8] = {controller, true}; | 533 | |
| 534 | InitNewlyAddedControler(8); | 534 | void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, |
| 535 | return; | 535 | bool connected) { |
| 536 | } | 536 | if (!connected) { |
| 537 | const auto pos = | 537 | DisconnectNPad(IndexToNPad(npad_index)); |
| 538 | std::find_if(connected_controllers.begin(), connected_controllers.end() - 2, | ||
| 539 | [](const ControllerHolder& holder) { return !holder.is_connected; }); | ||
| 540 | if (pos == connected_controllers.end() - 2) { | ||
| 541 | LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); | ||
| 542 | return; | 538 | return; |
| 543 | } | 539 | } |
| 544 | const auto controller_id = std::distance(connected_controllers.begin(), pos); | ||
| 545 | connected_controllers[controller_id] = {controller, true}; | ||
| 546 | InitNewlyAddedControler(controller_id); | ||
| 547 | } | ||
| 548 | 540 | ||
| 549 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) { | ||
| 550 | controller = DecideBestController(controller); | ||
| 551 | if (controller == NPadControllerType::Handheld) { | 541 | if (controller == NPadControllerType::Handheld) { |
| 552 | connected_controllers[NPadIdToIndex(NPAD_HANDHELD)] = {controller, true}; | 542 | Settings::values.players[HANDHELD_INDEX].controller_type = |
| 553 | InitNewlyAddedControler(NPadIdToIndex(NPAD_HANDHELD)); | 543 | MapNPadToSettingsType(controller); |
| 544 | Settings::values.players[HANDHELD_INDEX].connected = true; | ||
| 545 | connected_controllers[HANDHELD_INDEX] = {controller, true}; | ||
| 546 | InitNewlyAddedController(HANDHELD_INDEX); | ||
| 554 | return; | 547 | return; |
| 555 | } | 548 | } |
| 556 | 549 | ||
| 557 | connected_controllers[NPadIdToIndex(npad_id)] = {controller, true}; | 550 | Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller); |
| 558 | InitNewlyAddedControler(NPadIdToIndex(npad_id)); | 551 | Settings::values.players[npad_index].connected = true; |
| 559 | } | 552 | connected_controllers[npad_index] = {controller, true}; |
| 560 | 553 | InitNewlyAddedController(npad_index); | |
| 561 | void Controller_NPad::ConnectNPad(u32 npad_id) { | ||
| 562 | connected_controllers[NPadIdToIndex(npad_id)].is_connected = true; | ||
| 563 | } | 554 | } |
| 564 | 555 | ||
| 565 | void Controller_NPad::DisconnectNPad(u32 npad_id) { | 556 | void Controller_NPad::DisconnectNPad(u32 npad_id) { |
| 566 | connected_controllers[NPadIdToIndex(npad_id)].is_connected = false; | 557 | const auto npad_index = NPadIdToIndex(npad_id); |
| 558 | connected_controllers[npad_index].is_connected = false; | ||
| 559 | Settings::values.players[npad_index].connected = false; | ||
| 560 | |||
| 561 | auto& controller = shared_memory_entries[npad_index]; | ||
| 562 | controller.joy_styles.raw = 0; // Zero out | ||
| 563 | controller.device_type.raw = 0; | ||
| 564 | controller.properties.raw = 0; | ||
| 565 | |||
| 566 | styleset_changed_events[npad_index].writable->Signal(); | ||
| 567 | } | 567 | } |
| 568 | 568 | ||
| 569 | void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { | 569 | void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { |
| @@ -599,8 +599,8 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { | |||
| 599 | 599 | ||
| 600 | std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); | 600 | std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); |
| 601 | 601 | ||
| 602 | InitNewlyAddedControler(npad_index_1); | 602 | AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1); |
| 603 | InitNewlyAddedControler(npad_index_2); | 603 | AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2); |
| 604 | 604 | ||
| 605 | return true; | 605 | return true; |
| 606 | } | 606 | } |
| @@ -614,11 +614,11 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { | |||
| 614 | case 0: | 614 | case 0: |
| 615 | return LedPattern{1, 0, 0, 0}; | 615 | return LedPattern{1, 0, 0, 0}; |
| 616 | case 1: | 616 | case 1: |
| 617 | return LedPattern{0, 1, 0, 0}; | 617 | return LedPattern{1, 1, 0, 0}; |
| 618 | case 2: | 618 | case 2: |
| 619 | return LedPattern{0, 0, 1, 0}; | 619 | return LedPattern{1, 1, 1, 0}; |
| 620 | case 3: | 620 | case 3: |
| 621 | return LedPattern{0, 0, 0, 1}; | 621 | return LedPattern{1, 1, 1, 1}; |
| 622 | case 4: | 622 | case 4: |
| 623 | return LedPattern{1, 0, 0, 1}; | 623 | return LedPattern{1, 0, 0, 1}; |
| 624 | case 5: | 624 | case 5: |
| @@ -628,7 +628,6 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { | |||
| 628 | case 7: | 628 | case 7: |
| 629 | return LedPattern{0, 1, 1, 0}; | 629 | return LedPattern{0, 1, 1, 0}; |
| 630 | default: | 630 | default: |
| 631 | UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id); | ||
| 632 | return LedPattern{0, 0, 0, 0}; | 631 | return LedPattern{0, 0, 0, 0}; |
| 633 | } | 632 | } |
| 634 | } | 633 | } |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 5d4c58a43..75ce5b731 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -118,10 +118,11 @@ public: | |||
| 118 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; | 118 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; |
| 119 | Vibration GetLastVibration() const; | 119 | Vibration GetLastVibration() const; |
| 120 | 120 | ||
| 121 | void AddNewController(NPadControllerType controller); | 121 | // Adds a new controller at an index. |
| 122 | void AddNewControllerAt(NPadControllerType controller, u32 npad_id); | 122 | void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); |
| 123 | // Adds a new controller at an index with connection status. | ||
| 124 | void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); | ||
| 123 | 125 | ||
| 124 | void ConnectNPad(u32 npad_id); | ||
| 125 | void DisconnectNPad(u32 npad_id); | 126 | void DisconnectNPad(u32 npad_id); |
| 126 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); | 127 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); |
| 127 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; | 128 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; |
| @@ -141,6 +142,8 @@ public: | |||
| 141 | // Specifically for cheat engine and other features. | 142 | // Specifically for cheat engine and other features. |
| 142 | u32 GetAndResetPressState(); | 143 | u32 GetAndResetPressState(); |
| 143 | 144 | ||
| 145 | static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type); | ||
| 146 | static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); | ||
| 144 | static std::size_t NPadIdToIndex(u32 npad_id); | 147 | static std::size_t NPadIdToIndex(u32 npad_id); |
| 145 | static u32 IndexToNPad(std::size_t index); | 148 | static u32 IndexToNPad(std::size_t index); |
| 146 | 149 | ||
| @@ -309,7 +312,7 @@ private: | |||
| 309 | bool is_connected; | 312 | bool is_connected; |
| 310 | }; | 313 | }; |
| 311 | 314 | ||
| 312 | void InitNewlyAddedControler(std::size_t controller_idx); | 315 | void InitNewlyAddedController(std::size_t controller_idx); |
| 313 | bool IsControllerSupported(NPadControllerType controller) const; | 316 | bool IsControllerSupported(NPadControllerType controller) const; |
| 314 | NPadControllerType DecideBestController(NPadControllerType priority) const; | 317 | NPadControllerType DecideBestController(NPadControllerType priority) const; |
| 315 | void RequestPadStateUpdate(u32 npad_id); | 318 | void RequestPadStateUpdate(u32 npad_id); |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index e326f8f5c..0df395e85 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp | |||
| @@ -40,9 +40,14 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin | |||
| 40 | cur_entry.sampling_number = last_entry.sampling_number + 1; | 40 | cur_entry.sampling_number = last_entry.sampling_number + 1; |
| 41 | cur_entry.sampling_number2 = cur_entry.sampling_number; | 41 | cur_entry.sampling_number2 = cur_entry.sampling_number; |
| 42 | 42 | ||
| 43 | const auto [x, y, pressed] = touch_device->GetStatus(); | 43 | bool pressed = false; |
| 44 | float x, y; | ||
| 45 | std::tie(x, y, pressed) = touch_device->GetStatus(); | ||
| 44 | auto& touch_entry = cur_entry.states[0]; | 46 | auto& touch_entry = cur_entry.states[0]; |
| 45 | touch_entry.attribute.raw = 0; | 47 | touch_entry.attribute.raw = 0; |
| 48 | if (!pressed && touch_btn_device) { | ||
| 49 | std::tie(x, y, pressed) = touch_btn_device->GetStatus(); | ||
| 50 | } | ||
| 46 | if (pressed && Settings::values.touchscreen.enabled) { | 51 | if (pressed && Settings::values.touchscreen.enabled) { |
| 47 | touch_entry.x = static_cast<u16>(x * Layout::ScreenUndocked::Width); | 52 | touch_entry.x = static_cast<u16>(x * Layout::ScreenUndocked::Width); |
| 48 | touch_entry.y = static_cast<u16>(y * Layout::ScreenUndocked::Height); | 53 | touch_entry.y = static_cast<u16>(y * Layout::ScreenUndocked::Height); |
| @@ -63,5 +68,10 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin | |||
| 63 | 68 | ||
| 64 | void Controller_Touchscreen::OnLoadInputDevices() { | 69 | void Controller_Touchscreen::OnLoadInputDevices() { |
| 65 | touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touchscreen.device); | 70 | touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touchscreen.device); |
| 71 | if (Settings::values.use_touch_from_button) { | ||
| 72 | touch_btn_device = Input::CreateDevice<Input::TouchDevice>("engine:touch_from_button"); | ||
| 73 | } else { | ||
| 74 | touch_btn_device.reset(); | ||
| 75 | } | ||
| 66 | } | 76 | } |
| 67 | } // namespace Service::HID | 77 | } // namespace Service::HID |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index a1d97269e..4d9042adc 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h | |||
| @@ -68,6 +68,7 @@ private: | |||
| 68 | "TouchScreenSharedMemory is an invalid size"); | 68 | "TouchScreenSharedMemory is an invalid size"); |
| 69 | TouchScreenSharedMemory shared_memory{}; | 69 | TouchScreenSharedMemory shared_memory{}; |
| 70 | std::unique_ptr<Input::TouchDevice> touch_device; | 70 | std::unique_ptr<Input::TouchDevice> touch_device; |
| 71 | std::unique_ptr<Input::TouchDevice> touch_btn_device; | ||
| 71 | s64_le last_touch{}; | 72 | s64_le last_touch{}; |
| 72 | }; | 73 | }; |
| 73 | } // namespace Service::HID | 74 | } // namespace Service::HID |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 1e95b7580..33416b5dd 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -38,11 +38,9 @@ | |||
| 38 | namespace Service::HID { | 38 | namespace Service::HID { |
| 39 | 39 | ||
| 40 | // Updating period for each HID device. | 40 | // Updating period for each HID device. |
| 41 | // TODO(ogniK): Find actual polling rate of hid | 41 | // HID is polled every 15ms, this value was derived from |
| 42 | constexpr auto pad_update_ns = std::chrono::nanoseconds{1000000000 / 66}; | 42 | // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet |
| 43 | [[maybe_unused]] constexpr auto accelerometer_update_ns = | 43 | constexpr auto pad_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.6Hz) |
| 44 | std::chrono::nanoseconds{1000000000 / 100}; | ||
| 45 | [[maybe_unused]] constexpr auto gyroscope_update_ticks = std::chrono::nanoseconds{1000000000 / 100}; | ||
| 46 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; | 44 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; |
| 47 | 45 | ||
| 48 | IAppletResource::IAppletResource(Core::System& system) | 46 | IAppletResource::IAppletResource(Core::System& system) |
| @@ -845,8 +843,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { | |||
| 845 | void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { | 843 | void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { |
| 846 | IPC::RequestParser rp{ctx}; | 844 | IPC::RequestParser rp{ctx}; |
| 847 | const auto can_vibrate{rp.Pop<bool>()}; | 845 | const auto can_vibrate{rp.Pop<bool>()}; |
| 848 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 846 | Settings::values.vibration_enabled = can_vibrate; |
| 849 | .SetVibrationEnabled(can_vibrate); | ||
| 850 | 847 | ||
| 851 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); | 848 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); |
| 852 | 849 | ||
| @@ -859,8 +856,7 @@ void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { | |||
| 859 | 856 | ||
| 860 | IPC::ResponseBuilder rb{ctx, 3}; | 857 | IPC::ResponseBuilder rb{ctx, 3}; |
| 861 | rb.Push(RESULT_SUCCESS); | 858 | rb.Push(RESULT_SUCCESS); |
| 862 | rb.Push( | 859 | rb.Push(Settings::values.vibration_enabled); |
| 863 | applet_resource->GetController<Controller_NPad>(HidController::NPad).IsVibrationEnabled()); | ||
| 864 | } | 860 | } |
| 865 | 861 | ||
| 866 | void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | 862 | void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index d328fb8b7..28d3f9099 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -13,56 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | namespace Settings { | 14 | namespace Settings { |
| 15 | 15 | ||
| 16 | namespace NativeButton { | ||
| 17 | const std::array<const char*, NumButtons> mapping = {{ | ||
| 18 | "button_a", | ||
| 19 | "button_b", | ||
| 20 | "button_x", | ||
| 21 | "button_y", | ||
| 22 | "button_lstick", | ||
| 23 | "button_rstick", | ||
| 24 | "button_l", | ||
| 25 | "button_r", | ||
| 26 | "button_zl", | ||
| 27 | "button_zr", | ||
| 28 | "button_plus", | ||
| 29 | "button_minus", | ||
| 30 | "button_dleft", | ||
| 31 | "button_dup", | ||
| 32 | "button_dright", | ||
| 33 | "button_ddown", | ||
| 34 | "button_lstick_left", | ||
| 35 | "button_lstick_up", | ||
| 36 | "button_lstick_right", | ||
| 37 | "button_lstick_down", | ||
| 38 | "button_rstick_left", | ||
| 39 | "button_rstick_up", | ||
| 40 | "button_rstick_right", | ||
| 41 | "button_rstick_down", | ||
| 42 | "button_sl", | ||
| 43 | "button_sr", | ||
| 44 | "button_home", | ||
| 45 | "button_screenshot", | ||
| 46 | }}; | ||
| 47 | } | ||
| 48 | |||
| 49 | namespace NativeAnalog { | ||
| 50 | const std::array<const char*, NumAnalogs> mapping = {{ | ||
| 51 | "lstick", | ||
| 52 | "rstick", | ||
| 53 | }}; | ||
| 54 | } | ||
| 55 | |||
| 56 | namespace NativeMouseButton { | ||
| 57 | const std::array<const char*, NumMouseButtons> mapping = {{ | ||
| 58 | "left", | ||
| 59 | "right", | ||
| 60 | "middle", | ||
| 61 | "forward", | ||
| 62 | "back", | ||
| 63 | }}; | ||
| 64 | } | ||
| 65 | |||
| 66 | Values values = {}; | 16 | Values values = {}; |
| 67 | bool configuring_global = true; | 17 | bool configuring_global = true; |
| 68 | 18 | ||
diff --git a/src/core/settings.h b/src/core/settings.h index 3681b5e9d..80f0d95a7 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -12,340 +12,10 @@ | |||
| 12 | #include <string> | 12 | #include <string> |
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "input_common/settings.h" | ||
| 15 | 16 | ||
| 16 | namespace Settings { | 17 | namespace Settings { |
| 17 | 18 | ||
| 18 | namespace NativeButton { | ||
| 19 | enum Values { | ||
| 20 | A, | ||
| 21 | B, | ||
| 22 | X, | ||
| 23 | Y, | ||
| 24 | LStick, | ||
| 25 | RStick, | ||
| 26 | L, | ||
| 27 | R, | ||
| 28 | ZL, | ||
| 29 | ZR, | ||
| 30 | Plus, | ||
| 31 | Minus, | ||
| 32 | |||
| 33 | DLeft, | ||
| 34 | DUp, | ||
| 35 | DRight, | ||
| 36 | DDown, | ||
| 37 | |||
| 38 | LStick_Left, | ||
| 39 | LStick_Up, | ||
| 40 | LStick_Right, | ||
| 41 | LStick_Down, | ||
| 42 | |||
| 43 | RStick_Left, | ||
| 44 | RStick_Up, | ||
| 45 | RStick_Right, | ||
| 46 | RStick_Down, | ||
| 47 | |||
| 48 | SL, | ||
| 49 | SR, | ||
| 50 | |||
| 51 | Home, | ||
| 52 | Screenshot, | ||
| 53 | |||
| 54 | NumButtons, | ||
| 55 | }; | ||
| 56 | |||
| 57 | constexpr int BUTTON_HID_BEGIN = A; | ||
| 58 | constexpr int BUTTON_NS_BEGIN = Home; | ||
| 59 | |||
| 60 | constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN; | ||
| 61 | constexpr int BUTTON_NS_END = NumButtons; | ||
| 62 | |||
| 63 | constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; | ||
| 64 | constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; | ||
| 65 | |||
| 66 | extern const std::array<const char*, NumButtons> mapping; | ||
| 67 | |||
| 68 | } // namespace NativeButton | ||
| 69 | |||
| 70 | namespace NativeAnalog { | ||
| 71 | enum Values { | ||
| 72 | LStick, | ||
| 73 | RStick, | ||
| 74 | |||
| 75 | NumAnalogs, | ||
| 76 | }; | ||
| 77 | |||
| 78 | constexpr int STICK_HID_BEGIN = LStick; | ||
| 79 | constexpr int STICK_HID_END = NumAnalogs; | ||
| 80 | constexpr int NUM_STICKS_HID = NumAnalogs; | ||
| 81 | |||
| 82 | extern const std::array<const char*, NumAnalogs> mapping; | ||
| 83 | } // namespace NativeAnalog | ||
| 84 | |||
| 85 | namespace NativeMouseButton { | ||
| 86 | enum Values { | ||
| 87 | Left, | ||
| 88 | Right, | ||
| 89 | Middle, | ||
| 90 | Forward, | ||
| 91 | Back, | ||
| 92 | |||
| 93 | NumMouseButtons, | ||
| 94 | }; | ||
| 95 | |||
| 96 | constexpr int MOUSE_HID_BEGIN = Left; | ||
| 97 | constexpr int MOUSE_HID_END = NumMouseButtons; | ||
| 98 | constexpr int NUM_MOUSE_HID = NumMouseButtons; | ||
| 99 | |||
| 100 | extern const std::array<const char*, NumMouseButtons> mapping; | ||
| 101 | } // namespace NativeMouseButton | ||
| 102 | |||
| 103 | namespace NativeKeyboard { | ||
| 104 | enum Keys { | ||
| 105 | None, | ||
| 106 | Error, | ||
| 107 | |||
| 108 | A = 4, | ||
| 109 | B, | ||
| 110 | C, | ||
| 111 | D, | ||
| 112 | E, | ||
| 113 | F, | ||
| 114 | G, | ||
| 115 | H, | ||
| 116 | I, | ||
| 117 | J, | ||
| 118 | K, | ||
| 119 | L, | ||
| 120 | M, | ||
| 121 | N, | ||
| 122 | O, | ||
| 123 | P, | ||
| 124 | Q, | ||
| 125 | R, | ||
| 126 | S, | ||
| 127 | T, | ||
| 128 | U, | ||
| 129 | V, | ||
| 130 | W, | ||
| 131 | X, | ||
| 132 | Y, | ||
| 133 | Z, | ||
| 134 | N1, | ||
| 135 | N2, | ||
| 136 | N3, | ||
| 137 | N4, | ||
| 138 | N5, | ||
| 139 | N6, | ||
| 140 | N7, | ||
| 141 | N8, | ||
| 142 | N9, | ||
| 143 | N0, | ||
| 144 | Enter, | ||
| 145 | Escape, | ||
| 146 | Backspace, | ||
| 147 | Tab, | ||
| 148 | Space, | ||
| 149 | Minus, | ||
| 150 | Equal, | ||
| 151 | LeftBrace, | ||
| 152 | RightBrace, | ||
| 153 | Backslash, | ||
| 154 | Tilde, | ||
| 155 | Semicolon, | ||
| 156 | Apostrophe, | ||
| 157 | Grave, | ||
| 158 | Comma, | ||
| 159 | Dot, | ||
| 160 | Slash, | ||
| 161 | CapsLockKey, | ||
| 162 | |||
| 163 | F1, | ||
| 164 | F2, | ||
| 165 | F3, | ||
| 166 | F4, | ||
| 167 | F5, | ||
| 168 | F6, | ||
| 169 | F7, | ||
| 170 | F8, | ||
| 171 | F9, | ||
| 172 | F10, | ||
| 173 | F11, | ||
| 174 | F12, | ||
| 175 | |||
| 176 | SystemRequest, | ||
| 177 | ScrollLockKey, | ||
| 178 | Pause, | ||
| 179 | Insert, | ||
| 180 | Home, | ||
| 181 | PageUp, | ||
| 182 | Delete, | ||
| 183 | End, | ||
| 184 | PageDown, | ||
| 185 | Right, | ||
| 186 | Left, | ||
| 187 | Down, | ||
| 188 | Up, | ||
| 189 | |||
| 190 | NumLockKey, | ||
| 191 | KPSlash, | ||
| 192 | KPAsterisk, | ||
| 193 | KPMinus, | ||
| 194 | KPPlus, | ||
| 195 | KPEnter, | ||
| 196 | KP1, | ||
| 197 | KP2, | ||
| 198 | KP3, | ||
| 199 | KP4, | ||
| 200 | KP5, | ||
| 201 | KP6, | ||
| 202 | KP7, | ||
| 203 | KP8, | ||
| 204 | KP9, | ||
| 205 | KP0, | ||
| 206 | KPDot, | ||
| 207 | |||
| 208 | Key102, | ||
| 209 | Compose, | ||
| 210 | Power, | ||
| 211 | KPEqual, | ||
| 212 | |||
| 213 | F13, | ||
| 214 | F14, | ||
| 215 | F15, | ||
| 216 | F16, | ||
| 217 | F17, | ||
| 218 | F18, | ||
| 219 | F19, | ||
| 220 | F20, | ||
| 221 | F21, | ||
| 222 | F22, | ||
| 223 | F23, | ||
| 224 | F24, | ||
| 225 | |||
| 226 | Open, | ||
| 227 | Help, | ||
| 228 | Properties, | ||
| 229 | Front, | ||
| 230 | Stop, | ||
| 231 | Repeat, | ||
| 232 | Undo, | ||
| 233 | Cut, | ||
| 234 | Copy, | ||
| 235 | Paste, | ||
| 236 | Find, | ||
| 237 | Mute, | ||
| 238 | VolumeUp, | ||
| 239 | VolumeDown, | ||
| 240 | CapsLockActive, | ||
| 241 | NumLockActive, | ||
| 242 | ScrollLockActive, | ||
| 243 | KPComma, | ||
| 244 | |||
| 245 | KPLeftParenthesis, | ||
| 246 | KPRightParenthesis, | ||
| 247 | |||
| 248 | LeftControlKey = 0xE0, | ||
| 249 | LeftShiftKey, | ||
| 250 | LeftAltKey, | ||
| 251 | LeftMetaKey, | ||
| 252 | RightControlKey, | ||
| 253 | RightShiftKey, | ||
| 254 | RightAltKey, | ||
| 255 | RightMetaKey, | ||
| 256 | |||
| 257 | MediaPlayPause, | ||
| 258 | MediaStopCD, | ||
| 259 | MediaPrevious, | ||
| 260 | MediaNext, | ||
| 261 | MediaEject, | ||
| 262 | MediaVolumeUp, | ||
| 263 | MediaVolumeDown, | ||
| 264 | MediaMute, | ||
| 265 | MediaWebsite, | ||
| 266 | MediaBack, | ||
| 267 | MediaForward, | ||
| 268 | MediaStop, | ||
| 269 | MediaFind, | ||
| 270 | MediaScrollUp, | ||
| 271 | MediaScrollDown, | ||
| 272 | MediaEdit, | ||
| 273 | MediaSleep, | ||
| 274 | MediaCoffee, | ||
| 275 | MediaRefresh, | ||
| 276 | MediaCalculator, | ||
| 277 | |||
| 278 | NumKeyboardKeys, | ||
| 279 | }; | ||
| 280 | |||
| 281 | static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys."); | ||
| 282 | |||
| 283 | enum Modifiers { | ||
| 284 | LeftControl, | ||
| 285 | LeftShift, | ||
| 286 | LeftAlt, | ||
| 287 | LeftMeta, | ||
| 288 | RightControl, | ||
| 289 | RightShift, | ||
| 290 | RightAlt, | ||
| 291 | RightMeta, | ||
| 292 | CapsLock, | ||
| 293 | ScrollLock, | ||
| 294 | NumLock, | ||
| 295 | |||
| 296 | NumKeyboardMods, | ||
| 297 | }; | ||
| 298 | |||
| 299 | constexpr int KEYBOARD_KEYS_HID_BEGIN = None; | ||
| 300 | constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys; | ||
| 301 | constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys; | ||
| 302 | |||
| 303 | constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl; | ||
| 304 | constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods; | ||
| 305 | constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; | ||
| 306 | |||
| 307 | } // namespace NativeKeyboard | ||
| 308 | |||
| 309 | using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; | ||
| 310 | using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; | ||
| 311 | using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; | ||
| 312 | using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; | ||
| 313 | using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; | ||
| 314 | |||
| 315 | constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; | ||
| 316 | constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; | ||
| 317 | constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; | ||
| 318 | constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; | ||
| 319 | |||
| 320 | enum class ControllerType { | ||
| 321 | ProController, | ||
| 322 | DualJoycon, | ||
| 323 | RightJoycon, | ||
| 324 | LeftJoycon, | ||
| 325 | }; | ||
| 326 | |||
| 327 | struct PlayerInput { | ||
| 328 | bool connected; | ||
| 329 | ControllerType type; | ||
| 330 | ButtonsRaw buttons; | ||
| 331 | AnalogsRaw analogs; | ||
| 332 | |||
| 333 | u32 body_color_right; | ||
| 334 | u32 button_color_right; | ||
| 335 | u32 body_color_left; | ||
| 336 | u32 button_color_left; | ||
| 337 | }; | ||
| 338 | |||
| 339 | struct TouchscreenInput { | ||
| 340 | bool enabled; | ||
| 341 | std::string device; | ||
| 342 | |||
| 343 | u32 finger; | ||
| 344 | u32 diameter_x; | ||
| 345 | u32 diameter_y; | ||
| 346 | u32 rotation_angle; | ||
| 347 | }; | ||
| 348 | |||
| 349 | enum class RendererBackend { | 19 | enum class RendererBackend { |
| 350 | OpenGL = 0, | 20 | OpenGL = 0, |
| 351 | Vulkan = 1, | 21 | Vulkan = 1, |
| @@ -397,6 +67,11 @@ private: | |||
| 397 | Type local{}; | 67 | Type local{}; |
| 398 | }; | 68 | }; |
| 399 | 69 | ||
| 70 | struct TouchFromButtonMap { | ||
| 71 | std::string name; | ||
| 72 | std::vector<std::string> buttons; | ||
| 73 | }; | ||
| 74 | |||
| 400 | struct Values { | 75 | struct Values { |
| 401 | // Audio | 76 | // Audio |
| 402 | std::string audio_device_id; | 77 | std::string audio_device_id; |
| @@ -461,6 +136,8 @@ struct Values { | |||
| 461 | // Controls | 136 | // Controls |
| 462 | std::array<PlayerInput, 10> players; | 137 | std::array<PlayerInput, 10> players; |
| 463 | 138 | ||
| 139 | bool use_docked_mode; | ||
| 140 | |||
| 464 | bool mouse_enabled; | 141 | bool mouse_enabled; |
| 465 | std::string mouse_device; | 142 | std::string mouse_device; |
| 466 | MouseButtonsRaw mouse_buttons; | 143 | MouseButtonsRaw mouse_buttons; |
| @@ -473,14 +150,18 @@ struct Values { | |||
| 473 | ButtonsRaw debug_pad_buttons; | 150 | ButtonsRaw debug_pad_buttons; |
| 474 | AnalogsRaw debug_pad_analogs; | 151 | AnalogsRaw debug_pad_analogs; |
| 475 | 152 | ||
| 153 | bool vibration_enabled; | ||
| 154 | |||
| 476 | std::string motion_device; | 155 | std::string motion_device; |
| 156 | std::string touch_device; | ||
| 477 | TouchscreenInput touchscreen; | 157 | TouchscreenInput touchscreen; |
| 478 | std::atomic_bool is_device_reload_pending{true}; | 158 | std::atomic_bool is_device_reload_pending{true}; |
| 159 | bool use_touch_from_button; | ||
| 160 | int touch_from_button_map_index; | ||
| 479 | std::string udp_input_address; | 161 | std::string udp_input_address; |
| 480 | u16 udp_input_port; | 162 | u16 udp_input_port; |
| 481 | u8 udp_pad_index; | 163 | u8 udp_pad_index; |
| 482 | 164 | std::vector<TouchFromButtonMap> touch_from_button_maps; | |
| 483 | bool use_docked_mode; | ||
| 484 | 165 | ||
| 485 | // Data Storage | 166 | // Data Storage |
| 486 | bool use_virtual_sd; | 167 | bool use_virtual_sd; |
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index 317c25bad..32433df25 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt | |||
| @@ -7,6 +7,10 @@ add_library(input_common STATIC | |||
| 7 | main.h | 7 | main.h |
| 8 | motion_emu.cpp | 8 | motion_emu.cpp |
| 9 | motion_emu.h | 9 | motion_emu.h |
| 10 | settings.cpp | ||
| 11 | settings.h | ||
| 12 | touch_from_button.cpp | ||
| 13 | touch_from_button.h | ||
| 10 | gcadapter/gc_adapter.cpp | 14 | gcadapter/gc_adapter.cpp |
| 11 | gcadapter/gc_adapter.h | 15 | gcadapter/gc_adapter.h |
| 12 | gcadapter/gc_poller.cpp | 16 | gcadapter/gc_poller.cpp |
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp index b346fdf8e..71cd85eeb 100644 --- a/src/input_common/gcadapter/gc_poller.cpp +++ b/src/input_common/gcadapter/gc_poller.cpp | |||
| @@ -191,7 +191,7 @@ public: | |||
| 191 | 191 | ||
| 192 | bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { | 192 | bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { |
| 193 | const auto [x, y] = GetStatus(); | 193 | const auto [x, y] = GetStatus(); |
| 194 | const float directional_deadzone = 0.4f; | 194 | const float directional_deadzone = 0.5f; |
| 195 | switch (direction) { | 195 | switch (direction) { |
| 196 | case Input::AnalogDirection::RIGHT: | 196 | case Input::AnalogDirection::RIGHT: |
| 197 | return x > directional_deadzone; | 197 | return x > directional_deadzone; |
| @@ -232,7 +232,7 @@ std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::Param | |||
| 232 | const int port = params.Get("port", 0); | 232 | const int port = params.Get("port", 0); |
| 233 | const int axis_x = params.Get("axis_x", 0); | 233 | const int axis_x = params.Get("axis_x", 0); |
| 234 | const int axis_y = params.Get("axis_y", 1); | 234 | const int axis_y = params.Get("axis_y", 1); |
| 235 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); | 235 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); |
| 236 | const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); | 236 | const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); |
| 237 | 237 | ||
| 238 | return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range); | 238 | return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range); |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index b9d5d0ec3..ea1a1cee6 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "input_common/keyboard.h" | 11 | #include "input_common/keyboard.h" |
| 12 | #include "input_common/main.h" | 12 | #include "input_common/main.h" |
| 13 | #include "input_common/motion_emu.h" | 13 | #include "input_common/motion_emu.h" |
| 14 | #include "input_common/touch_from_button.h" | ||
| 14 | #include "input_common/udp/udp.h" | 15 | #include "input_common/udp/udp.h" |
| 15 | #ifdef HAVE_SDL2 | 16 | #ifdef HAVE_SDL2 |
| 16 | #include "input_common/sdl/sdl.h" | 17 | #include "input_common/sdl/sdl.h" |
| @@ -18,67 +19,176 @@ | |||
| 18 | 19 | ||
| 19 | namespace InputCommon { | 20 | namespace InputCommon { |
| 20 | 21 | ||
| 21 | static std::shared_ptr<Keyboard> keyboard; | 22 | struct InputSubsystem::Impl { |
| 22 | static std::shared_ptr<MotionEmu> motion_emu; | 23 | void Initialize() { |
| 24 | auto gcadapter = std::make_shared<GCAdapter::Adapter>(); | ||
| 25 | gcbuttons = std::make_shared<GCButtonFactory>(gcadapter); | ||
| 26 | Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); | ||
| 27 | gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); | ||
| 28 | Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); | ||
| 29 | |||
| 30 | keyboard = std::make_shared<Keyboard>(); | ||
| 31 | Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); | ||
| 32 | Input::RegisterFactory<Input::AnalogDevice>("analog_from_button", | ||
| 33 | std::make_shared<AnalogFromButton>()); | ||
| 34 | motion_emu = std::make_shared<MotionEmu>(); | ||
| 35 | Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu); | ||
| 36 | Input::RegisterFactory<Input::TouchDevice>("touch_from_button", | ||
| 37 | std::make_shared<TouchFromButtonFactory>()); | ||
| 38 | |||
| 23 | #ifdef HAVE_SDL2 | 39 | #ifdef HAVE_SDL2 |
| 24 | static std::unique_ptr<SDL::State> sdl; | 40 | sdl = SDL::Init(); |
| 25 | #endif | 41 | #endif |
| 26 | static std::unique_ptr<CemuhookUDP::State> udp; | ||
| 27 | static std::shared_ptr<GCButtonFactory> gcbuttons; | ||
| 28 | static std::shared_ptr<GCAnalogFactory> gcanalog; | ||
| 29 | |||
| 30 | void Init() { | ||
| 31 | auto gcadapter = std::make_shared<GCAdapter::Adapter>(); | ||
| 32 | gcbuttons = std::make_shared<GCButtonFactory>(gcadapter); | ||
| 33 | Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); | ||
| 34 | gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); | ||
| 35 | Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); | ||
| 36 | |||
| 37 | keyboard = std::make_shared<Keyboard>(); | ||
| 38 | Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); | ||
| 39 | Input::RegisterFactory<Input::AnalogDevice>("analog_from_button", | ||
| 40 | std::make_shared<AnalogFromButton>()); | ||
| 41 | motion_emu = std::make_shared<MotionEmu>(); | ||
| 42 | Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu); | ||
| 43 | 42 | ||
| 43 | udp = CemuhookUDP::Init(); | ||
| 44 | } | ||
| 45 | |||
| 46 | void Shutdown() { | ||
| 47 | Input::UnregisterFactory<Input::ButtonDevice>("keyboard"); | ||
| 48 | keyboard.reset(); | ||
| 49 | Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button"); | ||
| 50 | Input::UnregisterFactory<Input::MotionDevice>("motion_emu"); | ||
| 51 | motion_emu.reset(); | ||
| 52 | Input::UnregisterFactory<Input::TouchDevice>("touch_from_button"); | ||
| 44 | #ifdef HAVE_SDL2 | 53 | #ifdef HAVE_SDL2 |
| 45 | sdl = SDL::Init(); | 54 | sdl.reset(); |
| 46 | #endif | 55 | #endif |
| 56 | udp.reset(); | ||
| 57 | Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); | ||
| 58 | Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); | ||
| 59 | |||
| 60 | gcbuttons.reset(); | ||
| 61 | gcanalog.reset(); | ||
| 62 | } | ||
| 63 | |||
| 64 | [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { | ||
| 65 | std::vector<Common::ParamPackage> devices = { | ||
| 66 | Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, | ||
| 67 | Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}}, | ||
| 68 | }; | ||
| 69 | #ifdef HAVE_SDL2 | ||
| 70 | auto sdl_devices = sdl->GetInputDevices(); | ||
| 71 | devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end()); | ||
| 72 | #endif | ||
| 73 | auto udp_devices = udp->GetInputDevices(); | ||
| 74 | devices.insert(devices.end(), udp_devices.begin(), udp_devices.end()); | ||
| 75 | return devices; | ||
| 76 | } | ||
| 77 | |||
| 78 | [[nodiscard]] AnalogMapping GetAnalogMappingForDevice( | ||
| 79 | const Common::ParamPackage& params) const { | ||
| 80 | if (!params.Has("class") || params.Get("class", "") == "any") { | ||
| 81 | return {}; | ||
| 82 | } | ||
| 83 | if (params.Get("class", "") == "key") { | ||
| 84 | // TODO consider returning the SDL key codes for the default keybindings | ||
| 85 | return {}; | ||
| 86 | } | ||
| 87 | #ifdef HAVE_SDL2 | ||
| 88 | if (params.Get("class", "") == "sdl") { | ||
| 89 | return sdl->GetAnalogMappingForDevice(params); | ||
| 90 | } | ||
| 91 | #endif | ||
| 92 | return {}; | ||
| 93 | } | ||
| 94 | |||
| 95 | [[nodiscard]] ButtonMapping GetButtonMappingForDevice( | ||
| 96 | const Common::ParamPackage& params) const { | ||
| 97 | if (!params.Has("class") || params.Get("class", "") == "any") { | ||
| 98 | return {}; | ||
| 99 | } | ||
| 100 | if (params.Get("class", "") == "key") { | ||
| 101 | // TODO consider returning the SDL key codes for the default keybindings | ||
| 102 | return {}; | ||
| 103 | } | ||
| 104 | #ifdef HAVE_SDL2 | ||
| 105 | if (params.Get("class", "") == "sdl") { | ||
| 106 | return sdl->GetButtonMappingForDevice(params); | ||
| 107 | } | ||
| 108 | #endif | ||
| 109 | return {}; | ||
| 110 | } | ||
| 47 | 111 | ||
| 48 | udp = CemuhookUDP::Init(); | 112 | std::shared_ptr<Keyboard> keyboard; |
| 49 | } | 113 | std::shared_ptr<MotionEmu> motion_emu; |
| 50 | |||
| 51 | void Shutdown() { | ||
| 52 | Input::UnregisterFactory<Input::ButtonDevice>("keyboard"); | ||
| 53 | keyboard.reset(); | ||
| 54 | Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button"); | ||
| 55 | Input::UnregisterFactory<Input::MotionDevice>("motion_emu"); | ||
| 56 | motion_emu.reset(); | ||
| 57 | #ifdef HAVE_SDL2 | 114 | #ifdef HAVE_SDL2 |
| 58 | sdl.reset(); | 115 | std::unique_ptr<SDL::State> sdl; |
| 59 | #endif | 116 | #endif |
| 60 | udp.reset(); | 117 | std::unique_ptr<CemuhookUDP::State> udp; |
| 61 | Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); | 118 | std::shared_ptr<GCButtonFactory> gcbuttons; |
| 62 | Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); | 119 | std::shared_ptr<GCAnalogFactory> gcanalog; |
| 120 | }; | ||
| 121 | |||
| 122 | InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {} | ||
| 123 | |||
| 124 | InputSubsystem::~InputSubsystem() = default; | ||
| 125 | |||
| 126 | void InputSubsystem::Initialize() { | ||
| 127 | impl->Initialize(); | ||
| 128 | } | ||
| 129 | |||
| 130 | void InputSubsystem::Shutdown() { | ||
| 131 | impl->Shutdown(); | ||
| 132 | } | ||
| 133 | |||
| 134 | Keyboard* InputSubsystem::GetKeyboard() { | ||
| 135 | return impl->keyboard.get(); | ||
| 136 | } | ||
| 137 | |||
| 138 | const Keyboard* InputSubsystem::GetKeyboard() const { | ||
| 139 | return impl->keyboard.get(); | ||
| 140 | } | ||
| 141 | |||
| 142 | MotionEmu* InputSubsystem::GetMotionEmu() { | ||
| 143 | return impl->motion_emu.get(); | ||
| 144 | } | ||
| 145 | |||
| 146 | const MotionEmu* InputSubsystem::GetMotionEmu() const { | ||
| 147 | return impl->motion_emu.get(); | ||
| 148 | } | ||
| 63 | 149 | ||
| 64 | gcbuttons.reset(); | 150 | std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const { |
| 65 | gcanalog.reset(); | 151 | return impl->GetInputDevices(); |
| 66 | } | 152 | } |
| 67 | 153 | ||
| 68 | Keyboard* GetKeyboard() { | 154 | AnalogMapping InputSubsystem::GetAnalogMappingForDevice(const Common::ParamPackage& device) const { |
| 69 | return keyboard.get(); | 155 | return impl->GetAnalogMappingForDevice(device); |
| 70 | } | 156 | } |
| 71 | 157 | ||
| 72 | MotionEmu* GetMotionEmu() { | 158 | ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPackage& device) const { |
| 73 | return motion_emu.get(); | 159 | return impl->GetButtonMappingForDevice(device); |
| 74 | } | 160 | } |
| 75 | 161 | ||
| 76 | GCButtonFactory* GetGCButtons() { | 162 | GCAnalogFactory* InputSubsystem::GetGCAnalogs() { |
| 77 | return gcbuttons.get(); | 163 | return impl->gcanalog.get(); |
| 78 | } | 164 | } |
| 79 | 165 | ||
| 80 | GCAnalogFactory* GetGCAnalogs() { | 166 | const GCAnalogFactory* InputSubsystem::GetGCAnalogs() const { |
| 81 | return gcanalog.get(); | 167 | return impl->gcanalog.get(); |
| 168 | } | ||
| 169 | |||
| 170 | GCButtonFactory* InputSubsystem::GetGCButtons() { | ||
| 171 | return impl->gcbuttons.get(); | ||
| 172 | } | ||
| 173 | |||
| 174 | const GCButtonFactory* InputSubsystem::GetGCButtons() const { | ||
| 175 | return impl->gcbuttons.get(); | ||
| 176 | } | ||
| 177 | |||
| 178 | void InputSubsystem::ReloadInputDevices() { | ||
| 179 | if (!impl->udp) { | ||
| 180 | return; | ||
| 181 | } | ||
| 182 | impl->udp->ReloadUDPClient(); | ||
| 183 | } | ||
| 184 | |||
| 185 | std::vector<std::unique_ptr<Polling::DevicePoller>> InputSubsystem::GetPollers( | ||
| 186 | Polling::DeviceType type) const { | ||
| 187 | #ifdef HAVE_SDL2 | ||
| 188 | return impl->sdl->GetPollers(type); | ||
| 189 | #else | ||
| 190 | return {}; | ||
| 191 | #endif | ||
| 82 | } | 192 | } |
| 83 | 193 | ||
| 84 | std::string GenerateKeyboardParam(int key_code) { | 194 | std::string GenerateKeyboardParam(int key_code) { |
| @@ -102,18 +212,4 @@ std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, | |||
| 102 | }; | 212 | }; |
| 103 | return circle_pad_param.Serialize(); | 213 | return circle_pad_param.Serialize(); |
| 104 | } | 214 | } |
| 105 | |||
| 106 | namespace Polling { | ||
| 107 | |||
| 108 | std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type) { | ||
| 109 | std::vector<std::unique_ptr<DevicePoller>> pollers; | ||
| 110 | |||
| 111 | #ifdef HAVE_SDL2 | ||
| 112 | pollers = sdl->GetPollers(type); | ||
| 113 | #endif | ||
| 114 | |||
| 115 | return pollers; | ||
| 116 | } | ||
| 117 | |||
| 118 | } // namespace Polling | ||
| 119 | } // namespace InputCommon | 215 | } // namespace InputCommon |
diff --git a/src/input_common/main.h b/src/input_common/main.h index 0e32856f6..f3fbf696e 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h | |||
| @@ -6,45 +6,25 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <unordered_map> | ||
| 9 | #include <vector> | 10 | #include <vector> |
| 10 | #include "input_common/gcadapter/gc_poller.h" | ||
| 11 | 11 | ||
| 12 | namespace Common { | 12 | namespace Common { |
| 13 | class ParamPackage; | 13 | class ParamPackage; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | namespace InputCommon { | 16 | namespace Settings::NativeAnalog { |
| 17 | 17 | enum Values : int; | |
| 18 | /// Initializes and registers all built-in input device factories. | 18 | } |
| 19 | void Init(); | ||
| 20 | |||
| 21 | /// Deregisters all built-in input device factories and shuts them down. | ||
| 22 | void Shutdown(); | ||
| 23 | |||
| 24 | class Keyboard; | ||
| 25 | |||
| 26 | /// Gets the keyboard button device factory. | ||
| 27 | Keyboard* GetKeyboard(); | ||
| 28 | |||
| 29 | class MotionEmu; | ||
| 30 | |||
| 31 | /// Gets the motion emulation factory. | ||
| 32 | MotionEmu* GetMotionEmu(); | ||
| 33 | |||
| 34 | GCButtonFactory* GetGCButtons(); | ||
| 35 | |||
| 36 | GCAnalogFactory* GetGCAnalogs(); | ||
| 37 | |||
| 38 | /// Generates a serialized param package for creating a keyboard button device | ||
| 39 | std::string GenerateKeyboardParam(int key_code); | ||
| 40 | 19 | ||
| 41 | /// Generates a serialized param package for creating an analog device taking input from keyboard | 20 | namespace Settings::NativeButton { |
| 42 | std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, | 21 | enum Values : int; |
| 43 | int key_modifier, float modifier_scale); | 22 | } |
| 44 | 23 | ||
| 24 | namespace InputCommon { | ||
| 45 | namespace Polling { | 25 | namespace Polling { |
| 46 | 26 | ||
| 47 | enum class DeviceType { Button, Analog }; | 27 | enum class DeviceType { Button, AnalogPreferred }; |
| 48 | 28 | ||
| 49 | /** | 29 | /** |
| 50 | * A class that can be used to get inputs from an input device like controllers without having to | 30 | * A class that can be used to get inputs from an input device like controllers without having to |
| @@ -54,7 +34,9 @@ class DevicePoller { | |||
| 54 | public: | 34 | public: |
| 55 | virtual ~DevicePoller() = default; | 35 | virtual ~DevicePoller() = default; |
| 56 | /// Setup and start polling for inputs, should be called before GetNextInput | 36 | /// Setup and start polling for inputs, should be called before GetNextInput |
| 57 | virtual void Start() = 0; | 37 | /// If a device_id is provided, events should be filtered to only include events from this |
| 38 | /// device id | ||
| 39 | virtual void Start(const std::string& device_id = "") = 0; | ||
| 58 | /// Stop polling | 40 | /// Stop polling |
| 59 | virtual void Stop() = 0; | 41 | virtual void Stop() = 0; |
| 60 | /** | 42 | /** |
| @@ -64,8 +46,92 @@ public: | |||
| 64 | */ | 46 | */ |
| 65 | virtual Common::ParamPackage GetNextInput() = 0; | 47 | virtual Common::ParamPackage GetNextInput() = 0; |
| 66 | }; | 48 | }; |
| 67 | |||
| 68 | // Get all DevicePoller from all backends for a specific device type | ||
| 69 | std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type); | ||
| 70 | } // namespace Polling | 49 | } // namespace Polling |
| 50 | |||
| 51 | class GCAnalogFactory; | ||
| 52 | class GCButtonFactory; | ||
| 53 | class Keyboard; | ||
| 54 | class MotionEmu; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default | ||
| 58 | * mapping for the device. This is currently only implemented for the SDL backend devices. | ||
| 59 | */ | ||
| 60 | using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>; | ||
| 61 | using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>; | ||
| 62 | |||
| 63 | class InputSubsystem { | ||
| 64 | public: | ||
| 65 | explicit InputSubsystem(); | ||
| 66 | ~InputSubsystem(); | ||
| 67 | |||
| 68 | InputSubsystem(const InputSubsystem&) = delete; | ||
| 69 | InputSubsystem& operator=(const InputSubsystem&) = delete; | ||
| 70 | |||
| 71 | InputSubsystem(InputSubsystem&&) = delete; | ||
| 72 | InputSubsystem& operator=(InputSubsystem&&) = delete; | ||
| 73 | |||
| 74 | /// Initializes and registers all built-in input device factories. | ||
| 75 | void Initialize(); | ||
| 76 | |||
| 77 | /// Unregisters all built-in input device factories and shuts them down. | ||
| 78 | void Shutdown(); | ||
| 79 | |||
| 80 | /// Retrieves the underlying keyboard device. | ||
| 81 | [[nodiscard]] Keyboard* GetKeyboard(); | ||
| 82 | |||
| 83 | /// Retrieves the underlying keyboard device. | ||
| 84 | [[nodiscard]] const Keyboard* GetKeyboard() const; | ||
| 85 | |||
| 86 | /// Retrieves the underlying motion emulation factory. | ||
| 87 | [[nodiscard]] MotionEmu* GetMotionEmu(); | ||
| 88 | |||
| 89 | /// Retrieves the underlying motion emulation factory. | ||
| 90 | [[nodiscard]] const MotionEmu* GetMotionEmu() const; | ||
| 91 | |||
| 92 | /** | ||
| 93 | * Returns all available input devices that this Factory can create a new device with. | ||
| 94 | * Each returned ParamPackage should have a `display` field used for display, a class field for | ||
| 95 | * backends to determine if this backend is meant to service the request and any other | ||
| 96 | * information needed to identify this in the backend later. | ||
| 97 | */ | ||
| 98 | [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const; | ||
| 99 | |||
| 100 | /// Retrieves the analog mappings for the given device. | ||
| 101 | [[nodiscard]] AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& device) const; | ||
| 102 | |||
| 103 | /// Retrieves the button mappings for the given device. | ||
| 104 | [[nodiscard]] ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& device) const; | ||
| 105 | |||
| 106 | /// Retrieves the underlying GameCube analog handler. | ||
| 107 | [[nodiscard]] GCAnalogFactory* GetGCAnalogs(); | ||
| 108 | |||
| 109 | /// Retrieves the underlying GameCube analog handler. | ||
| 110 | [[nodiscard]] const GCAnalogFactory* GetGCAnalogs() const; | ||
| 111 | |||
| 112 | /// Retrieves the underlying GameCube button handler. | ||
| 113 | [[nodiscard]] GCButtonFactory* GetGCButtons(); | ||
| 114 | |||
| 115 | /// Retrieves the underlying GameCube button handler. | ||
| 116 | [[nodiscard]] const GCButtonFactory* GetGCButtons() const; | ||
| 117 | |||
| 118 | /// Reloads the input devices | ||
| 119 | void ReloadInputDevices(); | ||
| 120 | |||
| 121 | /// Get all DevicePoller from all backends for a specific device type | ||
| 122 | [[nodiscard]] std::vector<std::unique_ptr<Polling::DevicePoller>> GetPollers( | ||
| 123 | Polling::DeviceType type) const; | ||
| 124 | |||
| 125 | private: | ||
| 126 | struct Impl; | ||
| 127 | std::unique_ptr<Impl> impl; | ||
| 128 | }; | ||
| 129 | |||
| 130 | /// Generates a serialized param package for creating a keyboard button device | ||
| 131 | std::string GenerateKeyboardParam(int key_code); | ||
| 132 | |||
| 133 | /// Generates a serialized param package for creating an analog device taking input from keyboard | ||
| 134 | std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, | ||
| 135 | int key_modifier, float modifier_scale); | ||
| 136 | |||
| 71 | } // namespace InputCommon | 137 | } // namespace InputCommon |
diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h index 5306daa70..f3554be9a 100644 --- a/src/input_common/sdl/sdl.h +++ b/src/input_common/sdl/sdl.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | #include "common/param_package.h" | ||
| 9 | #include "input_common/main.h" | 10 | #include "input_common/main.h" |
| 10 | 11 | ||
| 11 | namespace InputCommon::Polling { | 12 | namespace InputCommon::Polling { |
| @@ -22,14 +23,24 @@ public: | |||
| 22 | /// Unregisters SDL device factories and shut them down. | 23 | /// Unregisters SDL device factories and shut them down. |
| 23 | virtual ~State() = default; | 24 | virtual ~State() = default; |
| 24 | 25 | ||
| 25 | virtual Pollers GetPollers(Polling::DeviceType type) = 0; | 26 | virtual Pollers GetPollers(Polling::DeviceType type) { |
| 27 | return {}; | ||
| 28 | } | ||
| 29 | |||
| 30 | virtual std::vector<Common::ParamPackage> GetInputDevices() { | ||
| 31 | return {}; | ||
| 32 | } | ||
| 33 | |||
| 34 | virtual ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage&) { | ||
| 35 | return {}; | ||
| 36 | } | ||
| 37 | virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) { | ||
| 38 | return {}; | ||
| 39 | } | ||
| 26 | }; | 40 | }; |
| 27 | 41 | ||
| 28 | class NullState : public State { | 42 | class NullState : public State { |
| 29 | public: | 43 | public: |
| 30 | Pollers GetPollers(Polling::DeviceType type) override { | ||
| 31 | return {}; | ||
| 32 | } | ||
| 33 | }; | 44 | }; |
| 34 | 45 | ||
| 35 | std::unique_ptr<State> Init(); | 46 | std::unique_ptr<State> Init(); |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index d76c279d3..a9e676f4b 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -3,10 +3,13 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <array> | ||
| 6 | #include <atomic> | 7 | #include <atomic> |
| 7 | #include <cmath> | 8 | #include <cmath> |
| 8 | #include <functional> | 9 | #include <functional> |
| 9 | #include <mutex> | 10 | #include <mutex> |
| 11 | #include <optional> | ||
| 12 | #include <sstream> | ||
| 10 | #include <string> | 13 | #include <string> |
| 11 | #include <thread> | 14 | #include <thread> |
| 12 | #include <tuple> | 15 | #include <tuple> |
| @@ -15,15 +18,16 @@ | |||
| 15 | #include <vector> | 18 | #include <vector> |
| 16 | #include <SDL.h> | 19 | #include <SDL.h> |
| 17 | #include "common/logging/log.h" | 20 | #include "common/logging/log.h" |
| 18 | #include "common/math_util.h" | ||
| 19 | #include "common/param_package.h" | 21 | #include "common/param_package.h" |
| 20 | #include "common/threadsafe_queue.h" | 22 | #include "common/threadsafe_queue.h" |
| 21 | #include "core/frontend/input.h" | 23 | #include "core/frontend/input.h" |
| 22 | #include "input_common/sdl/sdl_impl.h" | 24 | #include "input_common/sdl/sdl_impl.h" |
| 25 | #include "input_common/settings.h" | ||
| 23 | 26 | ||
| 24 | namespace InputCommon::SDL { | 27 | namespace InputCommon::SDL { |
| 25 | 28 | ||
| 26 | static std::string GetGUID(SDL_Joystick* joystick) { | 29 | namespace { |
| 30 | std::string GetGUID(SDL_Joystick* joystick) { | ||
| 27 | const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); | 31 | const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); |
| 28 | char guid_str[33]; | 32 | char guid_str[33]; |
| 29 | SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); | 33 | SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); |
| @@ -31,7 +35,8 @@ static std::string GetGUID(SDL_Joystick* joystick) { | |||
| 31 | } | 35 | } |
| 32 | 36 | ||
| 33 | /// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice | 37 | /// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice |
| 34 | static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event); | 38 | Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event); |
| 39 | } // Anonymous namespace | ||
| 35 | 40 | ||
| 36 | static int SDLEventWatcher(void* user_data, SDL_Event* event) { | 41 | static int SDLEventWatcher(void* user_data, SDL_Event* event) { |
| 37 | auto* const sdl_state = static_cast<SDLState*>(user_data); | 42 | auto* const sdl_state = static_cast<SDLState*>(user_data); |
| @@ -48,8 +53,10 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) { | |||
| 48 | 53 | ||
| 49 | class SDLJoystick { | 54 | class SDLJoystick { |
| 50 | public: | 55 | public: |
| 51 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick) | 56 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, |
| 52 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose} {} | 57 | SDL_GameController* gamecontroller) |
| 58 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, | ||
| 59 | sdl_controller{gamecontroller, &SDL_GameControllerClose} {} | ||
| 53 | 60 | ||
| 54 | void SetButton(int button, bool value) { | 61 | void SetButton(int button, bool value) { |
| 55 | std::lock_guard lock{mutex}; | 62 | std::lock_guard lock{mutex}; |
| @@ -115,10 +122,15 @@ public: | |||
| 115 | return sdl_joystick.get(); | 122 | return sdl_joystick.get(); |
| 116 | } | 123 | } |
| 117 | 124 | ||
| 118 | void SetSDLJoystick(SDL_Joystick* joystick) { | 125 | void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) { |
| 126 | sdl_controller.reset(controller); | ||
| 119 | sdl_joystick.reset(joystick); | 127 | sdl_joystick.reset(joystick); |
| 120 | } | 128 | } |
| 121 | 129 | ||
| 130 | SDL_GameController* GetSDLGameController() const { | ||
| 131 | return sdl_controller.get(); | ||
| 132 | } | ||
| 133 | |||
| 122 | private: | 134 | private: |
| 123 | struct State { | 135 | struct State { |
| 124 | std::unordered_map<int, bool> buttons; | 136 | std::unordered_map<int, bool> buttons; |
| @@ -128,6 +140,7 @@ private: | |||
| 128 | std::string guid; | 140 | std::string guid; |
| 129 | int port; | 141 | int port; |
| 130 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; | 142 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; |
| 143 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | ||
| 131 | mutable std::mutex mutex; | 144 | mutable std::mutex mutex; |
| 132 | }; | 145 | }; |
| 133 | 146 | ||
| @@ -136,18 +149,19 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& g | |||
| 136 | const auto it = joystick_map.find(guid); | 149 | const auto it = joystick_map.find(guid); |
| 137 | if (it != joystick_map.end()) { | 150 | if (it != joystick_map.end()) { |
| 138 | while (it->second.size() <= static_cast<std::size_t>(port)) { | 151 | while (it->second.size() <= static_cast<std::size_t>(port)) { |
| 139 | auto joystick = | 152 | auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), |
| 140 | std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), nullptr); | 153 | nullptr, nullptr); |
| 141 | it->second.emplace_back(std::move(joystick)); | 154 | it->second.emplace_back(std::move(joystick)); |
| 142 | } | 155 | } |
| 143 | return it->second[port]; | 156 | return it->second[port]; |
| 144 | } | 157 | } |
| 145 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr); | 158 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr); |
| 146 | return joystick_map[guid].emplace_back(std::move(joystick)); | 159 | return joystick_map[guid].emplace_back(std::move(joystick)); |
| 147 | } | 160 | } |
| 148 | 161 | ||
| 149 | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { | 162 | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { |
| 150 | auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); | 163 | auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); |
| 164 | auto sdl_controller = SDL_GameControllerFromInstanceID(sdl_id); | ||
| 151 | const std::string guid = GetGUID(sdl_joystick); | 165 | const std::string guid = GetGUID(sdl_joystick); |
| 152 | 166 | ||
| 153 | std::lock_guard lock{joystick_map_mutex}; | 167 | std::lock_guard lock{joystick_map_mutex}; |
| @@ -171,23 +185,27 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_ | |||
| 171 | }); | 185 | }); |
| 172 | if (nullptr_it != map_it->second.end()) { | 186 | if (nullptr_it != map_it->second.end()) { |
| 173 | // ... and map it | 187 | // ... and map it |
| 174 | (*nullptr_it)->SetSDLJoystick(sdl_joystick); | 188 | (*nullptr_it)->SetSDLJoystick(sdl_joystick, sdl_controller); |
| 175 | return *nullptr_it; | 189 | return *nullptr_it; |
| 176 | } | 190 | } |
| 177 | 191 | ||
| 178 | // There is no SDLJoystick without a mapped SDL_Joystick | 192 | // There is no SDLJoystick without a mapped SDL_Joystick |
| 179 | // Create a new SDLJoystick | 193 | // Create a new SDLJoystick |
| 180 | const int port = static_cast<int>(map_it->second.size()); | 194 | const int port = static_cast<int>(map_it->second.size()); |
| 181 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick); | 195 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_controller); |
| 182 | return map_it->second.emplace_back(std::move(joystick)); | 196 | return map_it->second.emplace_back(std::move(joystick)); |
| 183 | } | 197 | } |
| 184 | 198 | ||
| 185 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick); | 199 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_controller); |
| 186 | return joystick_map[guid].emplace_back(std::move(joystick)); | 200 | return joystick_map[guid].emplace_back(std::move(joystick)); |
| 187 | } | 201 | } |
| 188 | 202 | ||
| 189 | void SDLState::InitJoystick(int joystick_index) { | 203 | void SDLState::InitJoystick(int joystick_index) { |
| 190 | SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index); | 204 | SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index); |
| 205 | SDL_GameController* sdl_gamecontroller = nullptr; | ||
| 206 | if (SDL_IsGameController(joystick_index)) { | ||
| 207 | sdl_gamecontroller = SDL_GameControllerOpen(joystick_index); | ||
| 208 | } | ||
| 191 | if (!sdl_joystick) { | 209 | if (!sdl_joystick) { |
| 192 | LOG_ERROR(Input, "failed to open joystick {}", joystick_index); | 210 | LOG_ERROR(Input, "failed to open joystick {}", joystick_index); |
| 193 | return; | 211 | return; |
| @@ -196,7 +214,7 @@ void SDLState::InitJoystick(int joystick_index) { | |||
| 196 | 214 | ||
| 197 | std::lock_guard lock{joystick_map_mutex}; | 215 | std::lock_guard lock{joystick_map_mutex}; |
| 198 | if (joystick_map.find(guid) == joystick_map.end()) { | 216 | if (joystick_map.find(guid) == joystick_map.end()) { |
| 199 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick); | 217 | auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller); |
| 200 | joystick_map[guid].emplace_back(std::move(joystick)); | 218 | joystick_map[guid].emplace_back(std::move(joystick)); |
| 201 | return; | 219 | return; |
| 202 | } | 220 | } |
| @@ -205,11 +223,11 @@ void SDLState::InitJoystick(int joystick_index) { | |||
| 205 | joystick_guid_list.begin(), joystick_guid_list.end(), | 223 | joystick_guid_list.begin(), joystick_guid_list.end(), |
| 206 | [](const std::shared_ptr<SDLJoystick>& joystick) { return !joystick->GetSDLJoystick(); }); | 224 | [](const std::shared_ptr<SDLJoystick>& joystick) { return !joystick->GetSDLJoystick(); }); |
| 207 | if (it != joystick_guid_list.end()) { | 225 | if (it != joystick_guid_list.end()) { |
| 208 | (*it)->SetSDLJoystick(sdl_joystick); | 226 | (*it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller); |
| 209 | return; | 227 | return; |
| 210 | } | 228 | } |
| 211 | const int port = static_cast<int>(joystick_guid_list.size()); | 229 | const int port = static_cast<int>(joystick_guid_list.size()); |
| 212 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick); | 230 | auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller); |
| 213 | joystick_guid_list.emplace_back(std::move(joystick)); | 231 | joystick_guid_list.emplace_back(std::move(joystick)); |
| 214 | } | 232 | } |
| 215 | 233 | ||
| @@ -231,7 +249,7 @@ void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) { | |||
| 231 | 249 | ||
| 232 | // Destruct SDL_Joystick outside the lock guard because SDL can internally call the | 250 | // Destruct SDL_Joystick outside the lock guard because SDL can internally call the |
| 233 | // event callback which locks the mutex again. | 251 | // event callback which locks the mutex again. |
| 234 | joystick->SetSDLJoystick(nullptr); | 252 | joystick->SetSDLJoystick(nullptr, nullptr); |
| 235 | } | 253 | } |
| 236 | 254 | ||
| 237 | void SDLState::HandleGameControllerEvent(const SDL_Event& event) { | 255 | void SDLState::HandleGameControllerEvent(const SDL_Event& event) { |
| @@ -341,12 +359,12 @@ public: | |||
| 341 | return std::make_tuple(x / r * (r - deadzone) / (1 - deadzone), | 359 | return std::make_tuple(x / r * (r - deadzone) / (1 - deadzone), |
| 342 | y / r * (r - deadzone) / (1 - deadzone)); | 360 | y / r * (r - deadzone) / (1 - deadzone)); |
| 343 | } | 361 | } |
| 344 | return std::make_tuple<float, float>(0.0f, 0.0f); | 362 | return {}; |
| 345 | } | 363 | } |
| 346 | 364 | ||
| 347 | bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { | 365 | bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { |
| 348 | const auto [x, y] = GetStatus(); | 366 | const auto [x, y] = GetStatus(); |
| 349 | const float directional_deadzone = 0.4f; | 367 | const float directional_deadzone = 0.5f; |
| 350 | switch (direction) { | 368 | switch (direction) { |
| 351 | case Input::AnalogDirection::RIGHT: | 369 | case Input::AnalogDirection::RIGHT: |
| 352 | return x > directional_deadzone; | 370 | return x > directional_deadzone; |
| @@ -460,7 +478,7 @@ public: | |||
| 460 | const int port = params.Get("port", 0); | 478 | const int port = params.Get("port", 0); |
| 461 | const int axis_x = params.Get("axis_x", 0); | 479 | const int axis_x = params.Get("axis_x", 0); |
| 462 | const int axis_y = params.Get("axis_y", 1); | 480 | const int axis_y = params.Get("axis_y", 1); |
| 463 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); | 481 | const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); |
| 464 | const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); | 482 | const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); |
| 465 | auto joystick = state.GetSDLJoystickByGUID(guid, port); | 483 | auto joystick = state.GetSDLJoystickByGUID(guid, port); |
| 466 | 484 | ||
| @@ -476,8 +494,10 @@ private: | |||
| 476 | 494 | ||
| 477 | SDLState::SDLState() { | 495 | SDLState::SDLState() { |
| 478 | using namespace Input; | 496 | using namespace Input; |
| 479 | RegisterFactory<ButtonDevice>("sdl", std::make_shared<SDLButtonFactory>(*this)); | 497 | analog_factory = std::make_shared<SDLAnalogFactory>(*this); |
| 480 | RegisterFactory<AnalogDevice>("sdl", std::make_shared<SDLAnalogFactory>(*this)); | 498 | button_factory = std::make_shared<SDLButtonFactory>(*this); |
| 499 | RegisterFactory<AnalogDevice>("sdl", analog_factory); | ||
| 500 | RegisterFactory<ButtonDevice>("sdl", button_factory); | ||
| 481 | 501 | ||
| 482 | // If the frontend is going to manage the event loop, then we dont start one here | 502 | // If the frontend is going to manage the event loop, then we dont start one here |
| 483 | start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK); | 503 | start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK); |
| @@ -485,6 +505,7 @@ SDLState::SDLState() { | |||
| 485 | LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError()); | 505 | LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError()); |
| 486 | return; | 506 | return; |
| 487 | } | 507 | } |
| 508 | has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); | ||
| 488 | if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { | 509 | if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { |
| 489 | LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); | 510 | LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); |
| 490 | } | 511 | } |
| @@ -497,7 +518,7 @@ SDLState::SDLState() { | |||
| 497 | using namespace std::chrono_literals; | 518 | using namespace std::chrono_literals; |
| 498 | while (initialized) { | 519 | while (initialized) { |
| 499 | SDL_PumpEvents(); | 520 | SDL_PumpEvents(); |
| 500 | std::this_thread::sleep_for(10ms); | 521 | std::this_thread::sleep_for(5ms); |
| 501 | } | 522 | } |
| 502 | }); | 523 | }); |
| 503 | } | 524 | } |
| @@ -523,65 +544,230 @@ SDLState::~SDLState() { | |||
| 523 | } | 544 | } |
| 524 | } | 545 | } |
| 525 | 546 | ||
| 526 | static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { | 547 | std::vector<Common::ParamPackage> SDLState::GetInputDevices() { |
| 548 | std::scoped_lock lock(joystick_map_mutex); | ||
| 549 | std::vector<Common::ParamPackage> devices; | ||
| 550 | for (const auto& [key, value] : joystick_map) { | ||
| 551 | for (const auto& joystick : value) { | ||
| 552 | auto joy = joystick->GetSDLJoystick(); | ||
| 553 | if (auto controller = joystick->GetSDLGameController()) { | ||
| 554 | std::string name = | ||
| 555 | fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort()); | ||
| 556 | devices.emplace_back(Common::ParamPackage{ | ||
| 557 | {"class", "sdl"}, | ||
| 558 | {"display", std::move(name)}, | ||
| 559 | {"guid", joystick->GetGUID()}, | ||
| 560 | {"port", std::to_string(joystick->GetPort())}, | ||
| 561 | }); | ||
| 562 | } else if (joy) { | ||
| 563 | std::string name = fmt::format("{} {}", SDL_JoystickName(joy), joystick->GetPort()); | ||
| 564 | devices.emplace_back(Common::ParamPackage{ | ||
| 565 | {"class", "sdl"}, | ||
| 566 | {"display", std::move(name)}, | ||
| 567 | {"guid", joystick->GetGUID()}, | ||
| 568 | {"port", std::to_string(joystick->GetPort())}, | ||
| 569 | }); | ||
| 570 | } | ||
| 571 | } | ||
| 572 | } | ||
| 573 | return devices; | ||
| 574 | } | ||
| 575 | |||
| 576 | namespace { | ||
| 577 | Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, u8 axis, | ||
| 578 | float value = 0.1f) { | ||
| 527 | Common::ParamPackage params({{"engine", "sdl"}}); | 579 | Common::ParamPackage params({{"engine", "sdl"}}); |
| 580 | params.Set("port", port); | ||
| 581 | params.Set("guid", std::move(guid)); | ||
| 582 | params.Set("axis", axis); | ||
| 583 | if (value > 0) { | ||
| 584 | params.Set("direction", "+"); | ||
| 585 | params.Set("threshold", "0.5"); | ||
| 586 | } else { | ||
| 587 | params.Set("direction", "-"); | ||
| 588 | params.Set("threshold", "-0.5"); | ||
| 589 | } | ||
| 590 | return params; | ||
| 591 | } | ||
| 528 | 592 | ||
| 593 | Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, u8 button) { | ||
| 594 | Common::ParamPackage params({{"engine", "sdl"}}); | ||
| 595 | params.Set("port", port); | ||
| 596 | params.Set("guid", std::move(guid)); | ||
| 597 | params.Set("button", button); | ||
| 598 | return params; | ||
| 599 | } | ||
| 600 | |||
| 601 | Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, u8 hat, u8 value) { | ||
| 602 | Common::ParamPackage params({{"engine", "sdl"}}); | ||
| 603 | |||
| 604 | params.Set("port", port); | ||
| 605 | params.Set("guid", std::move(guid)); | ||
| 606 | params.Set("hat", hat); | ||
| 607 | switch (value) { | ||
| 608 | case SDL_HAT_UP: | ||
| 609 | params.Set("direction", "up"); | ||
| 610 | break; | ||
| 611 | case SDL_HAT_DOWN: | ||
| 612 | params.Set("direction", "down"); | ||
| 613 | break; | ||
| 614 | case SDL_HAT_LEFT: | ||
| 615 | params.Set("direction", "left"); | ||
| 616 | break; | ||
| 617 | case SDL_HAT_RIGHT: | ||
| 618 | params.Set("direction", "right"); | ||
| 619 | break; | ||
| 620 | default: | ||
| 621 | return {}; | ||
| 622 | } | ||
| 623 | return params; | ||
| 624 | } | ||
| 625 | |||
| 626 | Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { | ||
| 529 | switch (event.type) { | 627 | switch (event.type) { |
| 530 | case SDL_JOYAXISMOTION: { | 628 | case SDL_JOYAXISMOTION: { |
| 531 | const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | 629 | const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); |
| 532 | params.Set("port", joystick->GetPort()); | 630 | return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |
| 533 | params.Set("guid", joystick->GetGUID()); | 631 | event.jaxis.axis, event.jaxis.value); |
| 534 | params.Set("axis", event.jaxis.axis); | ||
| 535 | if (event.jaxis.value > 0) { | ||
| 536 | params.Set("direction", "+"); | ||
| 537 | params.Set("threshold", "0.5"); | ||
| 538 | } else { | ||
| 539 | params.Set("direction", "-"); | ||
| 540 | params.Set("threshold", "-0.5"); | ||
| 541 | } | ||
| 542 | break; | ||
| 543 | } | 632 | } |
| 544 | case SDL_JOYBUTTONUP: { | 633 | case SDL_JOYBUTTONUP: { |
| 545 | const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); | 634 | const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); |
| 546 | params.Set("port", joystick->GetPort()); | 635 | return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |
| 547 | params.Set("guid", joystick->GetGUID()); | 636 | event.jbutton.button); |
| 548 | params.Set("button", event.jbutton.button); | ||
| 549 | break; | ||
| 550 | } | 637 | } |
| 551 | case SDL_JOYHATMOTION: { | 638 | case SDL_JOYHATMOTION: { |
| 552 | const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); | 639 | const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); |
| 553 | params.Set("port", joystick->GetPort()); | 640 | return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |
| 554 | params.Set("guid", joystick->GetGUID()); | 641 | event.jhat.hat, event.jhat.value); |
| 555 | params.Set("hat", event.jhat.hat); | ||
| 556 | switch (event.jhat.value) { | ||
| 557 | case SDL_HAT_UP: | ||
| 558 | params.Set("direction", "up"); | ||
| 559 | break; | ||
| 560 | case SDL_HAT_DOWN: | ||
| 561 | params.Set("direction", "down"); | ||
| 562 | break; | ||
| 563 | case SDL_HAT_LEFT: | ||
| 564 | params.Set("direction", "left"); | ||
| 565 | break; | ||
| 566 | case SDL_HAT_RIGHT: | ||
| 567 | params.Set("direction", "right"); | ||
| 568 | break; | ||
| 569 | default: | ||
| 570 | return {}; | ||
| 571 | } | ||
| 572 | break; | ||
| 573 | } | 642 | } |
| 574 | } | 643 | } |
| 644 | return {}; | ||
| 645 | } | ||
| 646 | |||
| 647 | Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid, | ||
| 648 | const SDL_GameControllerButtonBind& binding) { | ||
| 649 | switch (binding.bindType) { | ||
| 650 | case SDL_CONTROLLER_BINDTYPE_AXIS: | ||
| 651 | return BuildAnalogParamPackageForButton(port, guid, binding.value.axis); | ||
| 652 | case SDL_CONTROLLER_BINDTYPE_BUTTON: | ||
| 653 | return BuildButtonParamPackageForButton(port, guid, binding.value.button); | ||
| 654 | case SDL_CONTROLLER_BINDTYPE_HAT: | ||
| 655 | return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat, | ||
| 656 | binding.value.hat.hat_mask); | ||
| 657 | } | ||
| 658 | return {}; | ||
| 659 | } | ||
| 660 | |||
| 661 | Common::ParamPackage BuildParamPackageForAnalog(int port, const std::string& guid, int axis_x, | ||
| 662 | int axis_y) { | ||
| 663 | Common::ParamPackage params; | ||
| 664 | params.Set("engine", "sdl"); | ||
| 665 | params.Set("port", port); | ||
| 666 | params.Set("guid", guid); | ||
| 667 | params.Set("axis_x", axis_x); | ||
| 668 | params.Set("axis_y", axis_y); | ||
| 575 | return params; | 669 | return params; |
| 576 | } | 670 | } |
| 671 | } // Anonymous namespace | ||
| 577 | 672 | ||
| 578 | namespace Polling { | 673 | ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& params) { |
| 674 | if (!params.Has("guid") || !params.Has("port")) { | ||
| 675 | return {}; | ||
| 676 | } | ||
| 677 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | ||
| 678 | auto* controller = joystick->GetSDLGameController(); | ||
| 679 | if (controller == nullptr) { | ||
| 680 | return {}; | ||
| 681 | } | ||
| 682 | |||
| 683 | // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. | ||
| 684 | // We will add those afterwards | ||
| 685 | // This list also excludes Screenshot since theres not really a mapping for that | ||
| 686 | using ButtonBindings = | ||
| 687 | std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>; | ||
| 688 | static constexpr ButtonBindings switch_to_sdl_button{{ | ||
| 689 | {Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B}, | ||
| 690 | {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A}, | ||
| 691 | {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y}, | ||
| 692 | {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X}, | ||
| 693 | {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, | ||
| 694 | {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, | ||
| 695 | {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, | ||
| 696 | {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, | ||
| 697 | {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START}, | ||
| 698 | {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK}, | ||
| 699 | {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT}, | ||
| 700 | {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP}, | ||
| 701 | {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT}, | ||
| 702 | {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN}, | ||
| 703 | {Settings::NativeButton::SL, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, | ||
| 704 | {Settings::NativeButton::SR, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, | ||
| 705 | {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE}, | ||
| 706 | }}; | ||
| 707 | |||
| 708 | // Add the missing bindings for ZL/ZR | ||
| 709 | using ZBindings = | ||
| 710 | std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerAxis>, 2>; | ||
| 711 | static constexpr ZBindings switch_to_sdl_axis{{ | ||
| 712 | {Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT}, | ||
| 713 | {Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT}, | ||
| 714 | }}; | ||
| 715 | |||
| 716 | ButtonMapping mapping; | ||
| 717 | mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size()); | ||
| 718 | |||
| 719 | for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) { | ||
| 720 | const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button); | ||
| 721 | mapping.insert_or_assign( | ||
| 722 | switch_button, | ||
| 723 | BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); | ||
| 724 | } | ||
| 725 | for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) { | ||
| 726 | const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis); | ||
| 727 | mapping.insert_or_assign( | ||
| 728 | switch_button, | ||
| 729 | BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); | ||
| 730 | } | ||
| 731 | |||
| 732 | return mapping; | ||
| 733 | } | ||
| 579 | 734 | ||
| 735 | AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& params) { | ||
| 736 | if (!params.Has("guid") || !params.Has("port")) { | ||
| 737 | return {}; | ||
| 738 | } | ||
| 739 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | ||
| 740 | auto* controller = joystick->GetSDLGameController(); | ||
| 741 | if (controller == nullptr) { | ||
| 742 | return {}; | ||
| 743 | } | ||
| 744 | |||
| 745 | AnalogMapping mapping = {}; | ||
| 746 | const auto& binding_left_x = | ||
| 747 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); | ||
| 748 | const auto& binding_left_y = | ||
| 749 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); | ||
| 750 | mapping.insert_or_assign(Settings::NativeAnalog::LStick, | ||
| 751 | BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(), | ||
| 752 | binding_left_x.value.axis, | ||
| 753 | binding_left_y.value.axis)); | ||
| 754 | const auto& binding_right_x = | ||
| 755 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); | ||
| 756 | const auto& binding_right_y = | ||
| 757 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY); | ||
| 758 | mapping.insert_or_assign(Settings::NativeAnalog::RStick, | ||
| 759 | BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(), | ||
| 760 | binding_right_x.value.axis, | ||
| 761 | binding_right_y.value.axis)); | ||
| 762 | return mapping; | ||
| 763 | } | ||
| 764 | |||
| 765 | namespace Polling { | ||
| 580 | class SDLPoller : public InputCommon::Polling::DevicePoller { | 766 | class SDLPoller : public InputCommon::Polling::DevicePoller { |
| 581 | public: | 767 | public: |
| 582 | explicit SDLPoller(SDLState& state_) : state(state_) {} | 768 | explicit SDLPoller(SDLState& state_) : state(state_) {} |
| 583 | 769 | ||
| 584 | void Start() override { | 770 | void Start(const std::string& device_id) override { |
| 585 | state.event_queue.Clear(); | 771 | state.event_queue.Clear(); |
| 586 | state.polling = true; | 772 | state.polling = true; |
| 587 | } | 773 | } |
| @@ -601,71 +787,106 @@ public: | |||
| 601 | Common::ParamPackage GetNextInput() override { | 787 | Common::ParamPackage GetNextInput() override { |
| 602 | SDL_Event event; | 788 | SDL_Event event; |
| 603 | while (state.event_queue.Pop(event)) { | 789 | while (state.event_queue.Pop(event)) { |
| 604 | switch (event.type) { | 790 | const auto package = FromEvent(event); |
| 605 | case SDL_JOYAXISMOTION: | 791 | if (package) { |
| 606 | if (std::abs(event.jaxis.value / 32767.0) < 0.5) { | 792 | return *package; |
| 607 | break; | ||
| 608 | } | ||
| 609 | [[fallthrough]]; | ||
| 610 | case SDL_JOYBUTTONUP: | ||
| 611 | case SDL_JOYHATMOTION: | ||
| 612 | return SDLEventToButtonParamPackage(state, event); | ||
| 613 | } | 793 | } |
| 614 | } | 794 | } |
| 615 | return {}; | 795 | return {}; |
| 616 | } | 796 | } |
| 797 | [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(const SDL_Event& event) const { | ||
| 798 | switch (event.type) { | ||
| 799 | case SDL_JOYAXISMOTION: | ||
| 800 | if (std::abs(event.jaxis.value / 32767.0) < 0.5) { | ||
| 801 | break; | ||
| 802 | } | ||
| 803 | [[fallthrough]]; | ||
| 804 | case SDL_JOYBUTTONUP: | ||
| 805 | case SDL_JOYHATMOTION: | ||
| 806 | return {SDLEventToButtonParamPackage(state, event)}; | ||
| 807 | } | ||
| 808 | return std::nullopt; | ||
| 809 | } | ||
| 617 | }; | 810 | }; |
| 618 | 811 | ||
| 619 | class SDLAnalogPoller final : public SDLPoller { | 812 | /** |
| 813 | * Attempts to match the press to a controller joy axis (left/right stick) and if a match | ||
| 814 | * isn't found, checks if the event matches anything from SDLButtonPoller and uses that | ||
| 815 | * instead | ||
| 816 | */ | ||
| 817 | class SDLAnalogPreferredPoller final : public SDLPoller { | ||
| 620 | public: | 818 | public: |
| 621 | explicit SDLAnalogPoller(SDLState& state_) : SDLPoller(state_) {} | 819 | explicit SDLAnalogPreferredPoller(SDLState& state_) |
| 622 | 820 | : SDLPoller(state_), button_poller(state_) {} | |
| 623 | void Start() override { | ||
| 624 | SDLPoller::Start(); | ||
| 625 | 821 | ||
| 822 | void Start(const std::string& device_id) override { | ||
| 823 | SDLPoller::Start(device_id); | ||
| 824 | // Load the game controller | ||
| 626 | // Reset stored axes | 825 | // Reset stored axes |
| 627 | analog_x_axis = -1; | 826 | analog_x_axis = -1; |
| 628 | analog_y_axis = -1; | 827 | analog_y_axis = -1; |
| 629 | analog_axes_joystick = -1; | ||
| 630 | } | 828 | } |
| 631 | 829 | ||
| 632 | Common::ParamPackage GetNextInput() override { | 830 | Common::ParamPackage GetNextInput() override { |
| 633 | SDL_Event event; | 831 | SDL_Event event; |
| 634 | while (state.event_queue.Pop(event)) { | 832 | while (state.event_queue.Pop(event)) { |
| 635 | if (event.type != SDL_JOYAXISMOTION || std::abs(event.jaxis.value / 32767.0) < 0.5) { | 833 | // Filter out axis events that are below a threshold |
| 834 | if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) { | ||
| 636 | continue; | 835 | continue; |
| 637 | } | 836 | } |
| 638 | // An analog device needs two axes, so we need to store the axis for later and wait for | 837 | // Simplify controller config by testing if game controller support is enabled. |
| 639 | // a second SDL event. The axes also must be from the same joystick. | 838 | if (event.type == SDL_JOYAXISMOTION) { |
| 640 | const int axis = event.jaxis.axis; | 839 | const auto axis = event.jaxis.axis; |
| 641 | if (analog_x_axis == -1) { | 840 | const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); |
| 642 | analog_x_axis = axis; | 841 | const auto controller = joystick->GetSDLGameController(); |
| 643 | analog_axes_joystick = event.jaxis.which; | 842 | if (controller) { |
| 644 | } else if (analog_y_axis == -1 && analog_x_axis != axis && | 843 | const auto axis_left_x = |
| 645 | analog_axes_joystick == event.jaxis.which) { | 844 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) |
| 646 | analog_y_axis = axis; | 845 | .value.axis; |
| 846 | const auto axis_left_y = | ||
| 847 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) | ||
| 848 | .value.axis; | ||
| 849 | const auto axis_right_x = | ||
| 850 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX) | ||
| 851 | .value.axis; | ||
| 852 | const auto axis_right_y = | ||
| 853 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY) | ||
| 854 | .value.axis; | ||
| 855 | |||
| 856 | if (axis == axis_left_x || axis == axis_left_y) { | ||
| 857 | analog_x_axis = axis_left_x; | ||
| 858 | analog_y_axis = axis_left_y; | ||
| 859 | break; | ||
| 860 | } else if (axis == axis_right_x || axis == axis_right_y) { | ||
| 861 | analog_x_axis = axis_right_x; | ||
| 862 | analog_y_axis = axis_right_y; | ||
| 863 | break; | ||
| 864 | } | ||
| 865 | } | ||
| 866 | } | ||
| 867 | |||
| 868 | // If the press wasn't accepted as a joy axis, check for a button press | ||
| 869 | auto button_press = button_poller.FromEvent(event); | ||
| 870 | if (button_press) { | ||
| 871 | return *button_press; | ||
| 647 | } | 872 | } |
| 648 | } | 873 | } |
| 649 | Common::ParamPackage params; | 874 | |
| 650 | if (analog_x_axis != -1 && analog_y_axis != -1) { | 875 | if (analog_x_axis != -1 && analog_y_axis != -1) { |
| 651 | const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | 876 | const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); |
| 652 | params.Set("engine", "sdl"); | 877 | auto params = BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(), |
| 653 | params.Set("port", joystick->GetPort()); | 878 | analog_x_axis, analog_y_axis); |
| 654 | params.Set("guid", joystick->GetGUID()); | ||
| 655 | params.Set("axis_x", analog_x_axis); | ||
| 656 | params.Set("axis_y", analog_y_axis); | ||
| 657 | analog_x_axis = -1; | 879 | analog_x_axis = -1; |
| 658 | analog_y_axis = -1; | 880 | analog_y_axis = -1; |
| 659 | analog_axes_joystick = -1; | ||
| 660 | return params; | 881 | return params; |
| 661 | } | 882 | } |
| 662 | return params; | 883 | return {}; |
| 663 | } | 884 | } |
| 664 | 885 | ||
| 665 | private: | 886 | private: |
| 666 | int analog_x_axis = -1; | 887 | int analog_x_axis = -1; |
| 667 | int analog_y_axis = -1; | 888 | int analog_y_axis = -1; |
| 668 | SDL_JoystickID analog_axes_joystick = -1; | 889 | SDLButtonPoller button_poller; |
| 669 | }; | 890 | }; |
| 670 | } // namespace Polling | 891 | } // namespace Polling |
| 671 | 892 | ||
| @@ -673,8 +894,8 @@ SDLState::Pollers SDLState::GetPollers(InputCommon::Polling::DeviceType type) { | |||
| 673 | Pollers pollers; | 894 | Pollers pollers; |
| 674 | 895 | ||
| 675 | switch (type) { | 896 | switch (type) { |
| 676 | case InputCommon::Polling::DeviceType::Analog: | 897 | case InputCommon::Polling::DeviceType::AnalogPreferred: |
| 677 | pollers.emplace_back(std::make_unique<Polling::SDLAnalogPoller>(*this)); | 898 | pollers.emplace_back(std::make_unique<Polling::SDLAnalogPreferredPoller>(*this)); |
| 678 | break; | 899 | break; |
| 679 | case InputCommon::Polling::DeviceType::Button: | 900 | case InputCommon::Polling::DeviceType::Button: |
| 680 | pollers.emplace_back(std::make_unique<Polling::SDLButtonPoller>(*this)); | 901 | pollers.emplace_back(std::make_unique<Polling::SDLButtonPoller>(*this)); |
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 606a32c5b..bd19ba61d 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h | |||
| @@ -50,6 +50,11 @@ public: | |||
| 50 | std::atomic<bool> polling = false; | 50 | std::atomic<bool> polling = false; |
| 51 | Common::SPSCQueue<SDL_Event> event_queue; | 51 | Common::SPSCQueue<SDL_Event> event_queue; |
| 52 | 52 | ||
| 53 | std::vector<Common::ParamPackage> GetInputDevices() override; | ||
| 54 | |||
| 55 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; | ||
| 56 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; | ||
| 57 | |||
| 53 | private: | 58 | private: |
| 54 | void InitJoystick(int joystick_index); | 59 | void InitJoystick(int joystick_index); |
| 55 | void CloseJoystick(SDL_Joystick* sdl_joystick); | 60 | void CloseJoystick(SDL_Joystick* sdl_joystick); |
| @@ -57,6 +62,9 @@ private: | |||
| 57 | /// Needs to be called before SDL_QuitSubSystem. | 62 | /// Needs to be called before SDL_QuitSubSystem. |
| 58 | void CloseJoysticks(); | 63 | void CloseJoysticks(); |
| 59 | 64 | ||
| 65 | // Set to true if SDL supports game controller subsystem | ||
| 66 | bool has_gamecontroller = false; | ||
| 67 | |||
| 60 | /// Map of GUID of a list of corresponding virtual Joysticks | 68 | /// Map of GUID of a list of corresponding virtual Joysticks |
| 61 | std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map; | 69 | std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map; |
| 62 | std::mutex joystick_map_mutex; | 70 | std::mutex joystick_map_mutex; |
diff --git a/src/input_common/settings.cpp b/src/input_common/settings.cpp new file mode 100644 index 000000000..80c719cf4 --- /dev/null +++ b/src/input_common/settings.cpp | |||
| @@ -0,0 +1,33 @@ | |||
| 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 "input_common/settings.h" | ||
| 6 | |||
| 7 | namespace Settings { | ||
| 8 | namespace NativeButton { | ||
| 9 | const std::array<const char*, NumButtons> mapping = {{ | ||
| 10 | "button_a", "button_b", "button_x", "button_y", "button_lstick", | ||
| 11 | "button_rstick", "button_l", "button_r", "button_zl", "button_zr", | ||
| 12 | "button_plus", "button_minus", "button_dleft", "button_dup", "button_dright", | ||
| 13 | "button_ddown", "button_sl", "button_sr", "button_home", "button_screenshot", | ||
| 14 | }}; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace NativeAnalog { | ||
| 18 | const std::array<const char*, NumAnalogs> mapping = {{ | ||
| 19 | "lstick", | ||
| 20 | "rstick", | ||
| 21 | }}; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace NativeMouseButton { | ||
| 25 | const std::array<const char*, NumMouseButtons> mapping = {{ | ||
| 26 | "left", | ||
| 27 | "right", | ||
| 28 | "middle", | ||
| 29 | "forward", | ||
| 30 | "back", | ||
| 31 | }}; | ||
| 32 | } | ||
| 33 | } // namespace Settings | ||
diff --git a/src/input_common/settings.h b/src/input_common/settings.h new file mode 100644 index 000000000..2d258960b --- /dev/null +++ b/src/input_common/settings.h | |||
| @@ -0,0 +1,335 @@ | |||
| 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 <string> | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace Settings { | ||
| 12 | namespace NativeButton { | ||
| 13 | enum Values : int { | ||
| 14 | A, | ||
| 15 | B, | ||
| 16 | X, | ||
| 17 | Y, | ||
| 18 | LStick, | ||
| 19 | RStick, | ||
| 20 | L, | ||
| 21 | R, | ||
| 22 | ZL, | ||
| 23 | ZR, | ||
| 24 | Plus, | ||
| 25 | Minus, | ||
| 26 | |||
| 27 | DLeft, | ||
| 28 | DUp, | ||
| 29 | DRight, | ||
| 30 | DDown, | ||
| 31 | |||
| 32 | SL, | ||
| 33 | SR, | ||
| 34 | |||
| 35 | Home, | ||
| 36 | Screenshot, | ||
| 37 | |||
| 38 | NumButtons, | ||
| 39 | }; | ||
| 40 | |||
| 41 | constexpr int BUTTON_HID_BEGIN = A; | ||
| 42 | constexpr int BUTTON_NS_BEGIN = Home; | ||
| 43 | |||
| 44 | constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN; | ||
| 45 | constexpr int BUTTON_NS_END = NumButtons; | ||
| 46 | |||
| 47 | constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; | ||
| 48 | constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; | ||
| 49 | |||
| 50 | extern const std::array<const char*, NumButtons> mapping; | ||
| 51 | |||
| 52 | } // namespace NativeButton | ||
| 53 | |||
| 54 | namespace NativeAnalog { | ||
| 55 | enum Values : int { | ||
| 56 | LStick, | ||
| 57 | RStick, | ||
| 58 | |||
| 59 | NumAnalogs, | ||
| 60 | }; | ||
| 61 | |||
| 62 | constexpr int STICK_HID_BEGIN = LStick; | ||
| 63 | constexpr int STICK_HID_END = NumAnalogs; | ||
| 64 | constexpr int NUM_STICKS_HID = NumAnalogs; | ||
| 65 | |||
| 66 | extern const std::array<const char*, NumAnalogs> mapping; | ||
| 67 | } // namespace NativeAnalog | ||
| 68 | |||
| 69 | namespace NativeMouseButton { | ||
| 70 | enum Values { | ||
| 71 | Left, | ||
| 72 | Right, | ||
| 73 | Middle, | ||
| 74 | Forward, | ||
| 75 | Back, | ||
| 76 | |||
| 77 | NumMouseButtons, | ||
| 78 | }; | ||
| 79 | |||
| 80 | constexpr int MOUSE_HID_BEGIN = Left; | ||
| 81 | constexpr int MOUSE_HID_END = NumMouseButtons; | ||
| 82 | constexpr int NUM_MOUSE_HID = NumMouseButtons; | ||
| 83 | |||
| 84 | extern const std::array<const char*, NumMouseButtons> mapping; | ||
| 85 | } // namespace NativeMouseButton | ||
| 86 | |||
| 87 | namespace NativeKeyboard { | ||
| 88 | enum Keys { | ||
| 89 | None, | ||
| 90 | Error, | ||
| 91 | |||
| 92 | A = 4, | ||
| 93 | B, | ||
| 94 | C, | ||
| 95 | D, | ||
| 96 | E, | ||
| 97 | F, | ||
| 98 | G, | ||
| 99 | H, | ||
| 100 | I, | ||
| 101 | J, | ||
| 102 | K, | ||
| 103 | L, | ||
| 104 | M, | ||
| 105 | N, | ||
| 106 | O, | ||
| 107 | P, | ||
| 108 | Q, | ||
| 109 | R, | ||
| 110 | S, | ||
| 111 | T, | ||
| 112 | U, | ||
| 113 | V, | ||
| 114 | W, | ||
| 115 | X, | ||
| 116 | Y, | ||
| 117 | Z, | ||
| 118 | N1, | ||
| 119 | N2, | ||
| 120 | N3, | ||
| 121 | N4, | ||
| 122 | N5, | ||
| 123 | N6, | ||
| 124 | N7, | ||
| 125 | N8, | ||
| 126 | N9, | ||
| 127 | N0, | ||
| 128 | Enter, | ||
| 129 | Escape, | ||
| 130 | Backspace, | ||
| 131 | Tab, | ||
| 132 | Space, | ||
| 133 | Minus, | ||
| 134 | Equal, | ||
| 135 | LeftBrace, | ||
| 136 | RightBrace, | ||
| 137 | Backslash, | ||
| 138 | Tilde, | ||
| 139 | Semicolon, | ||
| 140 | Apostrophe, | ||
| 141 | Grave, | ||
| 142 | Comma, | ||
| 143 | Dot, | ||
| 144 | Slash, | ||
| 145 | CapsLockKey, | ||
| 146 | |||
| 147 | F1, | ||
| 148 | F2, | ||
| 149 | F3, | ||
| 150 | F4, | ||
| 151 | F5, | ||
| 152 | F6, | ||
| 153 | F7, | ||
| 154 | F8, | ||
| 155 | F9, | ||
| 156 | F10, | ||
| 157 | F11, | ||
| 158 | F12, | ||
| 159 | |||
| 160 | SystemRequest, | ||
| 161 | ScrollLockKey, | ||
| 162 | Pause, | ||
| 163 | Insert, | ||
| 164 | Home, | ||
| 165 | PageUp, | ||
| 166 | Delete, | ||
| 167 | End, | ||
| 168 | PageDown, | ||
| 169 | Right, | ||
| 170 | Left, | ||
| 171 | Down, | ||
| 172 | Up, | ||
| 173 | |||
| 174 | NumLockKey, | ||
| 175 | KPSlash, | ||
| 176 | KPAsterisk, | ||
| 177 | KPMinus, | ||
| 178 | KPPlus, | ||
| 179 | KPEnter, | ||
| 180 | KP1, | ||
| 181 | KP2, | ||
| 182 | KP3, | ||
| 183 | KP4, | ||
| 184 | KP5, | ||
| 185 | KP6, | ||
| 186 | KP7, | ||
| 187 | KP8, | ||
| 188 | KP9, | ||
| 189 | KP0, | ||
| 190 | KPDot, | ||
| 191 | |||
| 192 | Key102, | ||
| 193 | Compose, | ||
| 194 | Power, | ||
| 195 | KPEqual, | ||
| 196 | |||
| 197 | F13, | ||
| 198 | F14, | ||
| 199 | F15, | ||
| 200 | F16, | ||
| 201 | F17, | ||
| 202 | F18, | ||
| 203 | F19, | ||
| 204 | F20, | ||
| 205 | F21, | ||
| 206 | F22, | ||
| 207 | F23, | ||
| 208 | F24, | ||
| 209 | |||
| 210 | Open, | ||
| 211 | Help, | ||
| 212 | Properties, | ||
| 213 | Front, | ||
| 214 | Stop, | ||
| 215 | Repeat, | ||
| 216 | Undo, | ||
| 217 | Cut, | ||
| 218 | Copy, | ||
| 219 | Paste, | ||
| 220 | Find, | ||
| 221 | Mute, | ||
| 222 | VolumeUp, | ||
| 223 | VolumeDown, | ||
| 224 | CapsLockActive, | ||
| 225 | NumLockActive, | ||
| 226 | ScrollLockActive, | ||
| 227 | KPComma, | ||
| 228 | |||
| 229 | KPLeftParenthesis, | ||
| 230 | KPRightParenthesis, | ||
| 231 | |||
| 232 | LeftControlKey = 0xE0, | ||
| 233 | LeftShiftKey, | ||
| 234 | LeftAltKey, | ||
| 235 | LeftMetaKey, | ||
| 236 | RightControlKey, | ||
| 237 | RightShiftKey, | ||
| 238 | RightAltKey, | ||
| 239 | RightMetaKey, | ||
| 240 | |||
| 241 | MediaPlayPause, | ||
| 242 | MediaStopCD, | ||
| 243 | MediaPrevious, | ||
| 244 | MediaNext, | ||
| 245 | MediaEject, | ||
| 246 | MediaVolumeUp, | ||
| 247 | MediaVolumeDown, | ||
| 248 | MediaMute, | ||
| 249 | MediaWebsite, | ||
| 250 | MediaBack, | ||
| 251 | MediaForward, | ||
| 252 | MediaStop, | ||
| 253 | MediaFind, | ||
| 254 | MediaScrollUp, | ||
| 255 | MediaScrollDown, | ||
| 256 | MediaEdit, | ||
| 257 | MediaSleep, | ||
| 258 | MediaCoffee, | ||
| 259 | MediaRefresh, | ||
| 260 | MediaCalculator, | ||
| 261 | |||
| 262 | NumKeyboardKeys, | ||
| 263 | }; | ||
| 264 | |||
| 265 | static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys."); | ||
| 266 | |||
| 267 | enum Modifiers { | ||
| 268 | LeftControl, | ||
| 269 | LeftShift, | ||
| 270 | LeftAlt, | ||
| 271 | LeftMeta, | ||
| 272 | RightControl, | ||
| 273 | RightShift, | ||
| 274 | RightAlt, | ||
| 275 | RightMeta, | ||
| 276 | CapsLock, | ||
| 277 | ScrollLock, | ||
| 278 | NumLock, | ||
| 279 | |||
| 280 | NumKeyboardMods, | ||
| 281 | }; | ||
| 282 | |||
| 283 | constexpr int KEYBOARD_KEYS_HID_BEGIN = None; | ||
| 284 | constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys; | ||
| 285 | constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys; | ||
| 286 | |||
| 287 | constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl; | ||
| 288 | constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods; | ||
| 289 | constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; | ||
| 290 | |||
| 291 | } // namespace NativeKeyboard | ||
| 292 | |||
| 293 | using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; | ||
| 294 | using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; | ||
| 295 | using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; | ||
| 296 | using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; | ||
| 297 | using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; | ||
| 298 | |||
| 299 | constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; | ||
| 300 | constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; | ||
| 301 | constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; | ||
| 302 | constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; | ||
| 303 | |||
| 304 | enum class ControllerType { | ||
| 305 | ProController, | ||
| 306 | DualJoyconDetached, | ||
| 307 | LeftJoycon, | ||
| 308 | RightJoycon, | ||
| 309 | Handheld, | ||
| 310 | }; | ||
| 311 | |||
| 312 | struct PlayerInput { | ||
| 313 | bool connected; | ||
| 314 | ControllerType controller_type; | ||
| 315 | ButtonsRaw buttons; | ||
| 316 | AnalogsRaw analogs; | ||
| 317 | std::string lstick_mod; | ||
| 318 | std::string rstick_mod; | ||
| 319 | |||
| 320 | u32 body_color_left; | ||
| 321 | u32 body_color_right; | ||
| 322 | u32 button_color_left; | ||
| 323 | u32 button_color_right; | ||
| 324 | }; | ||
| 325 | |||
| 326 | struct TouchscreenInput { | ||
| 327 | bool enabled; | ||
| 328 | std::string device; | ||
| 329 | |||
| 330 | u32 finger; | ||
| 331 | u32 diameter_x; | ||
| 332 | u32 diameter_y; | ||
| 333 | u32 rotation_angle; | ||
| 334 | }; | ||
| 335 | } // namespace Settings | ||
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp new file mode 100644 index 000000000..98da0ef1a --- /dev/null +++ b/src/input_common/touch_from_button.cpp | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | // Copyright 2020 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/frontend/framebuffer_layout.h" | ||
| 6 | #include "core/settings.h" | ||
| 7 | #include "input_common/touch_from_button.h" | ||
| 8 | |||
| 9 | namespace InputCommon { | ||
| 10 | |||
| 11 | class TouchFromButtonDevice final : public Input::TouchDevice { | ||
| 12 | public: | ||
| 13 | TouchFromButtonDevice() { | ||
| 14 | for (const auto& config_entry : | ||
| 15 | Settings::values.touch_from_button_maps[Settings::values.touch_from_button_map_index] | ||
| 16 | .buttons) { | ||
| 17 | const Common::ParamPackage package{config_entry}; | ||
| 18 | map.emplace_back( | ||
| 19 | Input::CreateDevice<Input::ButtonDevice>(config_entry), | ||
| 20 | std::clamp(package.Get("x", 0), 0, static_cast<int>(Layout::ScreenUndocked::Width)), | ||
| 21 | std::clamp(package.Get("y", 0), 0, | ||
| 22 | static_cast<int>(Layout::ScreenUndocked::Height))); | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | std::tuple<float, float, bool> GetStatus() const override { | ||
| 27 | for (const auto& m : map) { | ||
| 28 | const bool state = std::get<0>(m)->GetStatus(); | ||
| 29 | if (state) { | ||
| 30 | const float x = static_cast<float>(std::get<1>(m)) / | ||
| 31 | static_cast<int>(Layout::ScreenUndocked::Width); | ||
| 32 | const float y = static_cast<float>(std::get<2>(m)) / | ||
| 33 | static_cast<int>(Layout::ScreenUndocked::Height); | ||
| 34 | return {x, y, true}; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | return {}; | ||
| 38 | } | ||
| 39 | |||
| 40 | private: | ||
| 41 | // A vector of the mapped button, its x and its y-coordinate | ||
| 42 | std::vector<std::tuple<std::unique_ptr<Input::ButtonDevice>, int, int>> map; | ||
| 43 | }; | ||
| 44 | |||
| 45 | std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create( | ||
| 46 | const Common::ParamPackage& params) { | ||
| 47 | return std::make_unique<TouchFromButtonDevice>(); | ||
| 48 | } | ||
| 49 | |||
| 50 | } // namespace InputCommon | ||
diff --git a/src/input_common/touch_from_button.h b/src/input_common/touch_from_button.h new file mode 100644 index 000000000..8b4d1aa96 --- /dev/null +++ b/src/input_common/touch_from_button.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | // Copyright 2020 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 <memory> | ||
| 8 | #include "core/frontend/input.h" | ||
| 9 | |||
| 10 | namespace InputCommon { | ||
| 11 | |||
| 12 | /** | ||
| 13 | * A touch device factory that takes a list of button devices and combines them into a touch device. | ||
| 14 | */ | ||
| 15 | class TouchFromButtonFactory final : public Input::Factory<Input::TouchDevice> { | ||
| 16 | public: | ||
| 17 | /** | ||
| 18 | * Creates a touch device from a list of button devices | ||
| 19 | */ | ||
| 20 | std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override; | ||
| 21 | }; | ||
| 22 | |||
| 23 | } // namespace InputCommon | ||
diff --git a/src/input_common/udp/udp.cpp b/src/input_common/udp/udp.cpp index 8c6ef1394..4b347e47e 100644 --- a/src/input_common/udp/udp.cpp +++ b/src/input_common/udp/udp.cpp | |||
| @@ -77,10 +77,11 @@ State::State() { | |||
| 77 | std::make_unique<Client>(status, Settings::values.udp_input_address, | 77 | std::make_unique<Client>(status, Settings::values.udp_input_address, |
| 78 | Settings::values.udp_input_port, Settings::values.udp_pad_index); | 78 | Settings::values.udp_input_port, Settings::values.udp_pad_index); |
| 79 | 79 | ||
| 80 | Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", | 80 | motion_factory = std::make_shared<UDPMotionFactory>(status); |
| 81 | std::make_shared<UDPTouchFactory>(status)); | 81 | touch_factory = std::make_shared<UDPTouchFactory>(status); |
| 82 | Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", | 82 | |
| 83 | std::make_shared<UDPMotionFactory>(status)); | 83 | Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", motion_factory); |
| 84 | Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", touch_factory); | ||
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | State::~State() { | 87 | State::~State() { |
| @@ -88,6 +89,11 @@ State::~State() { | |||
| 88 | Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); | 89 | Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); |
| 89 | } | 90 | } |
| 90 | 91 | ||
| 92 | std::vector<Common::ParamPackage> State::GetInputDevices() const { | ||
| 93 | // TODO support binding udp devices | ||
| 94 | return {}; | ||
| 95 | } | ||
| 96 | |||
| 91 | void State::ReloadUDPClient() { | 97 | void State::ReloadUDPClient() { |
| 92 | client->ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, | 98 | client->ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, |
| 93 | Settings::values.udp_pad_index); | 99 | Settings::values.udp_pad_index); |
diff --git a/src/input_common/udp/udp.h b/src/input_common/udp/udp.h index 4f83f0441..672a5c812 100644 --- a/src/input_common/udp/udp.h +++ b/src/input_common/udp/udp.h | |||
| @@ -5,19 +5,26 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <vector> | ||
| 9 | #include "common/param_package.h" | ||
| 8 | 10 | ||
| 9 | namespace InputCommon::CemuhookUDP { | 11 | namespace InputCommon::CemuhookUDP { |
| 10 | 12 | ||
| 11 | class Client; | 13 | class Client; |
| 14 | class UDPMotionFactory; | ||
| 15 | class UDPTouchFactory; | ||
| 12 | 16 | ||
| 13 | class State { | 17 | class State { |
| 14 | public: | 18 | public: |
| 15 | State(); | 19 | State(); |
| 16 | ~State(); | 20 | ~State(); |
| 17 | void ReloadUDPClient(); | 21 | void ReloadUDPClient(); |
| 22 | std::vector<Common::ParamPackage> GetInputDevices() const; | ||
| 18 | 23 | ||
| 19 | private: | 24 | private: |
| 20 | std::unique_ptr<Client> client; | 25 | std::unique_ptr<Client> client; |
| 26 | std::shared_ptr<UDPMotionFactory> motion_factory; | ||
| 27 | std::shared_ptr<UDPTouchFactory> touch_factory; | ||
| 21 | }; | 28 | }; |
| 22 | 29 | ||
| 23 | std::unique_ptr<State> Init(); | 30 | std::unique_ptr<State> Init(); |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 3cd896a0f..d85f1e9d1 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | add_subdirectory(host_shaders) | ||
| 2 | |||
| 1 | add_library(video_core STATIC | 3 | add_library(video_core STATIC |
| 2 | buffer_cache/buffer_block.h | 4 | buffer_cache/buffer_block.h |
| 3 | buffer_cache/buffer_cache.h | 5 | buffer_cache/buffer_cache.h |
| @@ -244,6 +246,9 @@ create_target_directory_groups(video_core) | |||
| 244 | target_link_libraries(video_core PUBLIC common core) | 246 | target_link_libraries(video_core PUBLIC common core) |
| 245 | target_link_libraries(video_core PRIVATE glad xbyak) | 247 | target_link_libraries(video_core PRIVATE glad xbyak) |
| 246 | 248 | ||
| 249 | add_dependencies(video_core host_shaders) | ||
| 250 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) | ||
| 251 | |||
| 247 | if (ENABLE_VULKAN) | 252 | if (ENABLE_VULKAN) |
| 248 | target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include) | 253 | target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include) |
| 249 | target_compile_definitions(video_core PRIVATE HAS_VULKAN) | 254 | target_compile_definitions(video_core PRIVATE HAS_VULKAN) |
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt new file mode 100644 index 000000000..aa62363a7 --- /dev/null +++ b/src/video_core/host_shaders/CMakeLists.txt | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | set(SHADER_FILES | ||
| 2 | opengl_present.frag | ||
| 3 | opengl_present.vert | ||
| 4 | ) | ||
| 5 | |||
| 6 | set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include) | ||
| 7 | set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE) | ||
| 8 | |||
| 9 | set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders) | ||
| 10 | add_custom_command( | ||
| 11 | OUTPUT | ||
| 12 | ${SHADER_DIR} | ||
| 13 | COMMAND | ||
| 14 | ${CMAKE_COMMAND} -E make_directory ${SHADER_DIR} | ||
| 15 | ) | ||
| 16 | |||
| 17 | set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in) | ||
| 18 | set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake) | ||
| 19 | |||
| 20 | foreach(FILENAME IN ITEMS ${SHADER_FILES}) | ||
| 21 | string(REPLACE "." "_" SHADER_NAME ${FILENAME}) | ||
| 22 | set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}) | ||
| 23 | set(HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}.h) | ||
| 24 | add_custom_command( | ||
| 25 | OUTPUT | ||
| 26 | ${HEADER_FILE} | ||
| 27 | COMMAND | ||
| 28 | ${CMAKE_COMMAND} -P ${HEADER_GENERATOR} ${SOURCE_FILE} ${HEADER_FILE} ${INPUT_FILE} | ||
| 29 | MAIN_DEPENDENCY | ||
| 30 | ${SOURCE_FILE} | ||
| 31 | DEPENDS | ||
| 32 | ${HEADER_GENERATOR} | ||
| 33 | ${INPUT_FILE} | ||
| 34 | ) | ||
| 35 | set(SHADER_HEADERS ${SHADER_HEADERS} ${HEADER_FILE}) | ||
| 36 | endforeach() | ||
| 37 | |||
| 38 | add_custom_target(host_shaders | ||
| 39 | DEPENDS | ||
| 40 | ${SHADER_HEADERS} | ||
| 41 | SOURCES | ||
| 42 | ${SHADER_FILES} | ||
| 43 | ) | ||
diff --git a/src/video_core/host_shaders/StringShaderHeader.cmake b/src/video_core/host_shaders/StringShaderHeader.cmake new file mode 100644 index 000000000..368bce0ed --- /dev/null +++ b/src/video_core/host_shaders/StringShaderHeader.cmake | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | set(SOURCE_FILE ${CMAKE_ARGV3}) | ||
| 2 | set(HEADER_FILE ${CMAKE_ARGV4}) | ||
| 3 | set(INPUT_FILE ${CMAKE_ARGV5}) | ||
| 4 | |||
| 5 | get_filename_component(CONTENTS_NAME ${SOURCE_FILE} NAME) | ||
| 6 | string(REPLACE "." "_" CONTENTS_NAME ${CONTENTS_NAME}) | ||
| 7 | string(TOUPPER ${CONTENTS_NAME} CONTENTS_NAME) | ||
| 8 | |||
| 9 | file(READ ${SOURCE_FILE} CONTENTS) | ||
| 10 | |||
| 11 | configure_file(${INPUT_FILE} ${HEADER_FILE} @ONLY) | ||
diff --git a/src/video_core/host_shaders/opengl_present.frag b/src/video_core/host_shaders/opengl_present.frag new file mode 100644 index 000000000..8a4cb024b --- /dev/null +++ b/src/video_core/host_shaders/opengl_present.frag | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #version 430 core | ||
| 2 | |||
| 3 | layout (location = 0) in vec2 frag_tex_coord; | ||
| 4 | layout (location = 0) out vec4 color; | ||
| 5 | |||
| 6 | layout (binding = 0) uniform sampler2D color_texture; | ||
| 7 | |||
| 8 | void main() { | ||
| 9 | color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f); | ||
| 10 | } | ||
diff --git a/src/video_core/host_shaders/opengl_present.vert b/src/video_core/host_shaders/opengl_present.vert new file mode 100644 index 000000000..2235d31a4 --- /dev/null +++ b/src/video_core/host_shaders/opengl_present.vert | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #version 430 core | ||
| 2 | |||
| 3 | out gl_PerVertex { | ||
| 4 | vec4 gl_Position; | ||
| 5 | }; | ||
| 6 | |||
| 7 | layout (location = 0) in vec2 vert_position; | ||
| 8 | layout (location = 1) in vec2 vert_tex_coord; | ||
| 9 | layout (location = 0) out vec2 frag_tex_coord; | ||
| 10 | |||
| 11 | // This is a truncated 3x3 matrix for 2D transformations: | ||
| 12 | // The upper-left 2x2 submatrix performs scaling/rotation/mirroring. | ||
| 13 | // The third column performs translation. | ||
| 14 | // The third row could be used for projection, which we don't need in 2D. It hence is assumed to | ||
| 15 | // implicitly be [0, 0, 1] | ||
| 16 | layout (location = 0) uniform mat3x2 modelview_matrix; | ||
| 17 | |||
| 18 | void main() { | ||
| 19 | // Multiply input position by the rotscale part of the matrix and then manually translate by | ||
| 20 | // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector | ||
| 21 | // to `vec3(vert_position.xy, 1.0)` | ||
| 22 | gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); | ||
| 23 | frag_tex_coord = vert_tex_coord; | ||
| 24 | } | ||
diff --git a/src/video_core/host_shaders/source_shader.h.in b/src/video_core/host_shaders/source_shader.h.in new file mode 100644 index 000000000..ccdb0d2a9 --- /dev/null +++ b/src/video_core/host_shaders/source_shader.h.in | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <string_view> | ||
| 4 | |||
| 5 | namespace HostShaders { | ||
| 6 | |||
| 7 | constexpr std::string_view @CONTENTS_NAME@ = R"(@CONTENTS@)"; | ||
| 8 | |||
| 9 | } // namespace HostShaders | ||
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index 533b415e9..53c8d122a 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -31,19 +31,19 @@ public: | |||
| 31 | constexpr PageEntry(State state) : state{state} {} | 31 | constexpr PageEntry(State state) : state{state} {} |
| 32 | constexpr PageEntry(VAddr addr) : state{static_cast<State>(addr >> ShiftBits)} {} | 32 | constexpr PageEntry(VAddr addr) : state{static_cast<State>(addr >> ShiftBits)} {} |
| 33 | 33 | ||
| 34 | constexpr bool IsUnmapped() const { | 34 | [[nodiscard]] constexpr bool IsUnmapped() const { |
| 35 | return state == State::Unmapped; | 35 | return state == State::Unmapped; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | constexpr bool IsAllocated() const { | 38 | [[nodiscard]] constexpr bool IsAllocated() const { |
| 39 | return state == State::Allocated; | 39 | return state == State::Allocated; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | constexpr bool IsValid() const { | 42 | [[nodiscard]] constexpr bool IsValid() const { |
| 43 | return !IsUnmapped() && !IsAllocated(); | 43 | return !IsUnmapped() && !IsAllocated(); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | constexpr VAddr ToAddress() const { | 46 | [[nodiscard]] constexpr VAddr ToAddress() const { |
| 47 | if (!IsValid()) { | 47 | if (!IsValid()) { |
| 48 | return {}; | 48 | return {}; |
| 49 | } | 49 | } |
| @@ -51,7 +51,7 @@ public: | |||
| 51 | return static_cast<VAddr>(state) << ShiftBits; | 51 | return static_cast<VAddr>(state) << ShiftBits; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | constexpr PageEntry operator+(u64 offset) { | 54 | [[nodiscard]] constexpr PageEntry operator+(u64 offset) const { |
| 55 | // If this is a reserved value, offsets do not apply | 55 | // If this is a reserved value, offsets do not apply |
| 56 | if (!IsValid()) { | 56 | if (!IsValid()) { |
| 57 | return *this; | 57 | return *this; |
| @@ -74,16 +74,16 @@ public: | |||
| 74 | /// Binds a renderer to the memory manager. | 74 | /// Binds a renderer to the memory manager. |
| 75 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | 75 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); |
| 76 | 76 | ||
| 77 | std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; | 77 | [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; |
| 78 | 78 | ||
| 79 | template <typename T> | 79 | template <typename T> |
| 80 | T Read(GPUVAddr addr) const; | 80 | [[nodiscard]] T Read(GPUVAddr addr) const; |
| 81 | 81 | ||
| 82 | template <typename T> | 82 | template <typename T> |
| 83 | void Write(GPUVAddr addr, T data); | 83 | void Write(GPUVAddr addr, T data); |
| 84 | 84 | ||
| 85 | u8* GetPointer(GPUVAddr addr); | 85 | [[nodiscard]] u8* GetPointer(GPUVAddr addr); |
| 86 | const u8* GetPointer(GPUVAddr addr) const; | 86 | [[nodiscard]] const u8* GetPointer(GPUVAddr addr) const; |
| 87 | 87 | ||
| 88 | /** | 88 | /** |
| 89 | * ReadBlock and WriteBlock are full read and write operations over virtual | 89 | * ReadBlock and WriteBlock are full read and write operations over virtual |
| @@ -112,24 +112,24 @@ public: | |||
| 112 | /** | 112 | /** |
| 113 | * IsGranularRange checks if a gpu region can be simply read with a pointer. | 113 | * IsGranularRange checks if a gpu region can be simply read with a pointer. |
| 114 | */ | 114 | */ |
| 115 | bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const; | 115 | [[nodiscard]] bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const; |
| 116 | 116 | ||
| 117 | GPUVAddr Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size); | 117 | [[nodiscard]] GPUVAddr Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size); |
| 118 | GPUVAddr MapAllocate(VAddr cpu_addr, std::size_t size, std::size_t align); | 118 | [[nodiscard]] GPUVAddr MapAllocate(VAddr cpu_addr, std::size_t size, std::size_t align); |
| 119 | std::optional<GPUVAddr> AllocateFixed(GPUVAddr gpu_addr, std::size_t size); | 119 | [[nodiscard]] std::optional<GPUVAddr> AllocateFixed(GPUVAddr gpu_addr, std::size_t size); |
| 120 | GPUVAddr Allocate(std::size_t size, std::size_t align); | 120 | [[nodiscard]] GPUVAddr Allocate(std::size_t size, std::size_t align); |
| 121 | void Unmap(GPUVAddr gpu_addr, std::size_t size); | 121 | void Unmap(GPUVAddr gpu_addr, std::size_t size); |
| 122 | 122 | ||
| 123 | private: | 123 | private: |
| 124 | PageEntry GetPageEntry(GPUVAddr gpu_addr) const; | 124 | [[nodiscard]] PageEntry GetPageEntry(GPUVAddr gpu_addr) const; |
| 125 | void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size); | 125 | void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size); |
| 126 | GPUVAddr UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size); | 126 | GPUVAddr UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size); |
| 127 | std::optional<GPUVAddr> FindFreeRange(std::size_t size, std::size_t align) const; | 127 | [[nodiscard]] std::optional<GPUVAddr> FindFreeRange(std::size_t size, std::size_t align) const; |
| 128 | 128 | ||
| 129 | void TryLockPage(PageEntry page_entry, std::size_t size); | 129 | void TryLockPage(PageEntry page_entry, std::size_t size); |
| 130 | void TryUnlockPage(PageEntry page_entry, std::size_t size); | 130 | void TryUnlockPage(PageEntry page_entry, std::size_t size); |
| 131 | 131 | ||
| 132 | static constexpr std::size_t PageEntryIndex(GPUVAddr gpu_addr) { | 132 | [[nodiscard]] static constexpr std::size_t PageEntryIndex(GPUVAddr gpu_addr) { |
| 133 | return (gpu_addr >> page_bits) & page_table_mask; | 133 | return (gpu_addr >> page_bits) & page_table_mask; |
| 134 | } | 134 | } |
| 135 | 135 | ||
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index a787e27d2..0ebcec427 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <string_view> | ||
| 5 | #include <utility> | 6 | #include <utility> |
| 6 | #include <glad/glad.h> | 7 | #include <glad/glad.h> |
| 7 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| @@ -82,11 +83,13 @@ void OGLSampler::Release() { | |||
| 82 | handle = 0; | 83 | handle = 0; |
| 83 | } | 84 | } |
| 84 | 85 | ||
| 85 | void OGLShader::Create(const char* source, GLenum type) { | 86 | void OGLShader::Create(std::string_view source, GLenum type) { |
| 86 | if (handle != 0) | 87 | if (handle != 0) { |
| 87 | return; | 88 | return; |
| 88 | if (source == nullptr) | 89 | } |
| 90 | if (source.empty()) { | ||
| 89 | return; | 91 | return; |
| 92 | } | ||
| 90 | 93 | ||
| 91 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); | 94 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); |
| 92 | handle = GLShader::LoadShader(source, type); | 95 | handle = GLShader::LoadShader(source, type); |
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index b05cb641c..f48398669 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <string_view> | ||
| 7 | #include <utility> | 8 | #include <utility> |
| 8 | #include <glad/glad.h> | 9 | #include <glad/glad.h> |
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| @@ -127,7 +128,7 @@ public: | |||
| 127 | return *this; | 128 | return *this; |
| 128 | } | 129 | } |
| 129 | 130 | ||
| 130 | void Create(const char* source, GLenum type); | 131 | void Create(std::string_view source, GLenum type); |
| 131 | 132 | ||
| 132 | void Release(); | 133 | void Release(); |
| 133 | 134 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index eb49a36bf..a07d56ef0 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "video_core/memory_manager.h" | 22 | #include "video_core/memory_manager.h" |
| 23 | #include "video_core/renderer_opengl/gl_arb_decompiler.h" | 23 | #include "video_core/renderer_opengl/gl_arb_decompiler.h" |
| 24 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 24 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 25 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 25 | #include "video_core/renderer_opengl/gl_shader_cache.h" | 26 | #include "video_core/renderer_opengl/gl_shader_cache.h" |
| 26 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" | 27 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" |
| 27 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" | 28 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" |
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp index 9e74eda0d..4bf0d6090 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.cpp +++ b/src/video_core/renderer_opengl/gl_shader_util.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <string_view> | ||
| 5 | #include <vector> | 6 | #include <vector> |
| 6 | #include <glad/glad.h> | 7 | #include <glad/glad.h> |
| 7 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| @@ -11,7 +12,8 @@ | |||
| 11 | namespace OpenGL::GLShader { | 12 | namespace OpenGL::GLShader { |
| 12 | 13 | ||
| 13 | namespace { | 14 | namespace { |
| 14 | const char* GetStageDebugName(GLenum type) { | 15 | |
| 16 | std::string_view StageDebugName(GLenum type) { | ||
| 15 | switch (type) { | 17 | switch (type) { |
| 16 | case GL_VERTEX_SHADER: | 18 | case GL_VERTEX_SHADER: |
| 17 | return "vertex"; | 19 | return "vertex"; |
| @@ -25,12 +27,17 @@ const char* GetStageDebugName(GLenum type) { | |||
| 25 | UNIMPLEMENTED(); | 27 | UNIMPLEMENTED(); |
| 26 | return "unknown"; | 28 | return "unknown"; |
| 27 | } | 29 | } |
| 30 | |||
| 28 | } // Anonymous namespace | 31 | } // Anonymous namespace |
| 29 | 32 | ||
| 30 | GLuint LoadShader(const char* source, GLenum type) { | 33 | GLuint LoadShader(std::string_view source, GLenum type) { |
| 31 | const char* debug_type = GetStageDebugName(type); | 34 | const std::string_view debug_type = StageDebugName(type); |
| 32 | const GLuint shader_id = glCreateShader(type); | 35 | const GLuint shader_id = glCreateShader(type); |
| 33 | glShaderSource(shader_id, 1, &source, nullptr); | 36 | |
| 37 | const GLchar* source_string = source.data(); | ||
| 38 | const GLint source_length = static_cast<GLint>(source.size()); | ||
| 39 | |||
| 40 | glShaderSource(shader_id, 1, &source_string, &source_length); | ||
| 34 | LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); | 41 | LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); |
| 35 | glCompileShader(shader_id); | 42 | glCompileShader(shader_id); |
| 36 | 43 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h index 03b7548c2..1b770532e 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.h +++ b/src/video_core/renderer_opengl/gl_shader_util.h | |||
| @@ -38,7 +38,7 @@ void LogShaderSource(T... shaders) { | |||
| 38 | * @param source String of the GLSL shader program | 38 | * @param source String of the GLSL shader program |
| 39 | * @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER) | 39 | * @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER) |
| 40 | */ | 40 | */ |
| 41 | GLuint LoadShader(const char* source, GLenum type); | 41 | GLuint LoadShader(std::string_view source, GLenum type); |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) | 44 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index c39663db7..b759c2dba 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | #include "core/perf_stats.h" | 21 | #include "core/perf_stats.h" |
| 22 | #include "core/settings.h" | 22 | #include "core/settings.h" |
| 23 | #include "core/telemetry_session.h" | 23 | #include "core/telemetry_session.h" |
| 24 | #include "video_core/host_shaders/opengl_present_frag.h" | ||
| 25 | #include "video_core/host_shaders/opengl_present_vert.h" | ||
| 24 | #include "video_core/morton.h" | 26 | #include "video_core/morton.h" |
| 25 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 27 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 26 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 28 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| @@ -44,46 +46,6 @@ struct Frame { | |||
| 44 | bool is_srgb{}; /// Framebuffer is sRGB or RGB | 46 | bool is_srgb{}; /// Framebuffer is sRGB or RGB |
| 45 | }; | 47 | }; |
| 46 | 48 | ||
| 47 | constexpr char VERTEX_SHADER[] = R"( | ||
| 48 | #version 430 core | ||
| 49 | |||
| 50 | out gl_PerVertex { | ||
| 51 | vec4 gl_Position; | ||
| 52 | }; | ||
| 53 | |||
| 54 | layout (location = 0) in vec2 vert_position; | ||
| 55 | layout (location = 1) in vec2 vert_tex_coord; | ||
| 56 | layout (location = 0) out vec2 frag_tex_coord; | ||
| 57 | |||
| 58 | // This is a truncated 3x3 matrix for 2D transformations: | ||
| 59 | // The upper-left 2x2 submatrix performs scaling/rotation/mirroring. | ||
| 60 | // The third column performs translation. | ||
| 61 | // The third row could be used for projection, which we don't need in 2D. It hence is assumed to | ||
| 62 | // implicitly be [0, 0, 1] | ||
| 63 | layout (location = 0) uniform mat3x2 modelview_matrix; | ||
| 64 | |||
| 65 | void main() { | ||
| 66 | // Multiply input position by the rotscale part of the matrix and then manually translate by | ||
| 67 | // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector | ||
| 68 | // to `vec3(vert_position.xy, 1.0)` | ||
| 69 | gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); | ||
| 70 | frag_tex_coord = vert_tex_coord; | ||
| 71 | } | ||
| 72 | )"; | ||
| 73 | |||
| 74 | constexpr char FRAGMENT_SHADER[] = R"( | ||
| 75 | #version 430 core | ||
| 76 | |||
| 77 | layout (location = 0) in vec2 frag_tex_coord; | ||
| 78 | layout (location = 0) out vec4 color; | ||
| 79 | |||
| 80 | layout (binding = 0) uniform sampler2D color_texture; | ||
| 81 | |||
| 82 | void main() { | ||
| 83 | color = vec4(texture(color_texture, frag_tex_coord).rgb, 1.0f); | ||
| 84 | } | ||
| 85 | )"; | ||
| 86 | |||
| 87 | constexpr GLint PositionLocation = 0; | 49 | constexpr GLint PositionLocation = 0; |
| 88 | constexpr GLint TexCoordLocation = 1; | 50 | constexpr GLint TexCoordLocation = 1; |
| 89 | constexpr GLint ModelViewMatrixLocation = 0; | 51 | constexpr GLint ModelViewMatrixLocation = 0; |
| @@ -461,10 +423,10 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 461 | 423 | ||
| 462 | // Create shader programs | 424 | // Create shader programs |
| 463 | OGLShader vertex_shader; | 425 | OGLShader vertex_shader; |
| 464 | vertex_shader.Create(VERTEX_SHADER, GL_VERTEX_SHADER); | 426 | vertex_shader.Create(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); |
| 465 | 427 | ||
| 466 | OGLShader fragment_shader; | 428 | OGLShader fragment_shader; |
| 467 | fragment_shader.Create(FRAGMENT_SHADER, GL_FRAGMENT_SHADER); | 429 | fragment_shader.Create(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER); |
| 468 | 430 | ||
| 469 | vertex_program.Create(true, false, vertex_shader.handle); | 431 | vertex_program.Create(true, false, vertex_shader.handle); |
| 470 | fragment_program.Create(true, false, fragment_shader.handle); | 432 | fragment_program.Create(true, false, fragment_shader.handle); |
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp index ebcfaa0e3..4205bd573 100644 --- a/src/video_core/renderer_vulkan/vk_device.cpp +++ b/src/video_core/renderer_vulkan/vk_device.cpp | |||
| @@ -380,6 +380,14 @@ bool VKDevice::Create() { | |||
| 380 | 380 | ||
| 381 | CollectTelemetryParameters(); | 381 | CollectTelemetryParameters(); |
| 382 | 382 | ||
| 383 | if (ext_extended_dynamic_state && driver_id == VK_DRIVER_ID_AMD_PROPRIETARY_KHR) { | ||
| 384 | // AMD's proprietary driver supports VK_EXT_extended_dynamic_state but the <stride> field | ||
| 385 | // seems to be bugged. Blacklisting it for now. | ||
| 386 | LOG_WARNING(Render_Vulkan, | ||
| 387 | "Blacklisting AMD proprietary from VK_EXT_extended_dynamic_state"); | ||
| 388 | ext_extended_dynamic_state = false; | ||
| 389 | } | ||
| 390 | |||
| 383 | graphics_queue = logical.GetQueue(graphics_family); | 391 | graphics_queue = logical.GetQueue(graphics_family); |
| 384 | present_queue = logical.GetQueue(present_family); | 392 | present_queue = logical.GetQueue(present_family); |
| 385 | 393 | ||
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 936f76195..ff1b52eab 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -1443,10 +1443,10 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) { | |||
| 1443 | } | 1443 | } |
| 1444 | 1444 | ||
| 1445 | void RasterizerVulkan::UpdatePrimitiveTopology(Tegra::Engines::Maxwell3D::Regs& regs) { | 1445 | void RasterizerVulkan::UpdatePrimitiveTopology(Tegra::Engines::Maxwell3D::Regs& regs) { |
| 1446 | if (!state_tracker.TouchPrimitiveTopology()) { | 1446 | const Maxwell::PrimitiveTopology primitive_topology = regs.draw.topology.Value(); |
| 1447 | if (!state_tracker.ChangePrimitiveTopology(primitive_topology)) { | ||
| 1447 | return; | 1448 | return; |
| 1448 | } | 1449 | } |
| 1449 | const Maxwell::PrimitiveTopology primitive_topology = regs.draw.topology.Value(); | ||
| 1450 | scheduler.Record([this, primitive_topology](vk::CommandBuffer cmdbuf) { | 1450 | scheduler.Record([this, primitive_topology](vk::CommandBuffer cmdbuf) { |
| 1451 | cmdbuf.SetPrimitiveTopologyEXT(MaxwellToVK::PrimitiveTopology(device, primitive_topology)); | 1451 | cmdbuf.SetPrimitiveTopologyEXT(MaxwellToVK::PrimitiveTopology(device, primitive_topology)); |
| 1452 | }); | 1452 | }); |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp index 9151d9fb1..4bd1009f9 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp | |||
| @@ -42,7 +42,6 @@ Flags MakeInvalidationFlags() { | |||
| 42 | flags[DepthWriteEnable] = true; | 42 | flags[DepthWriteEnable] = true; |
| 43 | flags[DepthCompareOp] = true; | 43 | flags[DepthCompareOp] = true; |
| 44 | flags[FrontFace] = true; | 44 | flags[FrontFace] = true; |
| 45 | flags[PrimitiveTopology] = true; | ||
| 46 | flags[StencilOp] = true; | 45 | flags[StencilOp] = true; |
| 47 | flags[StencilTestEnable] = true; | 46 | flags[StencilTestEnable] = true; |
| 48 | return flags; | 47 | return flags; |
| @@ -112,10 +111,6 @@ void SetupDirtyFrontFace(Tables& tables) { | |||
| 112 | table[OFF(screen_y_control)] = FrontFace; | 111 | table[OFF(screen_y_control)] = FrontFace; |
| 113 | } | 112 | } |
| 114 | 113 | ||
| 115 | void SetupDirtyPrimitiveTopology(Tables& tables) { | ||
| 116 | tables[0][OFF(draw.topology)] = PrimitiveTopology; | ||
| 117 | } | ||
| 118 | |||
| 119 | void SetupDirtyStencilOp(Tables& tables) { | 114 | void SetupDirtyStencilOp(Tables& tables) { |
| 120 | auto& table = tables[0]; | 115 | auto& table = tables[0]; |
| 121 | table[OFF(stencil_front_op_fail)] = StencilOp; | 116 | table[OFF(stencil_front_op_fail)] = StencilOp; |
| @@ -156,13 +151,13 @@ void StateTracker::Initialize() { | |||
| 156 | SetupDirtyDepthWriteEnable(tables); | 151 | SetupDirtyDepthWriteEnable(tables); |
| 157 | SetupDirtyDepthCompareOp(tables); | 152 | SetupDirtyDepthCompareOp(tables); |
| 158 | SetupDirtyFrontFace(tables); | 153 | SetupDirtyFrontFace(tables); |
| 159 | SetupDirtyPrimitiveTopology(tables); | ||
| 160 | SetupDirtyStencilOp(tables); | 154 | SetupDirtyStencilOp(tables); |
| 161 | SetupDirtyStencilTestEnable(tables); | 155 | SetupDirtyStencilTestEnable(tables); |
| 162 | } | 156 | } |
| 163 | 157 | ||
| 164 | void StateTracker::InvalidateCommandBufferState() { | 158 | void StateTracker::InvalidateCommandBufferState() { |
| 165 | system.GPU().Maxwell3D().dirty.flags |= invalidation_flags; | 159 | system.GPU().Maxwell3D().dirty.flags |= invalidation_flags; |
| 160 | current_topology = INVALID_TOPOLOGY; | ||
| 166 | } | 161 | } |
| 167 | 162 | ||
| 168 | } // namespace Vulkan | 163 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index 54ca0d6c6..13a6ce786 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h | |||
| @@ -32,7 +32,6 @@ enum : u8 { | |||
| 32 | DepthWriteEnable, | 32 | DepthWriteEnable, |
| 33 | DepthCompareOp, | 33 | DepthCompareOp, |
| 34 | FrontFace, | 34 | FrontFace, |
| 35 | PrimitiveTopology, | ||
| 36 | StencilOp, | 35 | StencilOp, |
| 37 | StencilTestEnable, | 36 | StencilTestEnable, |
| 38 | 37 | ||
| @@ -43,6 +42,8 @@ static_assert(Last <= std::numeric_limits<u8>::max()); | |||
| 43 | } // namespace Dirty | 42 | } // namespace Dirty |
| 44 | 43 | ||
| 45 | class StateTracker { | 44 | class StateTracker { |
| 45 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | ||
| 46 | |||
| 46 | public: | 47 | public: |
| 47 | explicit StateTracker(Core::System& system); | 48 | explicit StateTracker(Core::System& system); |
| 48 | 49 | ||
| @@ -102,10 +103,6 @@ public: | |||
| 102 | return Exchange(Dirty::FrontFace, false); | 103 | return Exchange(Dirty::FrontFace, false); |
| 103 | } | 104 | } |
| 104 | 105 | ||
| 105 | bool TouchPrimitiveTopology() { | ||
| 106 | return Exchange(Dirty::PrimitiveTopology, false); | ||
| 107 | } | ||
| 108 | |||
| 109 | bool TouchStencilOp() { | 106 | bool TouchStencilOp() { |
| 110 | return Exchange(Dirty::StencilOp, false); | 107 | return Exchange(Dirty::StencilOp, false); |
| 111 | } | 108 | } |
| @@ -114,7 +111,15 @@ public: | |||
| 114 | return Exchange(Dirty::StencilTestEnable, false); | 111 | return Exchange(Dirty::StencilTestEnable, false); |
| 115 | } | 112 | } |
| 116 | 113 | ||
| 114 | bool ChangePrimitiveTopology(Maxwell::PrimitiveTopology new_topology) { | ||
| 115 | const bool has_changed = current_topology != new_topology; | ||
| 116 | current_topology = new_topology; | ||
| 117 | return has_changed; | ||
| 118 | } | ||
| 119 | |||
| 117 | private: | 120 | private: |
| 121 | static constexpr auto INVALID_TOPOLOGY = static_cast<Maxwell::PrimitiveTopology>(~0u); | ||
| 122 | |||
| 118 | bool Exchange(std::size_t id, bool new_value) const noexcept { | 123 | bool Exchange(std::size_t id, bool new_value) const noexcept { |
| 119 | auto& flags = system.GPU().Maxwell3D().dirty.flags; | 124 | auto& flags = system.GPU().Maxwell3D().dirty.flags; |
| 120 | const bool is_dirty = flags[id]; | 125 | const bool is_dirty = flags[id]; |
| @@ -124,6 +129,7 @@ private: | |||
| 124 | 129 | ||
| 125 | Core::System& system; | 130 | Core::System& system; |
| 126 | Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; | 131 | Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; |
| 132 | Maxwell::PrimitiveTopology current_topology = INVALID_TOPOLOGY; | ||
| 127 | }; | 133 | }; |
| 128 | 134 | ||
| 129 | } // namespace Vulkan | 135 | } // namespace Vulkan |
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index e4739394d..e2bba88dd 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -386,7 +386,8 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 386 | break; | 386 | break; |
| 387 | } | 387 | } |
| 388 | case OpCode::Id::RED: { | 388 | case OpCode::Id::RED: { |
| 389 | UNIMPLEMENTED_IF_MSG(instr.red.type != GlobalAtomicType::U32); | 389 | UNIMPLEMENTED_IF_MSG(instr.red.type != GlobalAtomicType::U32, "type={}", |
| 390 | static_cast<int>(instr.red.type.Value())); | ||
| 390 | const auto [real_address, base_address, descriptor] = | 391 | const auto [real_address, base_address, descriptor] = |
| 391 | TrackGlobalMemory(bb, instr, true, true); | 392 | TrackGlobalMemory(bb, instr, true, true); |
| 392 | if (!real_address || !base_address) { | 393 | if (!real_address || !base_address) { |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 656096c9f..3ea4e5601 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -39,6 +39,9 @@ add_executable(yuzu | |||
| 39 | configuration/configure_debug.cpp | 39 | configuration/configure_debug.cpp |
| 40 | configuration/configure_debug.h | 40 | configuration/configure_debug.h |
| 41 | configuration/configure_debug.ui | 41 | configuration/configure_debug.ui |
| 42 | configuration/configure_debug_controller.cpp | ||
| 43 | configuration/configure_debug_controller.h | ||
| 44 | configuration/configure_debug_controller.ui | ||
| 42 | configuration/configure_dialog.cpp | 45 | configuration/configure_dialog.cpp |
| 43 | configuration/configure_dialog.h | 46 | configuration/configure_dialog.h |
| 44 | configuration/configure_filesystem.cpp | 47 | configuration/configure_filesystem.cpp |
| @@ -62,9 +65,12 @@ add_executable(yuzu | |||
| 62 | configuration/configure_input_player.cpp | 65 | configuration/configure_input_player.cpp |
| 63 | configuration/configure_input_player.h | 66 | configuration/configure_input_player.h |
| 64 | configuration/configure_input_player.ui | 67 | configuration/configure_input_player.ui |
| 65 | configuration/configure_input_simple.cpp | 68 | configuration/configure_input_advanced.cpp |
| 66 | configuration/configure_input_simple.h | 69 | configuration/configure_input_advanced.h |
| 67 | configuration/configure_input_simple.ui | 70 | configuration/configure_input_advanced.ui |
| 71 | configuration/configure_motion_touch.cpp | ||
| 72 | configuration/configure_motion_touch.h | ||
| 73 | configuration/configure_motion_touch.ui | ||
| 68 | configuration/configure_mouse_advanced.cpp | 74 | configuration/configure_mouse_advanced.cpp |
| 69 | configuration/configure_mouse_advanced.h | 75 | configuration/configure_mouse_advanced.h |
| 70 | configuration/configure_mouse_advanced.ui | 76 | configuration/configure_mouse_advanced.ui |
| @@ -83,9 +89,13 @@ add_executable(yuzu | |||
| 83 | configuration/configure_system.cpp | 89 | configuration/configure_system.cpp |
| 84 | configuration/configure_system.h | 90 | configuration/configure_system.h |
| 85 | configuration/configure_system.ui | 91 | configuration/configure_system.ui |
| 92 | configuration/configure_touch_from_button.cpp | ||
| 93 | configuration/configure_touch_from_button.h | ||
| 94 | configuration/configure_touch_from_button.ui | ||
| 86 | configuration/configure_touchscreen_advanced.cpp | 95 | configuration/configure_touchscreen_advanced.cpp |
| 87 | configuration/configure_touchscreen_advanced.h | 96 | configuration/configure_touchscreen_advanced.h |
| 88 | configuration/configure_touchscreen_advanced.ui | 97 | configuration/configure_touchscreen_advanced.ui |
| 98 | configuration/configure_touch_widget.h | ||
| 89 | configuration/configure_ui.cpp | 99 | configuration/configure_ui.cpp |
| 90 | configuration/configure_ui.h | 100 | configuration/configure_ui.h |
| 91 | configuration/configure_ui.ui | 101 | configuration/configure_ui.ui |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 8fc322b30..21707e451 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -304,8 +304,9 @@ static Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* | |||
| 304 | return wsi; | 304 | return wsi; |
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread_) | 307 | GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_, |
| 308 | : QWidget(parent_), emu_thread(emu_thread_) { | 308 | std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_) |
| 309 | : QWidget(parent), emu_thread(emu_thread_), input_subsystem{std::move(input_subsystem_)} { | ||
| 309 | setWindowTitle(QStringLiteral("yuzu %1 | %2-%3") | 310 | setWindowTitle(QStringLiteral("yuzu %1 | %2-%3") |
| 310 | .arg(QString::fromUtf8(Common::g_build_name), | 311 | .arg(QString::fromUtf8(Common::g_build_name), |
| 311 | QString::fromUtf8(Common::g_scm_branch), | 312 | QString::fromUtf8(Common::g_scm_branch), |
| @@ -314,15 +315,15 @@ GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread_) | |||
| 314 | auto layout = new QHBoxLayout(this); | 315 | auto layout = new QHBoxLayout(this); |
| 315 | layout->setMargin(0); | 316 | layout->setMargin(0); |
| 316 | setLayout(layout); | 317 | setLayout(layout); |
| 317 | InputCommon::Init(); | 318 | input_subsystem->Initialize(); |
| 318 | 319 | ||
| 319 | this->setMouseTracking(true); | 320 | this->setMouseTracking(true); |
| 320 | 321 | ||
| 321 | connect(this, &GRenderWindow::FirstFrameDisplayed, parent_, &GMainWindow::OnLoadComplete); | 322 | connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); |
| 322 | } | 323 | } |
| 323 | 324 | ||
| 324 | GRenderWindow::~GRenderWindow() { | 325 | GRenderWindow::~GRenderWindow() { |
| 325 | InputCommon::Shutdown(); | 326 | input_subsystem->Shutdown(); |
| 326 | } | 327 | } |
| 327 | 328 | ||
| 328 | void GRenderWindow::PollEvents() { | 329 | void GRenderWindow::PollEvents() { |
| @@ -391,11 +392,11 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { | |||
| 391 | } | 392 | } |
| 392 | 393 | ||
| 393 | void GRenderWindow::keyPressEvent(QKeyEvent* event) { | 394 | void GRenderWindow::keyPressEvent(QKeyEvent* event) { |
| 394 | InputCommon::GetKeyboard()->PressKey(event->key()); | 395 | input_subsystem->GetKeyboard()->PressKey(event->key()); |
| 395 | } | 396 | } |
| 396 | 397 | ||
| 397 | void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { | 398 | void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { |
| 398 | InputCommon::GetKeyboard()->ReleaseKey(event->key()); | 399 | input_subsystem->GetKeyboard()->ReleaseKey(event->key()); |
| 399 | } | 400 | } |
| 400 | 401 | ||
| 401 | void GRenderWindow::mousePressEvent(QMouseEvent* event) { | 402 | void GRenderWindow::mousePressEvent(QMouseEvent* event) { |
| @@ -409,7 +410,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) { | |||
| 409 | const auto [x, y] = ScaleTouch(pos); | 410 | const auto [x, y] = ScaleTouch(pos); |
| 410 | this->TouchPressed(x, y); | 411 | this->TouchPressed(x, y); |
| 411 | } else if (event->button() == Qt::RightButton) { | 412 | } else if (event->button() == Qt::RightButton) { |
| 412 | InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y()); | 413 | input_subsystem->GetMotionEmu()->BeginTilt(pos.x(), pos.y()); |
| 413 | } | 414 | } |
| 414 | QWidget::mousePressEvent(event); | 415 | QWidget::mousePressEvent(event); |
| 415 | } | 416 | } |
| @@ -423,7 +424,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { | |||
| 423 | auto pos = event->pos(); | 424 | auto pos = event->pos(); |
| 424 | const auto [x, y] = ScaleTouch(pos); | 425 | const auto [x, y] = ScaleTouch(pos); |
| 425 | this->TouchMoved(x, y); | 426 | this->TouchMoved(x, y); |
| 426 | InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y()); | 427 | input_subsystem->GetMotionEmu()->Tilt(pos.x(), pos.y()); |
| 427 | QWidget::mouseMoveEvent(event); | 428 | QWidget::mouseMoveEvent(event); |
| 428 | } | 429 | } |
| 429 | 430 | ||
| @@ -436,7 +437,7 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { | |||
| 436 | if (event->button() == Qt::LeftButton) { | 437 | if (event->button() == Qt::LeftButton) { |
| 437 | this->TouchReleased(); | 438 | this->TouchReleased(); |
| 438 | } else if (event->button() == Qt::RightButton) { | 439 | } else if (event->button() == Qt::RightButton) { |
| 439 | InputCommon::GetMotionEmu()->EndTilt(); | 440 | input_subsystem->GetMotionEmu()->EndTilt(); |
| 440 | } | 441 | } |
| 441 | } | 442 | } |
| 442 | 443 | ||
| @@ -451,7 +452,7 @@ void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) { | |||
| 451 | int active_points = 0; | 452 | int active_points = 0; |
| 452 | 453 | ||
| 453 | // average all active touch points | 454 | // average all active touch points |
| 454 | for (const auto tp : event->touchPoints()) { | 455 | for (const auto& tp : event->touchPoints()) { |
| 455 | if (tp.state() & (Qt::TouchPointPressed | Qt::TouchPointMoved | Qt::TouchPointStationary)) { | 456 | if (tp.state() & (Qt::TouchPointPressed | Qt::TouchPointMoved | Qt::TouchPointStationary)) { |
| 456 | active_points++; | 457 | active_points++; |
| 457 | pos += tp.pos(); | 458 | pos += tp.pos(); |
| @@ -485,7 +486,7 @@ bool GRenderWindow::event(QEvent* event) { | |||
| 485 | 486 | ||
| 486 | void GRenderWindow::focusOutEvent(QFocusEvent* event) { | 487 | void GRenderWindow::focusOutEvent(QFocusEvent* event) { |
| 487 | QWidget::focusOutEvent(event); | 488 | QWidget::focusOutEvent(event); |
| 488 | InputCommon::GetKeyboard()->ReleaseAllKeys(); | 489 | input_subsystem->GetKeyboard()->ReleaseAllKeys(); |
| 489 | } | 490 | } |
| 490 | 491 | ||
| 491 | void GRenderWindow::resizeEvent(QResizeEvent* event) { | 492 | void GRenderWindow::resizeEvent(QResizeEvent* event) { |
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 6c59b4d5c..ca35cf831 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <condition_variable> | 8 | #include <condition_variable> |
| 9 | #include <memory> | ||
| 9 | #include <mutex> | 10 | #include <mutex> |
| 10 | 11 | ||
| 11 | #include <QImage> | 12 | #include <QImage> |
| @@ -23,6 +24,10 @@ class QKeyEvent; | |||
| 23 | class QTouchEvent; | 24 | class QTouchEvent; |
| 24 | class QStringList; | 25 | class QStringList; |
| 25 | 26 | ||
| 27 | namespace InputCommon { | ||
| 28 | class InputSubsystem; | ||
| 29 | } | ||
| 30 | |||
| 26 | namespace VideoCore { | 31 | namespace VideoCore { |
| 27 | enum class LoadCallbackStage; | 32 | enum class LoadCallbackStage; |
| 28 | } | 33 | } |
| @@ -121,7 +126,8 @@ class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow { | |||
| 121 | Q_OBJECT | 126 | Q_OBJECT |
| 122 | 127 | ||
| 123 | public: | 128 | public: |
| 124 | GRenderWindow(GMainWindow* parent, EmuThread* emu_thread); | 129 | explicit GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_, |
| 130 | std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_); | ||
| 125 | ~GRenderWindow() override; | 131 | ~GRenderWindow() override; |
| 126 | 132 | ||
| 127 | // EmuWindow implementation. | 133 | // EmuWindow implementation. |
| @@ -183,6 +189,7 @@ private: | |||
| 183 | QStringList GetUnsupportedGLExtensions() const; | 189 | QStringList GetUnsupportedGLExtensions() const; |
| 184 | 190 | ||
| 185 | EmuThread* emu_thread; | 191 | EmuThread* emu_thread; |
| 192 | std::shared_ptr<InputCommon::InputSubsystem> input_subsystem; | ||
| 186 | 193 | ||
| 187 | // Main context that will be shared with all other contexts that are requested. | 194 | // Main context that will be shared with all other contexts that are requested. |
| 188 | // If this is used in a shared context setting, then this should not be used directly, but | 195 | // If this is used in a shared context setting, then this should not be used directly, but |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 7af974d8d..2bc55a26a 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | #include <QKeySequence> | 6 | #include <QKeySequence> |
| 7 | #include <QSettings> | 7 | #include <QSettings> |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | #include "configure_input_simple.h" | ||
| 10 | #include "core/hle/service/acc/profile_manager.h" | 9 | #include "core/hle/service/acc/profile_manager.h" |
| 11 | #include "core/hle/service/hid/controllers/npad.h" | 10 | #include "core/hle/service/hid/controllers/npad.h" |
| 12 | #include "input_common/main.h" | 11 | #include "input_common/main.h" |
| @@ -32,29 +31,31 @@ Config::~Config() { | |||
| 32 | } | 31 | } |
| 33 | 32 | ||
| 34 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { | 33 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { |
| 35 | Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q, | 34 | Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q, |
| 36 | Qt::Key_W, Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T, | 35 | Qt::Key_W, Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T, |
| 37 | Qt::Key_H, Qt::Key_G, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_Down, Qt::Key_J, | 36 | Qt::Key_H, Qt::Key_G, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V, |
| 38 | Qt::Key_I, Qt::Key_L, Qt::Key_K, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V, | ||
| 39 | }; | 37 | }; |
| 40 | 38 | ||
| 41 | const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ | 39 | const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ |
| 42 | { | 40 | { |
| 43 | Qt::Key_Up, | 41 | Qt::Key_Up, |
| 44 | Qt::Key_Down, | 42 | Qt::Key_Down, |
| 45 | Qt::Key_Left, | 43 | Qt::Key_Left, |
| 46 | Qt::Key_Right, | 44 | Qt::Key_Right, |
| 47 | Qt::Key_E, | ||
| 48 | }, | 45 | }, |
| 49 | { | 46 | { |
| 50 | Qt::Key_I, | 47 | Qt::Key_I, |
| 51 | Qt::Key_K, | 48 | Qt::Key_K, |
| 52 | Qt::Key_J, | 49 | Qt::Key_J, |
| 53 | Qt::Key_L, | 50 | Qt::Key_L, |
| 54 | Qt::Key_R, | ||
| 55 | }, | 51 | }, |
| 56 | }}; | 52 | }}; |
| 57 | 53 | ||
| 54 | const std::array<int, 2> Config::default_stick_mod = { | ||
| 55 | Qt::Key_E, | ||
| 56 | Qt::Key_R, | ||
| 57 | }; | ||
| 58 | |||
| 58 | const std::array<int, Settings::NativeMouseButton::NumMouseButtons> Config::default_mouse_buttons = | 59 | const std::array<int, Settings::NativeMouseButton::NumMouseButtons> Config::default_mouse_buttons = |
| 59 | { | 60 | { |
| 60 | Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal, | 61 | Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal, |
| @@ -243,10 +244,10 @@ void Config::ReadPlayerValues() { | |||
| 243 | player.connected = | 244 | player.connected = |
| 244 | ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool(); | 245 | ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool(); |
| 245 | 246 | ||
| 246 | player.type = static_cast<Settings::ControllerType>( | 247 | player.controller_type = static_cast<Settings::ControllerType>( |
| 247 | qt_config | 248 | qt_config |
| 248 | ->value(QStringLiteral("player_%1_type").arg(p), | 249 | ->value(QStringLiteral("player_%1_type").arg(p), |
| 249 | static_cast<u8>(Settings::ControllerType::DualJoycon)) | 250 | static_cast<u8>(Settings::ControllerType::ProController)) |
| 250 | .toUInt()); | 251 | .toUInt()); |
| 251 | 252 | ||
| 252 | player.body_color_left = qt_config | 253 | player.body_color_left = qt_config |
| @@ -286,7 +287,7 @@ void Config::ReadPlayerValues() { | |||
| 286 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 287 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 287 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 288 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 288 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 289 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 289 | default_analogs[i][3], default_analogs[i][4], 0.5f); | 290 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 290 | auto& player_analogs = player.analogs[i]; | 291 | auto& player_analogs = player.analogs[i]; |
| 291 | 292 | ||
| 292 | player_analogs = qt_config | 293 | player_analogs = qt_config |
| @@ -300,12 +301,6 @@ void Config::ReadPlayerValues() { | |||
| 300 | } | 301 | } |
| 301 | } | 302 | } |
| 302 | } | 303 | } |
| 303 | |||
| 304 | std::stable_partition( | ||
| 305 | Settings::values.players.begin(), | ||
| 306 | Settings::values.players.begin() + | ||
| 307 | Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD), | ||
| 308 | [](const auto& player) { return player.connected; }); | ||
| 309 | } | 304 | } |
| 310 | 305 | ||
| 311 | void Config::ReadDebugValues() { | 306 | void Config::ReadDebugValues() { |
| @@ -330,7 +325,7 @@ void Config::ReadDebugValues() { | |||
| 330 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 325 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 331 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 326 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 332 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 327 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 333 | default_analogs[i][3], default_analogs[i][4], 0.5f); | 328 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 334 | auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; | 329 | auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; |
| 335 | 330 | ||
| 336 | debug_pad_analogs = qt_config | 331 | debug_pad_analogs = qt_config |
| @@ -397,13 +392,6 @@ void Config::ReadTouchscreenValues() { | |||
| 397 | ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt(); | 392 | ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt(); |
| 398 | } | 393 | } |
| 399 | 394 | ||
| 400 | void Config::ApplyDefaultProfileIfInputInvalid() { | ||
| 401 | if (!std::any_of(Settings::values.players.begin(), Settings::values.players.end(), | ||
| 402 | [](const Settings::PlayerInput& in) { return in.connected; })) { | ||
| 403 | ApplyInputProfileConfiguration(UISettings::values.profile_index); | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 407 | void Config::ReadAudioValues() { | 395 | void Config::ReadAudioValues() { |
| 408 | qt_config->beginGroup(QStringLiteral("Audio")); | 396 | qt_config->beginGroup(QStringLiteral("Audio")); |
| 409 | 397 | ||
| @@ -432,12 +420,64 @@ void Config::ReadControlValues() { | |||
| 432 | ReadKeyboardValues(); | 420 | ReadKeyboardValues(); |
| 433 | ReadMouseValues(); | 421 | ReadMouseValues(); |
| 434 | ReadTouchscreenValues(); | 422 | ReadTouchscreenValues(); |
| 423 | ReadMotionTouchValues(); | ||
| 424 | |||
| 425 | Settings::values.vibration_enabled = | ||
| 426 | ReadSetting(QStringLiteral("vibration_enabled"), true).toBool(); | ||
| 427 | Settings::values.use_docked_mode = | ||
| 428 | ReadSetting(QStringLiteral("use_docked_mode"), false).toBool(); | ||
| 429 | |||
| 430 | qt_config->endGroup(); | ||
| 431 | } | ||
| 432 | |||
| 433 | void Config::ReadMotionTouchValues() { | ||
| 434 | int num_touch_from_button_maps = | ||
| 435 | qt_config->beginReadArray(QStringLiteral("touch_from_button_maps")); | ||
| 436 | |||
| 437 | if (num_touch_from_button_maps > 0) { | ||
| 438 | const auto append_touch_from_button_map = [this] { | ||
| 439 | Settings::TouchFromButtonMap map; | ||
| 440 | map.name = ReadSetting(QStringLiteral("name"), QStringLiteral("default")) | ||
| 441 | .toString() | ||
| 442 | .toStdString(); | ||
| 443 | const int num_touch_maps = qt_config->beginReadArray(QStringLiteral("entries")); | ||
| 444 | map.buttons.reserve(num_touch_maps); | ||
| 445 | for (int i = 0; i < num_touch_maps; i++) { | ||
| 446 | qt_config->setArrayIndex(i); | ||
| 447 | std::string touch_mapping = | ||
| 448 | ReadSetting(QStringLiteral("bind")).toString().toStdString(); | ||
| 449 | map.buttons.emplace_back(std::move(touch_mapping)); | ||
| 450 | } | ||
| 451 | qt_config->endArray(); // entries | ||
| 452 | Settings::values.touch_from_button_maps.emplace_back(std::move(map)); | ||
| 453 | }; | ||
| 454 | |||
| 455 | for (int i = 0; i < num_touch_from_button_maps; ++i) { | ||
| 456 | qt_config->setArrayIndex(i); | ||
| 457 | append_touch_from_button_map(); | ||
| 458 | } | ||
| 459 | } else { | ||
| 460 | Settings::values.touch_from_button_maps.emplace_back( | ||
| 461 | Settings::TouchFromButtonMap{"default", {}}); | ||
| 462 | num_touch_from_button_maps = 1; | ||
| 463 | } | ||
| 464 | qt_config->endArray(); | ||
| 435 | 465 | ||
| 436 | Settings::values.motion_device = | 466 | Settings::values.motion_device = |
| 437 | ReadSetting(QStringLiteral("motion_device"), | 467 | ReadSetting(QStringLiteral("motion_device"), |
| 438 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")) | 468 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")) |
| 439 | .toString() | 469 | .toString() |
| 440 | .toStdString(); | 470 | .toStdString(); |
| 471 | Settings::values.touch_device = | ||
| 472 | ReadSetting(QStringLiteral("touch_device"), QStringLiteral("engine:emu_window")) | ||
| 473 | .toString() | ||
| 474 | .toStdString(); | ||
| 475 | Settings::values.use_touch_from_button = | ||
| 476 | ReadSetting(QStringLiteral("use_touch_from_button"), false).toBool(); | ||
| 477 | Settings::values.touch_from_button_map_index = | ||
| 478 | ReadSetting(QStringLiteral("touch_from_button_map"), 0).toInt(); | ||
| 479 | Settings::values.touch_from_button_map_index = | ||
| 480 | std::clamp(Settings::values.touch_from_button_map_index, 0, num_touch_from_button_maps - 1); | ||
| 441 | Settings::values.udp_input_address = | 481 | Settings::values.udp_input_address = |
| 442 | ReadSetting(QStringLiteral("udp_input_address"), | 482 | ReadSetting(QStringLiteral("udp_input_address"), |
| 443 | QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_ADDR)) | 483 | QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_ADDR)) |
| @@ -448,10 +488,6 @@ void Config::ReadControlValues() { | |||
| 448 | .toInt()); | 488 | .toInt()); |
| 449 | Settings::values.udp_pad_index = | 489 | Settings::values.udp_pad_index = |
| 450 | static_cast<u8>(ReadSetting(QStringLiteral("udp_pad_index"), 0).toUInt()); | 490 | static_cast<u8>(ReadSetting(QStringLiteral("udp_pad_index"), 0).toUInt()); |
| 451 | Settings::values.use_docked_mode = | ||
| 452 | ReadSetting(QStringLiteral("use_docked_mode"), false).toBool(); | ||
| 453 | |||
| 454 | qt_config->endGroup(); | ||
| 455 | } | 491 | } |
| 456 | 492 | ||
| 457 | void Config::ReadCoreValues() { | 493 | void Config::ReadCoreValues() { |
| @@ -501,7 +537,7 @@ void Config::ReadDataStorageValues() { | |||
| 501 | Settings::values.gamecard_current_game = | 537 | Settings::values.gamecard_current_game = |
| 502 | ReadSetting(QStringLiteral("gamecard_current_game"), false).toBool(); | 538 | ReadSetting(QStringLiteral("gamecard_current_game"), false).toBool(); |
| 503 | Settings::values.gamecard_path = | 539 | Settings::values.gamecard_path = |
| 504 | ReadSetting(QStringLiteral("gamecard_path"), QStringLiteral("")).toString().toStdString(); | 540 | ReadSetting(QStringLiteral("gamecard_path"), QString{}).toString().toStdString(); |
| 505 | 541 | ||
| 506 | qt_config->endGroup(); | 542 | qt_config->endGroup(); |
| 507 | } | 543 | } |
| @@ -515,7 +551,7 @@ void Config::ReadDebuggingValues() { | |||
| 515 | Settings::values.use_gdbstub = ReadSetting(QStringLiteral("use_gdbstub"), false).toBool(); | 551 | Settings::values.use_gdbstub = ReadSetting(QStringLiteral("use_gdbstub"), false).toBool(); |
| 516 | Settings::values.gdbstub_port = ReadSetting(QStringLiteral("gdbstub_port"), 24689).toInt(); | 552 | Settings::values.gdbstub_port = ReadSetting(QStringLiteral("gdbstub_port"), 24689).toInt(); |
| 517 | Settings::values.program_args = | 553 | Settings::values.program_args = |
| 518 | ReadSetting(QStringLiteral("program_args"), QStringLiteral("")).toString().toStdString(); | 554 | ReadSetting(QStringLiteral("program_args"), QString{}).toString().toStdString(); |
| 519 | Settings::values.dump_exefs = ReadSetting(QStringLiteral("dump_exefs"), false).toBool(); | 555 | Settings::values.dump_exefs = ReadSetting(QStringLiteral("dump_exefs"), false).toBool(); |
| 520 | Settings::values.dump_nso = ReadSetting(QStringLiteral("dump_nso"), false).toBool(); | 556 | Settings::values.dump_nso = ReadSetting(QStringLiteral("dump_nso"), false).toBool(); |
| 521 | Settings::values.reporting_services = | 557 | Settings::values.reporting_services = |
| @@ -548,8 +584,7 @@ void Config::ReadDisabledAddOnValues() { | |||
| 548 | const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled")); | 584 | const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled")); |
| 549 | for (int j = 0; j < d_size; ++j) { | 585 | for (int j = 0; j < d_size; ++j) { |
| 550 | qt_config->setArrayIndex(j); | 586 | qt_config->setArrayIndex(j); |
| 551 | out.push_back( | 587 | out.push_back(ReadSetting(QStringLiteral("d"), QString{}).toString().toStdString()); |
| 552 | ReadSetting(QStringLiteral("d"), QStringLiteral("")).toString().toStdString()); | ||
| 553 | } | 588 | } |
| 554 | qt_config->endArray(); | 589 | qt_config->endArray(); |
| 555 | Settings::values.disabled_addons.insert_or_assign(title_id, out); | 590 | Settings::values.disabled_addons.insert_or_assign(title_id, out); |
| @@ -788,14 +823,11 @@ void Config::ReadUIValues() { | |||
| 788 | UISettings::values.first_start = ReadSetting(QStringLiteral("firstStart"), true).toBool(); | 823 | UISettings::values.first_start = ReadSetting(QStringLiteral("firstStart"), true).toBool(); |
| 789 | UISettings::values.callout_flags = ReadSetting(QStringLiteral("calloutFlags"), 0).toUInt(); | 824 | UISettings::values.callout_flags = ReadSetting(QStringLiteral("calloutFlags"), 0).toUInt(); |
| 790 | UISettings::values.show_console = ReadSetting(QStringLiteral("showConsole"), false).toBool(); | 825 | UISettings::values.show_console = ReadSetting(QStringLiteral("showConsole"), false).toBool(); |
| 791 | UISettings::values.profile_index = ReadSetting(QStringLiteral("profileIndex"), 0).toUInt(); | ||
| 792 | UISettings::values.pause_when_in_background = | 826 | UISettings::values.pause_when_in_background = |
| 793 | ReadSetting(QStringLiteral("pauseWhenInBackground"), false).toBool(); | 827 | ReadSetting(QStringLiteral("pauseWhenInBackground"), false).toBool(); |
| 794 | UISettings::values.hide_mouse = | 828 | UISettings::values.hide_mouse = |
| 795 | ReadSetting(QStringLiteral("hideInactiveMouse"), false).toBool(); | 829 | ReadSetting(QStringLiteral("hideInactiveMouse"), false).toBool(); |
| 796 | 830 | ||
| 797 | ApplyDefaultProfileIfInputInvalid(); | ||
| 798 | |||
| 799 | qt_config->endGroup(); | 831 | qt_config->endGroup(); |
| 800 | } | 832 | } |
| 801 | 833 | ||
| @@ -869,8 +901,9 @@ void Config::SavePlayerValues() { | |||
| 869 | const auto& player = Settings::values.players[p]; | 901 | const auto& player = Settings::values.players[p]; |
| 870 | 902 | ||
| 871 | WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false); | 903 | WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false); |
| 872 | WriteSetting(QStringLiteral("player_%1_type").arg(p), static_cast<u8>(player.type), | 904 | WriteSetting(QStringLiteral("player_%1_type").arg(p), |
| 873 | static_cast<u8>(Settings::ControllerType::DualJoycon)); | 905 | static_cast<u8>(player.controller_type), |
| 906 | static_cast<u8>(Settings::ControllerType::ProController)); | ||
| 874 | 907 | ||
| 875 | WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left, | 908 | WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left, |
| 876 | Settings::JOYCON_BODY_NEON_BLUE); | 909 | Settings::JOYCON_BODY_NEON_BLUE); |
| @@ -892,7 +925,7 @@ void Config::SavePlayerValues() { | |||
| 892 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 925 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 893 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 926 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 894 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 927 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 895 | default_analogs[i][3], default_analogs[i][4], 0.5f); | 928 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 896 | WriteSetting(QStringLiteral("player_%1_").arg(p) + | 929 | WriteSetting(QStringLiteral("player_%1_").arg(p) + |
| 897 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), | 930 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), |
| 898 | QString::fromStdString(player.analogs[i]), | 931 | QString::fromStdString(player.analogs[i]), |
| @@ -913,7 +946,7 @@ void Config::SaveDebugValues() { | |||
| 913 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 946 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 914 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 947 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 915 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 948 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 916 | default_analogs[i][3], default_analogs[i][4], 0.5f); | 949 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 917 | WriteSetting(QStringLiteral("debug_pad_") + | 950 | WriteSetting(QStringLiteral("debug_pad_") + |
| 918 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), | 951 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), |
| 919 | QString::fromStdString(Settings::values.debug_pad_analogs[i]), | 952 | QString::fromStdString(Settings::values.debug_pad_analogs[i]), |
| @@ -947,6 +980,43 @@ void Config::SaveTouchscreenValues() { | |||
| 947 | WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); | 980 | WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); |
| 948 | } | 981 | } |
| 949 | 982 | ||
| 983 | void Config::SaveMotionTouchValues() { | ||
| 984 | WriteSetting(QStringLiteral("motion_device"), | ||
| 985 | QString::fromStdString(Settings::values.motion_device), | ||
| 986 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); | ||
| 987 | WriteSetting(QStringLiteral("touch_device"), | ||
| 988 | QString::fromStdString(Settings::values.touch_device), | ||
| 989 | QStringLiteral("engine:emu_window")); | ||
| 990 | WriteSetting(QStringLiteral("use_touch_from_button"), Settings::values.use_touch_from_button, | ||
| 991 | false); | ||
| 992 | WriteSetting(QStringLiteral("touch_from_button_map"), | ||
| 993 | Settings::values.touch_from_button_map_index, 0); | ||
| 994 | WriteSetting(QStringLiteral("udp_input_address"), | ||
| 995 | QString::fromStdString(Settings::values.udp_input_address), | ||
| 996 | QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_ADDR)); | ||
| 997 | WriteSetting(QStringLiteral("udp_input_port"), Settings::values.udp_input_port, | ||
| 998 | InputCommon::CemuhookUDP::DEFAULT_PORT); | ||
| 999 | WriteSetting(QStringLiteral("udp_pad_index"), Settings::values.udp_pad_index, 0); | ||
| 1000 | |||
| 1001 | qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); | ||
| 1002 | for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { | ||
| 1003 | qt_config->setArrayIndex(static_cast<int>(p)); | ||
| 1004 | WriteSetting(QStringLiteral("name"), | ||
| 1005 | QString::fromStdString(Settings::values.touch_from_button_maps[p].name), | ||
| 1006 | QStringLiteral("default")); | ||
| 1007 | qt_config->beginWriteArray(QStringLiteral("entries")); | ||
| 1008 | for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size(); | ||
| 1009 | ++q) { | ||
| 1010 | qt_config->setArrayIndex(static_cast<int>(q)); | ||
| 1011 | WriteSetting( | ||
| 1012 | QStringLiteral("bind"), | ||
| 1013 | QString::fromStdString(Settings::values.touch_from_button_maps[p].buttons[q])); | ||
| 1014 | } | ||
| 1015 | qt_config->endArray(); | ||
| 1016 | } | ||
| 1017 | qt_config->endArray(); | ||
| 1018 | } | ||
| 1019 | |||
| 950 | void Config::SaveValues() { | 1020 | void Config::SaveValues() { |
| 951 | if (global) { | 1021 | if (global) { |
| 952 | SaveControlValues(); | 1022 | SaveControlValues(); |
| @@ -989,17 +1059,16 @@ void Config::SaveControlValues() { | |||
| 989 | SaveDebugValues(); | 1059 | SaveDebugValues(); |
| 990 | SaveMouseValues(); | 1060 | SaveMouseValues(); |
| 991 | SaveTouchscreenValues(); | 1061 | SaveTouchscreenValues(); |
| 1062 | SaveMotionTouchValues(); | ||
| 992 | 1063 | ||
| 1064 | WriteSetting(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, true); | ||
| 993 | WriteSetting(QStringLiteral("motion_device"), | 1065 | WriteSetting(QStringLiteral("motion_device"), |
| 994 | QString::fromStdString(Settings::values.motion_device), | 1066 | QString::fromStdString(Settings::values.motion_device), |
| 995 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); | 1067 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); |
| 1068 | WriteSetting(QStringLiteral("touch_device"), | ||
| 1069 | QString::fromStdString(Settings::values.touch_device), | ||
| 1070 | QStringLiteral("engine:emu_window")); | ||
| 996 | WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); | 1071 | WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); |
| 997 | WriteSetting(QStringLiteral("udp_input_address"), | ||
| 998 | QString::fromStdString(Settings::values.udp_input_address), | ||
| 999 | QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_ADDR)); | ||
| 1000 | WriteSetting(QStringLiteral("udp_input_port"), Settings::values.udp_input_port, | ||
| 1001 | InputCommon::CemuhookUDP::DEFAULT_PORT); | ||
| 1002 | WriteSetting(QStringLiteral("udp_pad_index"), Settings::values.udp_pad_index, 0); | ||
| 1003 | WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); | 1072 | WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); |
| 1004 | 1073 | ||
| 1005 | qt_config->endGroup(); | 1074 | qt_config->endGroup(); |
| @@ -1036,7 +1105,7 @@ void Config::SaveDataStorageValues() { | |||
| 1036 | WriteSetting(QStringLiteral("gamecard_current_game"), Settings::values.gamecard_current_game, | 1105 | WriteSetting(QStringLiteral("gamecard_current_game"), Settings::values.gamecard_current_game, |
| 1037 | false); | 1106 | false); |
| 1038 | WriteSetting(QStringLiteral("gamecard_path"), | 1107 | WriteSetting(QStringLiteral("gamecard_path"), |
| 1039 | QString::fromStdString(Settings::values.gamecard_path), QStringLiteral("")); | 1108 | QString::fromStdString(Settings::values.gamecard_path), QString{}); |
| 1040 | 1109 | ||
| 1041 | qt_config->endGroup(); | 1110 | qt_config->endGroup(); |
| 1042 | } | 1111 | } |
| @@ -1049,7 +1118,7 @@ void Config::SaveDebuggingValues() { | |||
| 1049 | WriteSetting(QStringLiteral("use_gdbstub"), Settings::values.use_gdbstub, false); | 1118 | WriteSetting(QStringLiteral("use_gdbstub"), Settings::values.use_gdbstub, false); |
| 1050 | WriteSetting(QStringLiteral("gdbstub_port"), Settings::values.gdbstub_port, 24689); | 1119 | WriteSetting(QStringLiteral("gdbstub_port"), Settings::values.gdbstub_port, 24689); |
| 1051 | WriteSetting(QStringLiteral("program_args"), | 1120 | WriteSetting(QStringLiteral("program_args"), |
| 1052 | QString::fromStdString(Settings::values.program_args), QStringLiteral("")); | 1121 | QString::fromStdString(Settings::values.program_args), QString{}); |
| 1053 | WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false); | 1122 | WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false); |
| 1054 | WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false); | 1123 | WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false); |
| 1055 | WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false); | 1124 | WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false); |
| @@ -1076,8 +1145,7 @@ void Config::SaveDisabledAddOnValues() { | |||
| 1076 | qt_config->beginWriteArray(QStringLiteral("disabled")); | 1145 | qt_config->beginWriteArray(QStringLiteral("disabled")); |
| 1077 | for (std::size_t j = 0; j < elem.second.size(); ++j) { | 1146 | for (std::size_t j = 0; j < elem.second.size(); ++j) { |
| 1078 | qt_config->setArrayIndex(static_cast<int>(j)); | 1147 | qt_config->setArrayIndex(static_cast<int>(j)); |
| 1079 | WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]), | 1148 | WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]), QString{}); |
| 1080 | QStringLiteral("")); | ||
| 1081 | } | 1149 | } |
| 1082 | qt_config->endArray(); | 1150 | qt_config->endArray(); |
| 1083 | ++i; | 1151 | ++i; |
| @@ -1266,7 +1334,6 @@ void Config::SaveUIValues() { | |||
| 1266 | WriteSetting(QStringLiteral("firstStart"), UISettings::values.first_start, true); | 1334 | WriteSetting(QStringLiteral("firstStart"), UISettings::values.first_start, true); |
| 1267 | WriteSetting(QStringLiteral("calloutFlags"), UISettings::values.callout_flags, 0); | 1335 | WriteSetting(QStringLiteral("calloutFlags"), UISettings::values.callout_flags, 0); |
| 1268 | WriteSetting(QStringLiteral("showConsole"), UISettings::values.show_console, false); | 1336 | WriteSetting(QStringLiteral("showConsole"), UISettings::values.show_console, false); |
| 1269 | WriteSetting(QStringLiteral("profileIndex"), UISettings::values.profile_index, 0); | ||
| 1270 | WriteSetting(QStringLiteral("pauseWhenInBackground"), | 1337 | WriteSetting(QStringLiteral("pauseWhenInBackground"), |
| 1271 | UISettings::values.pause_when_in_background, false); | 1338 | UISettings::values.pause_when_in_background, false); |
| 1272 | WriteSetting(QStringLiteral("hideInactiveMouse"), UISettings::values.hide_mouse, false); | 1339 | WriteSetting(QStringLiteral("hideInactiveMouse"), UISettings::values.hide_mouse, false); |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index e5f39b040..ca0d29c6c 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -23,7 +23,8 @@ public: | |||
| 23 | void Save(); | 23 | void Save(); |
| 24 | 24 | ||
| 25 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; | 25 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; |
| 26 | static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs; | 26 | static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs; |
| 27 | static const std::array<int, 2> default_stick_mod; | ||
| 27 | static const std::array<int, Settings::NativeMouseButton::NumMouseButtons> | 28 | static const std::array<int, Settings::NativeMouseButton::NumMouseButtons> |
| 28 | default_mouse_buttons; | 29 | default_mouse_buttons; |
| 29 | static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; | 30 | static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; |
| @@ -37,7 +38,7 @@ private: | |||
| 37 | void ReadKeyboardValues(); | 38 | void ReadKeyboardValues(); |
| 38 | void ReadMouseValues(); | 39 | void ReadMouseValues(); |
| 39 | void ReadTouchscreenValues(); | 40 | void ReadTouchscreenValues(); |
| 40 | void ApplyDefaultProfileIfInputInvalid(); | 41 | void ReadMotionTouchValues(); |
| 41 | 42 | ||
| 42 | // Read functions bases off the respective config section names. | 43 | // Read functions bases off the respective config section names. |
| 43 | void ReadAudioValues(); | 44 | void ReadAudioValues(); |
| @@ -64,6 +65,7 @@ private: | |||
| 64 | void SaveDebugValues(); | 65 | void SaveDebugValues(); |
| 65 | void SaveMouseValues(); | 66 | void SaveMouseValues(); |
| 66 | void SaveTouchscreenValues(); | 67 | void SaveTouchscreenValues(); |
| 68 | void SaveMotionTouchValues(); | ||
| 67 | 69 | ||
| 68 | // Save functions based off the respective config section names. | 70 | // Save functions based off the respective config section names. |
| 69 | void SaveAudioValues(); | 71 | void SaveAudioValues(); |
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui index 5f5d8e571..fcf42cdcb 100644 --- a/src/yuzu/configuration/configure.ui +++ b/src/yuzu/configuration/configure.ui | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>382</width> | 9 | <width>650</width> |
| 10 | <height>650</height> | 10 | <height>650</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| @@ -26,13 +26,13 @@ | |||
| 26 | <widget class="QListWidget" name="selectorList"> | 26 | <widget class="QListWidget" name="selectorList"> |
| 27 | <property name="minimumSize"> | 27 | <property name="minimumSize"> |
| 28 | <size> | 28 | <size> |
| 29 | <width>150</width> | 29 | <width>120</width> |
| 30 | <height>0</height> | 30 | <height>0</height> |
| 31 | </size> | 31 | </size> |
| 32 | </property> | 32 | </property> |
| 33 | <property name="maximumSize"> | 33 | <property name="maximumSize"> |
| 34 | <size> | 34 | <size> |
| 35 | <width>150</width> | 35 | <width>120</width> |
| 36 | <height>16777215</height> | 36 | <height>16777215</height> |
| 37 | </size> | 37 | </size> |
| 38 | </property> | 38 | </property> |
| @@ -44,76 +44,121 @@ | |||
| 44 | <number>0</number> | 44 | <number>0</number> |
| 45 | </property> | 45 | </property> |
| 46 | <widget class="ConfigureGeneral" name="generalTab"> | 46 | <widget class="ConfigureGeneral" name="generalTab"> |
| 47 | <property name="accessibleName"> | ||
| 48 | <string>General</string> | ||
| 49 | </property> | ||
| 47 | <attribute name="title"> | 50 | <attribute name="title"> |
| 48 | <string>General</string> | 51 | <string>General</string> |
| 49 | </attribute> | 52 | </attribute> |
| 50 | </widget> | 53 | </widget> |
| 51 | <widget class="ConfigureUi" name="uiTab"> | 54 | <widget class="ConfigureUi" name="uiTab"> |
| 55 | <property name="accessibleName"> | ||
| 56 | <string>UI</string> | ||
| 57 | </property> | ||
| 52 | <attribute name="title"> | 58 | <attribute name="title"> |
| 53 | <string>Game List</string> | 59 | <string>Game List</string> |
| 54 | </attribute> | 60 | </attribute> |
| 55 | </widget> | 61 | </widget> |
| 56 | <widget class="ConfigureSystem" name="systemTab"> | 62 | <widget class="ConfigureSystem" name="systemTab"> |
| 63 | <property name="accessibleName"> | ||
| 64 | <string>System</string> | ||
| 65 | </property> | ||
| 57 | <attribute name="title"> | 66 | <attribute name="title"> |
| 58 | <string>System</string> | 67 | <string>System</string> |
| 59 | </attribute> | 68 | </attribute> |
| 60 | </widget> | 69 | </widget> |
| 61 | <widget class="ConfigureProfileManager" name="profileManagerTab"> | 70 | <widget class="ConfigureProfileManager" name="profileManagerTab"> |
| 71 | <property name="accessibleName"> | ||
| 72 | <string>Profiles</string> | ||
| 73 | </property> | ||
| 62 | <attribute name="title"> | 74 | <attribute name="title"> |
| 63 | <string>Profiles</string> | 75 | <string>Profiles</string> |
| 64 | </attribute> | 76 | </attribute> |
| 65 | </widget> | 77 | </widget> |
| 66 | <widget class="ConfigureFilesystem" name="filesystemTab"> | 78 | <widget class="ConfigureFilesystem" name="filesystemTab"> |
| 79 | <property name="accessibleName"> | ||
| 80 | <string>Filesystem</string> | ||
| 81 | </property> | ||
| 67 | <attribute name="title"> | 82 | <attribute name="title"> |
| 68 | <string>Filesystem</string> | 83 | <string>Filesystem</string> |
| 69 | </attribute> | 84 | </attribute> |
| 70 | </widget> | 85 | </widget> |
| 71 | <widget class="ConfigureInputSimple" name="inputTab"> | 86 | <widget class="ConfigureInput" name="inputTab"> |
| 87 | <property name="accessibleName"> | ||
| 88 | <string>Controls</string> | ||
| 89 | </property> | ||
| 72 | <attribute name="title"> | 90 | <attribute name="title"> |
| 73 | <string>Input</string> | 91 | <string>Controls</string> |
| 74 | </attribute> | 92 | </attribute> |
| 75 | </widget> | 93 | </widget> |
| 76 | <widget class="ConfigureHotkeys" name="hotkeysTab"> | 94 | <widget class="ConfigureHotkeys" name="hotkeysTab"> |
| 95 | <property name="accessibleName"> | ||
| 96 | <string>Hotkeys</string> | ||
| 97 | </property> | ||
| 77 | <attribute name="title"> | 98 | <attribute name="title"> |
| 78 | <string>Hotkeys</string> | 99 | <string>Hotkeys</string> |
| 79 | </attribute> | 100 | </attribute> |
| 80 | </widget> | 101 | </widget> |
| 81 | <widget class="ConfigureCpu" name="cpuTab"> | 102 | <widget class="ConfigureCpu" name="cpuTab"> |
| 103 | <property name="accessibleName"> | ||
| 104 | <string>CPU</string> | ||
| 105 | </property> | ||
| 82 | <attribute name="title"> | 106 | <attribute name="title"> |
| 83 | <string>CPU</string> | 107 | <string>CPU</string> |
| 84 | </attribute> | 108 | </attribute> |
| 85 | </widget> | 109 | </widget> |
| 86 | <widget class="ConfigureCpuDebug" name="cpuDebugTab"> | 110 | <widget class="ConfigureCpuDebug" name="cpuDebugTab"> |
| 111 | <property name="accessibleName"> | ||
| 112 | <string>Debug</string> | ||
| 113 | </property> | ||
| 87 | <attribute name="title"> | 114 | <attribute name="title"> |
| 88 | <string>Debug</string> | 115 | <string>Debug</string> |
| 89 | </attribute> | 116 | </attribute> |
| 90 | </widget> | 117 | </widget> |
| 91 | <widget class="ConfigureGraphics" name="graphicsTab"> | 118 | <widget class="ConfigureGraphics" name="graphicsTab"> |
| 119 | <property name="accessibleName"> | ||
| 120 | <string>Graphics</string> | ||
| 121 | </property> | ||
| 92 | <attribute name="title"> | 122 | <attribute name="title"> |
| 93 | <string>Graphics</string> | 123 | <string>Graphics</string> |
| 94 | </attribute> | 124 | </attribute> |
| 95 | </widget> | 125 | </widget> |
| 96 | <widget class="ConfigureGraphicsAdvanced" name="graphicsAdvancedTab"> | 126 | <widget class="ConfigureGraphicsAdvanced" name="graphicsAdvancedTab"> |
| 127 | <property name="accessibleName"> | ||
| 128 | <string>Advanced</string> | ||
| 129 | </property> | ||
| 97 | <attribute name="title"> | 130 | <attribute name="title"> |
| 98 | <string>GraphicsAdvanced</string> | 131 | <string>GraphicsAdvanced</string> |
| 99 | </attribute> | 132 | </attribute> |
| 100 | </widget> | 133 | </widget> |
| 101 | <widget class="ConfigureAudio" name="audioTab"> | 134 | <widget class="ConfigureAudio" name="audioTab"> |
| 135 | <property name="accessibleName"> | ||
| 136 | <string>Audio</string> | ||
| 137 | </property> | ||
| 102 | <attribute name="title"> | 138 | <attribute name="title"> |
| 103 | <string>Audio</string> | 139 | <string>Audio</string> |
| 104 | </attribute> | 140 | </attribute> |
| 105 | </widget> | 141 | </widget> |
| 106 | <widget class="ConfigureDebug" name="debugTab"> | 142 | <widget class="ConfigureDebug" name="debugTab"> |
| 143 | <property name="accessibleName"> | ||
| 144 | <string>Debug</string> | ||
| 145 | </property> | ||
| 107 | <attribute name="title"> | 146 | <attribute name="title"> |
| 108 | <string>Debug</string> | 147 | <string>Debug</string> |
| 109 | </attribute> | 148 | </attribute> |
| 110 | </widget> | 149 | </widget> |
| 111 | <widget class="ConfigureWeb" name="webTab"> | 150 | <widget class="ConfigureWeb" name="webTab"> |
| 151 | <property name="accessibleName"> | ||
| 152 | <string>Web</string> | ||
| 153 | </property> | ||
| 112 | <attribute name="title"> | 154 | <attribute name="title"> |
| 113 | <string>Web</string> | 155 | <string>Web</string> |
| 114 | </attribute> | 156 | </attribute> |
| 115 | </widget> | 157 | </widget> |
| 116 | <widget class="ConfigureService" name="serviceTab"> | 158 | <widget class="ConfigureService" name="serviceTab"> |
| 159 | <property name="accessibleName"> | ||
| 160 | <string>Services</string> | ||
| 161 | </property> | ||
| 117 | <attribute name="title"> | 162 | <attribute name="title"> |
| 118 | <string>Services</string> | 163 | <string>Services</string> |
| 119 | </attribute> | 164 | </attribute> |
| @@ -205,9 +250,9 @@ | |||
| 205 | <container>1</container> | 250 | <container>1</container> |
| 206 | </customwidget> | 251 | </customwidget> |
| 207 | <customwidget> | 252 | <customwidget> |
| 208 | <class>ConfigureInputSimple</class> | 253 | <class>ConfigureInput</class> |
| 209 | <extends>QWidget</extends> | 254 | <extends>QWidget</extends> |
| 210 | <header>configuration/configure_input_simple.h</header> | 255 | <header>configuration/configure_input.h</header> |
| 211 | <container>1</container> | 256 | <container>1</container> |
| 212 | </customwidget> | 257 | </customwidget> |
| 213 | <customwidget> | 258 | <customwidget> |
diff --git a/src/yuzu/configuration/configure_debug_controller.cpp b/src/yuzu/configuration/configure_debug_controller.cpp new file mode 100644 index 000000000..0097c9a29 --- /dev/null +++ b/src/yuzu/configuration/configure_debug_controller.cpp | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "ui_configure_debug_controller.h" | ||
| 6 | #include "yuzu/configuration/configure_debug_controller.h" | ||
| 7 | |||
| 8 | ConfigureDebugController::ConfigureDebugController(QWidget* parent, | ||
| 9 | InputCommon::InputSubsystem* input_subsystem) | ||
| 10 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()), | ||
| 11 | debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, true)) { | ||
| 12 | ui->setupUi(this); | ||
| 13 | |||
| 14 | ui->controllerLayout->addWidget(debug_controller); | ||
| 15 | |||
| 16 | connect(ui->clear_all_button, &QPushButton::clicked, this, | ||
| 17 | [this] { debug_controller->ClearAll(); }); | ||
| 18 | connect(ui->restore_defaults_button, &QPushButton::clicked, this, | ||
| 19 | [this] { debug_controller->RestoreDefaults(); }); | ||
| 20 | |||
| 21 | RetranslateUI(); | ||
| 22 | } | ||
| 23 | |||
| 24 | ConfigureDebugController::~ConfigureDebugController() = default; | ||
| 25 | |||
| 26 | void ConfigureDebugController::ApplyConfiguration() { | ||
| 27 | debug_controller->ApplyConfiguration(); | ||
| 28 | } | ||
| 29 | |||
| 30 | void ConfigureDebugController::changeEvent(QEvent* event) { | ||
| 31 | if (event->type() == QEvent::LanguageChange) { | ||
| 32 | RetranslateUI(); | ||
| 33 | } | ||
| 34 | |||
| 35 | QDialog::changeEvent(event); | ||
| 36 | } | ||
| 37 | |||
| 38 | void ConfigureDebugController::RetranslateUI() { | ||
| 39 | ui->retranslateUi(this); | ||
| 40 | } | ||
diff --git a/src/yuzu/configuration/configure_debug_controller.h b/src/yuzu/configuration/configure_debug_controller.h new file mode 100644 index 000000000..34dcf705f --- /dev/null +++ b/src/yuzu/configuration/configure_debug_controller.h | |||
| @@ -0,0 +1,38 @@ | |||
| 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 <memory> | ||
| 8 | #include <QDialog> | ||
| 9 | #include "yuzu/configuration/configure_input_player.h" | ||
| 10 | |||
| 11 | class QPushButton; | ||
| 12 | |||
| 13 | namespace InputCommon { | ||
| 14 | class InputSubsystem; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Ui { | ||
| 18 | class ConfigureDebugController; | ||
| 19 | } | ||
| 20 | |||
| 21 | class ConfigureDebugController : public QDialog { | ||
| 22 | Q_OBJECT | ||
| 23 | |||
| 24 | public: | ||
| 25 | explicit ConfigureDebugController(QWidget* parent, | ||
| 26 | InputCommon::InputSubsystem* input_subsystem); | ||
| 27 | ~ConfigureDebugController() override; | ||
| 28 | |||
| 29 | void ApplyConfiguration(); | ||
| 30 | |||
| 31 | private: | ||
| 32 | void changeEvent(QEvent* event) override; | ||
| 33 | void RetranslateUI(); | ||
| 34 | |||
| 35 | std::unique_ptr<Ui::ConfigureDebugController> ui; | ||
| 36 | |||
| 37 | ConfigureInputPlayer* debug_controller; | ||
| 38 | }; | ||
diff --git a/src/yuzu/configuration/configure_debug_controller.ui b/src/yuzu/configuration/configure_debug_controller.ui new file mode 100644 index 000000000..a95ed50ff --- /dev/null +++ b/src/yuzu/configuration/configure_debug_controller.ui | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureDebugController</class> | ||
| 4 | <widget class="QDialog" name="ConfigureDebugController"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>780</width> | ||
| 10 | <height>500</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Configure Debug Controller</string> | ||
| 15 | </property> | ||
| 16 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 17 | <property name="spacing"> | ||
| 18 | <number>2</number> | ||
| 19 | </property> | ||
| 20 | <property name="leftMargin"> | ||
| 21 | <number>9</number> | ||
| 22 | </property> | ||
| 23 | <property name="topMargin"> | ||
| 24 | <number>9</number> | ||
| 25 | </property> | ||
| 26 | <property name="rightMargin"> | ||
| 27 | <number>9</number> | ||
| 28 | </property> | ||
| 29 | <property name="bottomMargin"> | ||
| 30 | <number>9</number> | ||
| 31 | </property> | ||
| 32 | <item> | ||
| 33 | <layout class="QHBoxLayout" name="controllerLayout"/> | ||
| 34 | </item> | ||
| 35 | <item> | ||
| 36 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 37 | <item> | ||
| 38 | <widget class="QPushButton" name="clear_all_button"> | ||
| 39 | <property name="text"> | ||
| 40 | <string>Clear</string> | ||
| 41 | </property> | ||
| 42 | </widget> | ||
| 43 | </item> | ||
| 44 | <item> | ||
| 45 | <widget class="QPushButton" name="restore_defaults_button"> | ||
| 46 | <property name="text"> | ||
| 47 | <string>Defaults</string> | ||
| 48 | </property> | ||
| 49 | </widget> | ||
| 50 | </item> | ||
| 51 | <item> | ||
| 52 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 53 | <property name="standardButtons"> | ||
| 54 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 55 | </property> | ||
| 56 | </widget> | ||
| 57 | </item> | ||
| 58 | </layout> | ||
| 59 | </item> | ||
| 60 | </layout> | ||
| 61 | </widget> | ||
| 62 | <resources/> | ||
| 63 | <connections> | ||
| 64 | <connection> | ||
| 65 | <sender>buttonBox</sender> | ||
| 66 | <signal>accepted()</signal> | ||
| 67 | <receiver>ConfigureDebugController</receiver> | ||
| 68 | <slot>accept()</slot> | ||
| 69 | <hints> | ||
| 70 | <hint type="sourcelabel"> | ||
| 71 | <x>140</x> | ||
| 72 | <y>318</y> | ||
| 73 | </hint> | ||
| 74 | <hint type="destinationlabel"> | ||
| 75 | <x>140</x> | ||
| 76 | <y>169</y> | ||
| 77 | </hint> | ||
| 78 | </hints> | ||
| 79 | </connection> | ||
| 80 | <connection> | ||
| 81 | <sender>buttonBox</sender> | ||
| 82 | <signal>rejected()</signal> | ||
| 83 | <receiver>ConfigureDebugController</receiver> | ||
| 84 | <slot>reject()</slot> | ||
| 85 | <hints> | ||
| 86 | <hint type="sourcelabel"> | ||
| 87 | <x>140</x> | ||
| 88 | <y>318</y> | ||
| 89 | </hint> | ||
| 90 | <hint type="destinationlabel"> | ||
| 91 | <x>140</x> | ||
| 92 | <y>169</y> | ||
| 93 | </hint> | ||
| 94 | </hints> | ||
| 95 | </connection> | ||
| 96 | </connections> | ||
| 97 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 4e30dc51e..8186929a6 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -12,7 +12,8 @@ | |||
| 12 | #include "yuzu/configuration/configure_input_player.h" | 12 | #include "yuzu/configuration/configure_input_player.h" |
| 13 | #include "yuzu/hotkeys.h" | 13 | #include "yuzu/hotkeys.h" |
| 14 | 14 | ||
| 15 | ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) | 15 | ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, |
| 16 | InputCommon::InputSubsystem* input_subsystem) | ||
| 16 | : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { | 17 | : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { |
| 17 | Settings::configuring_global = true; | 18 | Settings::configuring_global = true; |
| 18 | 19 | ||
| @@ -20,6 +21,8 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) | |||
| 20 | ui->hotkeysTab->Populate(registry); | 21 | ui->hotkeysTab->Populate(registry); |
| 21 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); | 22 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); |
| 22 | 23 | ||
| 24 | ui->inputTab->Initialize(input_subsystem); | ||
| 25 | |||
| 23 | SetConfiguration(); | 26 | SetConfiguration(); |
| 24 | PopulateSelectionList(); | 27 | PopulateSelectionList(); |
| 25 | 28 | ||
| @@ -80,12 +83,12 @@ Q_DECLARE_METATYPE(QList<QWidget*>); | |||
| 80 | 83 | ||
| 81 | void ConfigureDialog::PopulateSelectionList() { | 84 | void ConfigureDialog::PopulateSelectionList() { |
| 82 | const std::array<std::pair<QString, QList<QWidget*>>, 6> items{ | 85 | const std::array<std::pair<QString, QList<QWidget*>>, 6> items{ |
| 83 | {{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->uiTab}}, | 86 | {{tr("General"), {ui->generalTab, ui->hotkeysTab, ui->uiTab, ui->webTab, ui->debugTab}}, |
| 84 | {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}}, | 87 | {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}}, |
| 85 | {tr("CPU"), {ui->cpuTab, ui->cpuDebugTab}}, | 88 | {tr("CPU"), {ui->cpuTab, ui->cpuDebugTab}}, |
| 86 | {tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}}, | 89 | {tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}}, |
| 87 | {tr("Audio"), {ui->audioTab}}, | 90 | {tr("Audio"), {ui->audioTab}}, |
| 88 | {tr("Controls"), {ui->inputTab, ui->hotkeysTab}}}, | 91 | {tr("Controls"), ui->inputTab->GetSubTabs()}}, |
| 89 | }; | 92 | }; |
| 90 | 93 | ||
| 91 | [[maybe_unused]] const QSignalBlocker blocker(ui->selectorList); | 94 | [[maybe_unused]] const QSignalBlocker blocker(ui->selectorList); |
| @@ -117,7 +120,7 @@ void ConfigureDialog::UpdateVisibleTabs() { | |||
| 117 | {ui->generalTab, tr("General")}, | 120 | {ui->generalTab, tr("General")}, |
| 118 | {ui->systemTab, tr("System")}, | 121 | {ui->systemTab, tr("System")}, |
| 119 | {ui->profileManagerTab, tr("Profiles")}, | 122 | {ui->profileManagerTab, tr("Profiles")}, |
| 120 | {ui->inputTab, tr("Input")}, | 123 | {ui->inputTab, tr("Controls")}, |
| 121 | {ui->hotkeysTab, tr("Hotkeys")}, | 124 | {ui->hotkeysTab, tr("Hotkeys")}, |
| 122 | {ui->cpuTab, tr("CPU")}, | 125 | {ui->cpuTab, tr("CPU")}, |
| 123 | {ui->cpuDebugTab, tr("Debug")}, | 126 | {ui->cpuDebugTab, tr("Debug")}, |
| @@ -138,6 +141,6 @@ void ConfigureDialog::UpdateVisibleTabs() { | |||
| 138 | const QList<QWidget*> tabs = qvariant_cast<QList<QWidget*>>(items[0]->data(Qt::UserRole)); | 141 | const QList<QWidget*> tabs = qvariant_cast<QList<QWidget*>>(items[0]->data(Qt::UserRole)); |
| 139 | 142 | ||
| 140 | for (const auto tab : tabs) { | 143 | for (const auto tab : tabs) { |
| 141 | ui->tabWidget->addTab(tab, widgets.at(tab)); | 144 | ui->tabWidget->addTab(tab, tab->accessibleName()); |
| 142 | } | 145 | } |
| 143 | } | 146 | } |
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 4289bc225..570c3b941 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h | |||
| @@ -9,6 +9,10 @@ | |||
| 9 | 9 | ||
| 10 | class HotkeyRegistry; | 10 | class HotkeyRegistry; |
| 11 | 11 | ||
| 12 | namespace InputCommon { | ||
| 13 | class InputSubsystem; | ||
| 14 | } | ||
| 15 | |||
| 12 | namespace Ui { | 16 | namespace Ui { |
| 13 | class ConfigureDialog; | 17 | class ConfigureDialog; |
| 14 | } | 18 | } |
| @@ -17,7 +21,8 @@ class ConfigureDialog : public QDialog { | |||
| 17 | Q_OBJECT | 21 | Q_OBJECT |
| 18 | 22 | ||
| 19 | public: | 23 | public: |
| 20 | explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry); | 24 | explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, |
| 25 | InputCommon::InputSubsystem* input_subsystem); | ||
| 21 | ~ConfigureDialog() override; | 26 | ~ConfigureDialog() override; |
| 22 | 27 | ||
| 23 | void ApplyConfiguration(); | 28 | void ApplyConfiguration(); |
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index f2977719c..ae3e31762 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -8,18 +8,33 @@ | |||
| 8 | #include <QSignalBlocker> | 8 | #include <QSignalBlocker> |
| 9 | #include <QTimer> | 9 | #include <QTimer> |
| 10 | 10 | ||
| 11 | #include "configuration/configure_touchscreen_advanced.h" | ||
| 12 | #include "core/core.h" | 11 | #include "core/core.h" |
| 13 | #include "core/hle/service/am/am.h" | 12 | #include "core/hle/service/am/am.h" |
| 14 | #include "core/hle/service/am/applet_ae.h" | 13 | #include "core/hle/service/am/applet_ae.h" |
| 15 | #include "core/hle/service/am/applet_oe.h" | 14 | #include "core/hle/service/am/applet_oe.h" |
| 16 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 17 | #include "core/hle/service/sm/sm.h" | 15 | #include "core/hle/service/sm/sm.h" |
| 18 | #include "ui_configure_input.h" | 16 | #include "ui_configure_input.h" |
| 17 | #include "ui_configure_input_advanced.h" | ||
| 19 | #include "ui_configure_input_player.h" | 18 | #include "ui_configure_input_player.h" |
| 19 | #include "yuzu/configuration/configure_debug_controller.h" | ||
| 20 | #include "yuzu/configuration/configure_input.h" | 20 | #include "yuzu/configuration/configure_input.h" |
| 21 | #include "yuzu/configuration/configure_input_advanced.h" | ||
| 21 | #include "yuzu/configuration/configure_input_player.h" | 22 | #include "yuzu/configuration/configure_input_player.h" |
| 23 | #include "yuzu/configuration/configure_motion_touch.h" | ||
| 22 | #include "yuzu/configuration/configure_mouse_advanced.h" | 24 | #include "yuzu/configuration/configure_mouse_advanced.h" |
| 25 | #include "yuzu/configuration/configure_touchscreen_advanced.h" | ||
| 26 | |||
| 27 | namespace { | ||
| 28 | template <typename Dialog, typename... Args> | ||
| 29 | void CallConfigureDialog(ConfigureInput& parent, Args&&... args) { | ||
| 30 | Dialog dialog(&parent, std::forward<Args>(args)...); | ||
| 31 | |||
| 32 | const auto res = dialog.exec(); | ||
| 33 | if (res == QDialog::Accepted) { | ||
| 34 | dialog.ApplyConfiguration(); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } // Anonymous namespace | ||
| 23 | 38 | ||
| 24 | void OnDockedModeChanged(bool last_state, bool new_state) { | 39 | void OnDockedModeChanged(bool last_state, bool new_state) { |
| 25 | if (last_state == new_state) { | 40 | if (last_state == new_state) { |
| @@ -48,97 +63,102 @@ void OnDockedModeChanged(bool last_state, bool new_state) { | |||
| 48 | } | 63 | } |
| 49 | } | 64 | } |
| 50 | 65 | ||
| 51 | namespace { | ||
| 52 | template <typename Dialog, typename... Args> | ||
| 53 | void CallConfigureDialog(ConfigureInput& parent, Args&&... args) { | ||
| 54 | parent.ApplyConfiguration(); | ||
| 55 | Dialog dialog(&parent, std::forward<Args>(args)...); | ||
| 56 | |||
| 57 | const auto res = dialog.exec(); | ||
| 58 | if (res == QDialog::Accepted) { | ||
| 59 | dialog.ApplyConfiguration(); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | } // Anonymous namespace | ||
| 63 | |||
| 64 | ConfigureInput::ConfigureInput(QWidget* parent) | 66 | ConfigureInput::ConfigureInput(QWidget* parent) |
| 65 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureInput>()) { | 67 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) { |
| 66 | ui->setupUi(this); | 68 | ui->setupUi(this); |
| 69 | } | ||
| 67 | 70 | ||
| 68 | players_controller = { | 71 | ConfigureInput::~ConfigureInput() = default; |
| 69 | ui->player1_combobox, ui->player2_combobox, ui->player3_combobox, ui->player4_combobox, | ||
| 70 | ui->player5_combobox, ui->player6_combobox, ui->player7_combobox, ui->player8_combobox, | ||
| 71 | }; | ||
| 72 | 72 | ||
| 73 | players_configure = { | 73 | void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem) { |
| 74 | ui->player1_configure, ui->player2_configure, ui->player3_configure, ui->player4_configure, | 74 | player_controllers = { |
| 75 | ui->player5_configure, ui->player6_configure, ui->player7_configure, ui->player8_configure, | 75 | new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem), |
| 76 | new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem), | ||
| 77 | new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem), | ||
| 78 | new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem), | ||
| 79 | new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem), | ||
| 80 | new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem), | ||
| 81 | new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem), | ||
| 82 | new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem), | ||
| 76 | }; | 83 | }; |
| 77 | 84 | ||
| 78 | RetranslateUI(); | 85 | player_tabs = { |
| 79 | LoadConfiguration(); | 86 | ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4, |
| 80 | UpdateUIEnabled(); | 87 | ui->tabPlayer5, ui->tabPlayer6, ui->tabPlayer7, ui->tabPlayer8, |
| 88 | }; | ||
| 81 | 89 | ||
| 82 | connect(ui->restore_defaults_button, &QPushButton::clicked, this, | 90 | player_connected = { |
| 83 | &ConfigureInput::RestoreDefaults); | 91 | ui->checkboxPlayer1Connected, ui->checkboxPlayer2Connected, ui->checkboxPlayer3Connected, |
| 92 | ui->checkboxPlayer4Connected, ui->checkboxPlayer5Connected, ui->checkboxPlayer6Connected, | ||
| 93 | ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected, | ||
| 94 | }; | ||
| 84 | 95 | ||
| 85 | for (auto* enabled : players_controller) { | 96 | for (std::size_t i = 0; i < player_tabs.size(); ++i) { |
| 86 | connect(enabled, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | 97 | player_tabs[i]->setLayout(new QHBoxLayout(player_tabs[i])); |
| 87 | &ConfigureInput::UpdateUIEnabled); | 98 | player_tabs[i]->layout()->addWidget(player_controllers[i]); |
| 88 | } | 99 | connect(player_controllers[i], &ConfigureInputPlayer::Connected, [&, i](bool is_connected) { |
| 89 | connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); | 100 | if (is_connected) { |
| 90 | connect(ui->handheld_connected, &QCheckBox::stateChanged, this, | 101 | for (std::size_t index = 0; index <= i; ++index) { |
| 91 | &ConfigureInput::UpdateUIEnabled); | 102 | player_connected[index]->setChecked(is_connected); |
| 92 | connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); | 103 | } |
| 93 | connect(ui->keyboard_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); | 104 | } else { |
| 94 | connect(ui->debug_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); | 105 | for (std::size_t index = i; index < player_tabs.size(); ++index) { |
| 95 | connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this, | 106 | player_connected[index]->setChecked(is_connected); |
| 96 | &ConfigureInput::UpdateUIEnabled); | 107 | } |
| 97 | 108 | } | |
| 98 | for (std::size_t i = 0; i < players_configure.size(); ++i) { | 109 | }); |
| 99 | connect(players_configure[i], &QPushButton::clicked, this, | 110 | connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, |
| 100 | [this, i] { CallConfigureDialog<ConfigureInputPlayer>(*this, i, false); }); | 111 | [this] { UpdateAllInputDevices(); }); |
| 112 | connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) { | ||
| 113 | player_controllers[i]->ConnectPlayer(state == Qt::Checked); | ||
| 114 | }); | ||
| 101 | } | 115 | } |
| 116 | // Only the first player can choose handheld mode so connect the signal just to player 1 | ||
| 117 | connect(player_controllers[0], &ConfigureInputPlayer::HandheldStateChanged, | ||
| 118 | [this](bool is_handheld) { UpdateDockedState(is_handheld); }); | ||
| 119 | |||
| 120 | advanced = new ConfigureInputAdvanced(this); | ||
| 121 | ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); | ||
| 122 | ui->tabAdvanced->layout()->addWidget(advanced); | ||
| 123 | connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] { | ||
| 124 | CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem); | ||
| 125 | }); | ||
| 126 | connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] { | ||
| 127 | CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem); | ||
| 128 | }); | ||
| 129 | connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog, | ||
| 130 | [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); }); | ||
| 131 | connect(advanced, &ConfigureInputAdvanced::CallMotionTouchConfigDialog, | ||
| 132 | [this, input_subsystem] { | ||
| 133 | CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); | ||
| 134 | }); | ||
| 102 | 135 | ||
| 103 | connect(ui->handheld_configure, &QPushButton::clicked, this, | 136 | connect(ui->buttonClearAll, &QPushButton::clicked, [this] { ClearAll(); }); |
| 104 | [this] { CallConfigureDialog<ConfigureInputPlayer>(*this, 8, false); }); | 137 | connect(ui->buttonRestoreDefaults, &QPushButton::clicked, [this] { RestoreDefaults(); }); |
| 105 | |||
| 106 | connect(ui->debug_configure, &QPushButton::clicked, this, | ||
| 107 | [this] { CallConfigureDialog<ConfigureInputPlayer>(*this, 9, true); }); | ||
| 108 | |||
| 109 | connect(ui->mouse_advanced, &QPushButton::clicked, this, | ||
| 110 | [this] { CallConfigureDialog<ConfigureMouseAdvanced>(*this); }); | ||
| 111 | 138 | ||
| 112 | connect(ui->touchscreen_advanced, &QPushButton::clicked, this, | 139 | RetranslateUI(); |
| 113 | [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); }); | 140 | LoadConfiguration(); |
| 114 | } | 141 | } |
| 115 | 142 | ||
| 116 | ConfigureInput::~ConfigureInput() = default; | 143 | QList<QWidget*> ConfigureInput::GetSubTabs() const { |
| 144 | return { | ||
| 145 | ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4, ui->tabPlayer5, | ||
| 146 | ui->tabPlayer6, ui->tabPlayer7, ui->tabPlayer8, ui->tabAdvanced, | ||
| 147 | }; | ||
| 148 | } | ||
| 117 | 149 | ||
| 118 | void ConfigureInput::ApplyConfiguration() { | 150 | void ConfigureInput::ApplyConfiguration() { |
| 119 | for (std::size_t i = 0; i < players_controller.size(); ++i) { | 151 | for (auto controller : player_controllers) { |
| 120 | const auto controller_type_index = players_controller[i]->currentIndex(); | 152 | controller->ApplyConfiguration(); |
| 121 | |||
| 122 | Settings::values.players[i].connected = controller_type_index != 0; | ||
| 123 | |||
| 124 | if (controller_type_index > 0) { | ||
| 125 | Settings::values.players[i].type = | ||
| 126 | static_cast<Settings::ControllerType>(controller_type_index - 1); | ||
| 127 | } else { | ||
| 128 | Settings::values.players[i].type = Settings::ControllerType::DualJoycon; | ||
| 129 | } | ||
| 130 | } | 153 | } |
| 131 | 154 | ||
| 155 | advanced->ApplyConfiguration(); | ||
| 156 | |||
| 132 | const bool pre_docked_mode = Settings::values.use_docked_mode; | 157 | const bool pre_docked_mode = Settings::values.use_docked_mode; |
| 133 | Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); | 158 | Settings::values.use_docked_mode = ui->radioDocked->isChecked(); |
| 134 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); | 159 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); |
| 135 | Settings::values | 160 | |
| 136 | .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)] | 161 | Settings::values.vibration_enabled = ui->vibrationGroup->isChecked(); |
| 137 | .connected = ui->handheld_connected->isChecked(); | ||
| 138 | Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked(); | ||
| 139 | Settings::values.mouse_enabled = ui->mouse_enabled->isChecked(); | ||
| 140 | Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked(); | ||
| 141 | Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); | ||
| 142 | } | 162 | } |
| 143 | 163 | ||
| 144 | void ConfigureInput::changeEvent(QEvent* event) { | 164 | void ConfigureInput::changeEvent(QEvent* event) { |
| @@ -146,94 +166,63 @@ void ConfigureInput::changeEvent(QEvent* event) { | |||
| 146 | RetranslateUI(); | 166 | RetranslateUI(); |
| 147 | } | 167 | } |
| 148 | 168 | ||
| 149 | QDialog::changeEvent(event); | 169 | QWidget::changeEvent(event); |
| 150 | } | 170 | } |
| 151 | 171 | ||
| 152 | void ConfigureInput::RetranslateUI() { | 172 | void ConfigureInput::RetranslateUI() { |
| 153 | ui->retranslateUi(this); | 173 | ui->retranslateUi(this); |
| 154 | RetranslateControllerComboBoxes(); | ||
| 155 | } | 174 | } |
| 156 | 175 | ||
| 157 | void ConfigureInput::RetranslateControllerComboBoxes() { | 176 | void ConfigureInput::LoadConfiguration() { |
| 158 | for (auto* controller_box : players_controller) { | ||
| 159 | [[maybe_unused]] const QSignalBlocker blocker(controller_box); | ||
| 160 | |||
| 161 | controller_box->clear(); | ||
| 162 | controller_box->addItems({tr("None"), tr("Pro Controller"), tr("Dual Joycons"), | ||
| 163 | tr("Single Right Joycon"), tr("Single Left Joycon")}); | ||
| 164 | } | ||
| 165 | |||
| 166 | LoadPlayerControllerIndices(); | 177 | LoadPlayerControllerIndices(); |
| 167 | } | 178 | UpdateDockedState(Settings::values.players[0].controller_type == |
| 179 | Settings::ControllerType::Handheld); | ||
| 168 | 180 | ||
| 169 | void ConfigureInput::UpdateUIEnabled() { | 181 | ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); |
| 170 | bool hit_disabled = false; | 182 | } |
| 171 | for (auto* player : players_controller) { | ||
| 172 | player->setDisabled(hit_disabled); | ||
| 173 | if (hit_disabled) { | ||
| 174 | player->setCurrentIndex(0); | ||
| 175 | } | ||
| 176 | if (!hit_disabled && player->currentIndex() == 0) { | ||
| 177 | hit_disabled = true; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | 183 | ||
| 181 | for (std::size_t i = 0; i < players_controller.size(); ++i) { | 184 | void ConfigureInput::LoadPlayerControllerIndices() { |
| 182 | players_configure[i]->setEnabled(players_controller[i]->currentIndex() != 0); | 185 | for (std::size_t i = 0; i < player_connected.size(); ++i) { |
| 186 | const auto connected = Settings::values.players[i].connected || | ||
| 187 | (i == 0 && Settings::values.players[8].connected); | ||
| 188 | player_connected[i]->setChecked(connected); | ||
| 183 | } | 189 | } |
| 190 | } | ||
| 184 | 191 | ||
| 185 | ui->handheld_connected->setChecked(ui->handheld_connected->isChecked() && | 192 | void ConfigureInput::ClearAll() { |
| 186 | !ui->use_docked_mode->isChecked()); | 193 | // We don't have a good way to know what tab is active, but we can find out by getting the |
| 187 | ui->handheld_connected->setEnabled(!ui->use_docked_mode->isChecked()); | 194 | // parent of the consoleInputSettings |
| 188 | ui->handheld_configure->setEnabled(ui->handheld_connected->isChecked() && | 195 | auto* player_tab = static_cast<ConfigureInputPlayer*>(ui->consoleInputSettings->parent()); |
| 189 | !ui->use_docked_mode->isChecked()); | 196 | player_tab->ClearAll(); |
| 190 | ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked()); | ||
| 191 | ui->debug_configure->setEnabled(ui->debug_enabled->isChecked()); | ||
| 192 | ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); | ||
| 193 | } | 197 | } |
| 194 | 198 | ||
| 195 | void ConfigureInput::LoadConfiguration() { | 199 | void ConfigureInput::RestoreDefaults() { |
| 196 | std::stable_partition( | 200 | // We don't have a good way to know what tab is active, but we can find out by getting the |
| 197 | Settings::values.players.begin(), | 201 | // parent of the consoleInputSettings |
| 198 | Settings::values.players.begin() + | 202 | auto* player_tab = static_cast<ConfigureInputPlayer*>(ui->consoleInputSettings->parent()); |
| 199 | Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD), | 203 | player_tab->RestoreDefaults(); |
| 200 | [](const auto& player) { return player.connected; }); | 204 | |
| 205 | ui->radioDocked->setChecked(true); | ||
| 206 | ui->radioUndocked->setChecked(false); | ||
| 207 | ui->vibrationGroup->setChecked(true); | ||
| 208 | } | ||
| 201 | 209 | ||
| 202 | LoadPlayerControllerIndices(); | 210 | void ConfigureInput::UpdateDockedState(bool is_handheld) { |
| 211 | // If the controller type is handheld only, disallow changing docked mode | ||
| 212 | ui->radioDocked->setEnabled(!is_handheld); | ||
| 213 | ui->radioUndocked->setEnabled(!is_handheld); | ||
| 203 | 214 | ||
| 204 | ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); | 215 | ui->radioDocked->setChecked(Settings::values.use_docked_mode); |
| 205 | ui->handheld_connected->setChecked( | 216 | ui->radioUndocked->setChecked(!Settings::values.use_docked_mode); |
| 206 | Settings::values | ||
| 207 | .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)] | ||
| 208 | .connected); | ||
| 209 | ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled); | ||
| 210 | ui->mouse_enabled->setChecked(Settings::values.mouse_enabled); | ||
| 211 | ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); | ||
| 212 | ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); | ||
| 213 | |||
| 214 | UpdateUIEnabled(); | ||
| 215 | } | ||
| 216 | 217 | ||
| 217 | void ConfigureInput::LoadPlayerControllerIndices() { | 218 | // If its handheld only, force docked mode off (since you can't play handheld in a dock) |
| 218 | for (std::size_t i = 0; i < players_controller.size(); ++i) { | 219 | if (is_handheld) { |
| 219 | const auto connected = Settings::values.players[i].connected; | 220 | ui->radioUndocked->setChecked(true); |
| 220 | players_controller[i]->setCurrentIndex( | ||
| 221 | connected ? static_cast<u8>(Settings::values.players[i].type) + 1 : 0); | ||
| 222 | } | 221 | } |
| 223 | } | 222 | } |
| 224 | 223 | ||
| 225 | void ConfigureInput::RestoreDefaults() { | 224 | void ConfigureInput::UpdateAllInputDevices() { |
| 226 | players_controller[0]->setCurrentIndex(2); | 225 | for (const auto& player : player_controllers) { |
| 227 | 226 | player->UpdateInputDevices(); | |
| 228 | for (std::size_t i = 1; i < players_controller.size(); ++i) { | ||
| 229 | players_controller[i]->setCurrentIndex(0); | ||
| 230 | } | 227 | } |
| 231 | |||
| 232 | ui->use_docked_mode->setCheckState(Qt::Unchecked); | ||
| 233 | ui->handheld_connected->setCheckState(Qt::Unchecked); | ||
| 234 | ui->mouse_enabled->setCheckState(Qt::Unchecked); | ||
| 235 | ui->keyboard_enabled->setCheckState(Qt::Unchecked); | ||
| 236 | ui->debug_enabled->setCheckState(Qt::Unchecked); | ||
| 237 | ui->touchscreen_enabled->setCheckState(Qt::Checked); | ||
| 238 | UpdateUIEnabled(); | ||
| 239 | } | 228 | } |
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index 2f70cb3ca..d08a24f96 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h | |||
| @@ -7,37 +7,50 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | 9 | ||
| 10 | #include <QDialog> | ||
| 11 | #include <QKeyEvent> | 10 | #include <QKeyEvent> |
| 11 | #include <QWidget> | ||
| 12 | |||
| 13 | #include "yuzu/configuration/configure_input_advanced.h" | ||
| 14 | #include "yuzu/configuration/configure_input_player.h" | ||
| 12 | 15 | ||
| 13 | #include "ui_configure_input.h" | 16 | #include "ui_configure_input.h" |
| 14 | 17 | ||
| 15 | class QPushButton; | 18 | class QCheckBox; |
| 16 | class QString; | 19 | class QString; |
| 17 | class QTimer; | 20 | class QTimer; |
| 18 | 21 | ||
| 22 | namespace InputCommon { | ||
| 23 | class InputSubsystem; | ||
| 24 | } | ||
| 25 | |||
| 19 | namespace Ui { | 26 | namespace Ui { |
| 20 | class ConfigureInput; | 27 | class ConfigureInput; |
| 21 | } | 28 | } |
| 22 | 29 | ||
| 23 | void OnDockedModeChanged(bool last_state, bool new_state); | 30 | void OnDockedModeChanged(bool last_state, bool new_state); |
| 24 | 31 | ||
| 25 | class ConfigureInput : public QDialog { | 32 | class ConfigureInput : public QWidget { |
| 26 | Q_OBJECT | 33 | Q_OBJECT |
| 27 | 34 | ||
| 28 | public: | 35 | public: |
| 29 | explicit ConfigureInput(QWidget* parent = nullptr); | 36 | explicit ConfigureInput(QWidget* parent = nullptr); |
| 30 | ~ConfigureInput() override; | 37 | ~ConfigureInput() override; |
| 31 | 38 | ||
| 32 | /// Save all button configurations to settings file | 39 | /// Initializes the input dialog with the given input subsystem. |
| 40 | void Initialize(InputCommon::InputSubsystem* input_subsystem_); | ||
| 41 | |||
| 42 | /// Save all button configurations to settings file. | ||
| 33 | void ApplyConfiguration(); | 43 | void ApplyConfiguration(); |
| 34 | 44 | ||
| 45 | QList<QWidget*> GetSubTabs() const; | ||
| 46 | |||
| 35 | private: | 47 | private: |
| 36 | void changeEvent(QEvent* event) override; | 48 | void changeEvent(QEvent* event) override; |
| 37 | void RetranslateUI(); | 49 | void RetranslateUI(); |
| 38 | void RetranslateControllerComboBoxes(); | 50 | void ClearAll(); |
| 39 | 51 | ||
| 40 | void UpdateUIEnabled(); | 52 | void UpdateDockedState(bool is_handheld); |
| 53 | void UpdateAllInputDevices(); | ||
| 41 | 54 | ||
| 42 | /// Load configuration settings. | 55 | /// Load configuration settings. |
| 43 | void LoadConfiguration(); | 56 | void LoadConfiguration(); |
| @@ -48,6 +61,8 @@ private: | |||
| 48 | 61 | ||
| 49 | std::unique_ptr<Ui::ConfigureInput> ui; | 62 | std::unique_ptr<Ui::ConfigureInput> ui; |
| 50 | 63 | ||
| 51 | std::array<QComboBox*, 8> players_controller; | 64 | std::array<ConfigureInputPlayer*, 8> player_controllers; |
| 52 | std::array<QPushButton*, 8> players_configure; | 65 | std::array<QWidget*, 8> player_tabs; |
| 66 | std::array<QCheckBox*, 8> player_connected; | ||
| 67 | ConfigureInputAdvanced* advanced; | ||
| 53 | }; | 68 | }; |
diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index efffd8487..136955224 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui | |||
| @@ -1,529 +1,554 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
| 2 | <ui version="4.0"> | 2 | <ui version="4.0"> |
| 3 | <class>ConfigureInput</class> | 3 | <class>ConfigureInput</class> |
| 4 | <widget class="QDialog" name="ConfigureInput"> | 4 | <widget class="QWidget" name="ConfigureInput"> |
| 5 | <property name="geometry"> | 5 | <property name="geometry"> |
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>384</width> | 9 | <width>700</width> |
| 10 | <height>576</height> | 10 | <height>540</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Custom Input Settings</string> | 14 | <string>ConfigureInput</string> |
| 15 | </property> | 15 | </property> |
| 16 | <layout class="QVBoxLayout" name="verticalLayout_5"> | 16 | <layout class="QVBoxLayout" name="verticalLayout_5"> |
| 17 | <property name="spacing"> | ||
| 18 | <number>2</number> | ||
| 19 | </property> | ||
| 20 | <property name="leftMargin"> | ||
| 21 | <number>3</number> | ||
| 22 | </property> | ||
| 23 | <property name="topMargin"> | ||
| 24 | <number>3</number> | ||
| 25 | </property> | ||
| 26 | <property name="rightMargin"> | ||
| 27 | <number>3</number> | ||
| 28 | </property> | ||
| 29 | <property name="bottomMargin"> | ||
| 30 | <number>3</number> | ||
| 31 | </property> | ||
| 17 | <item> | 32 | <item> |
| 18 | <layout class="QVBoxLayout" name="verticalLayout"> | 33 | <widget class="QTabWidget" name="tabWidget"> |
| 19 | <item> | 34 | <property name="currentIndex"> |
| 20 | <widget class="QGroupBox" name="gridGroupBox_1"> | 35 | <number>0</number> |
| 21 | <property name="title"> | 36 | </property> |
| 22 | <string>Players</string> | 37 | <widget class="QWidget" name="tabPlayer1"> |
| 23 | </property> | 38 | <property name="accessibleName"> |
| 24 | <layout class="QGridLayout" name="gridLayout"> | 39 | <string>Player 1</string> |
| 25 | <item row="1" column="2"> | 40 | </property> |
| 26 | <widget class="QComboBox" name="player1_combobox"> | 41 | <attribute name="title"> |
| 27 | <property name="minimumSize"> | 42 | <string>Player 1</string> |
| 28 | <size> | 43 | </attribute> |
| 29 | <width>110</width> | 44 | </widget> |
| 30 | <height>0</height> | 45 | <widget class="QWidget" name="tabPlayer2"> |
| 31 | </size> | 46 | <property name="accessibleName"> |
| 32 | </property> | 47 | <string>Player 2</string> |
| 33 | </widget> | 48 | </property> |
| 34 | </item> | 49 | <attribute name="title"> |
| 35 | <item row="1" column="3"> | 50 | <string>Player 2</string> |
| 36 | <widget class="QPushButton" name="player1_configure"> | 51 | </attribute> |
| 37 | <property name="text"> | 52 | </widget> |
| 38 | <string>Configure</string> | 53 | <widget class="QWidget" name="tabPlayer3"> |
| 39 | </property> | 54 | <property name="accessibleName"> |
| 40 | </widget> | 55 | <string>Player 3</string> |
| 41 | </item> | 56 | </property> |
| 42 | <item row="0" column="2"> | 57 | <attribute name="title"> |
| 43 | <widget class="QLabel" name="label"> | 58 | <string>Player 3</string> |
| 44 | <property name="text"> | 59 | </attribute> |
| 45 | <string>Controller Type</string> | 60 | </widget> |
| 46 | </property> | 61 | <widget class="QWidget" name="tabPlayer4"> |
| 47 | <property name="alignment"> | 62 | <property name="accessibleName"> |
| 48 | <set>Qt::AlignCenter</set> | 63 | <string>Player 4</string> |
| 49 | </property> | 64 | </property> |
| 50 | </widget> | 65 | <attribute name="title"> |
| 51 | </item> | 66 | <string>Player 4</string> |
| 52 | <item row="2" column="2"> | 67 | </attribute> |
| 53 | <widget class="QComboBox" name="player2_combobox"> | 68 | </widget> |
| 54 | <property name="minimumSize"> | 69 | <widget class="QWidget" name="tabPlayer5"> |
| 55 | <size> | 70 | <property name="accessibleName"> |
| 56 | <width>110</width> | 71 | <string>Player 5</string> |
| 57 | <height>0</height> | 72 | </property> |
| 58 | </size> | 73 | <attribute name="title"> |
| 59 | </property> | 74 | <string>Player 5</string> |
| 60 | </widget> | 75 | </attribute> |
| 61 | </item> | 76 | </widget> |
| 62 | <item row="3" column="2"> | 77 | <widget class="QWidget" name="tabPlayer6"> |
| 63 | <widget class="QComboBox" name="player3_combobox"> | 78 | <property name="accessibleName"> |
| 64 | <property name="minimumSize"> | 79 | <string>Player 6</string> |
| 65 | <size> | 80 | </property> |
| 66 | <width>110</width> | 81 | <attribute name="title"> |
| 67 | <height>0</height> | 82 | <string>Player 6</string> |
| 68 | </size> | 83 | </attribute> |
| 69 | </property> | 84 | </widget> |
| 70 | </widget> | 85 | <widget class="QWidget" name="tabPlayer7"> |
| 71 | </item> | 86 | <property name="accessibleName"> |
| 72 | <item row="4" column="2"> | 87 | <string>Player 7</string> |
| 73 | <widget class="QComboBox" name="player4_combobox"> | 88 | </property> |
| 74 | <property name="minimumSize"> | 89 | <attribute name="title"> |
| 75 | <size> | 90 | <string>Player 7</string> |
| 76 | <width>110</width> | 91 | </attribute> |
| 77 | <height>0</height> | 92 | </widget> |
| 78 | </size> | 93 | <widget class="QWidget" name="tabPlayer8"> |
| 79 | </property> | 94 | <property name="accessibleName"> |
| 80 | </widget> | 95 | <string>Player 8</string> |
| 81 | </item> | 96 | </property> |
| 82 | <item row="5" column="2"> | 97 | <attribute name="title"> |
| 83 | <widget class="QComboBox" name="player5_combobox"> | 98 | <string>Player 8</string> |
| 84 | <property name="minimumSize"> | 99 | </attribute> |
| 85 | <size> | 100 | </widget> |
| 86 | <width>110</width> | 101 | <widget class="QWidget" name="tabAdvanced"> |
| 87 | <height>0</height> | 102 | <property name="accessibleName"> |
| 88 | </size> | 103 | <string>Advanced</string> |
| 89 | </property> | 104 | </property> |
| 90 | </widget> | 105 | <attribute name="title"> |
| 91 | </item> | 106 | <string>Advanced</string> |
| 92 | <item row="6" column="2"> | 107 | </attribute> |
| 93 | <widget class="QComboBox" name="player6_combobox"> | 108 | </widget> |
| 94 | <property name="minimumSize"> | 109 | </widget> |
| 95 | <size> | 110 | </item> |
| 96 | <width>110</width> | 111 | <item alignment="Qt::AlignVCenter"> |
| 97 | <height>0</height> | 112 | <widget class="QWidget" name="consoleInputSettings" native="true"> |
| 98 | </size> | 113 | <layout class="QHBoxLayout" name="buttonsBottomRightHorizontalLayout"> |
| 99 | </property> | 114 | <property name="spacing"> |
| 100 | </widget> | 115 | <number>3</number> |
| 101 | </item> | 116 | </property> |
| 102 | <item row="7" column="2"> | 117 | <property name="leftMargin"> |
| 103 | <widget class="QComboBox" name="player7_combobox"> | 118 | <number>0</number> |
| 104 | <property name="minimumSize"> | 119 | </property> |
| 105 | <size> | 120 | <property name="topMargin"> |
| 106 | <width>110</width> | 121 | <number>3</number> |
| 107 | <height>0</height> | 122 | </property> |
| 108 | </size> | 123 | <property name="rightMargin"> |
| 109 | </property> | 124 | <number>0</number> |
| 110 | </widget> | 125 | </property> |
| 111 | </item> | 126 | <property name="bottomMargin"> |
| 112 | <item row="8" column="2"> | 127 | <number>0</number> |
| 113 | <widget class="QComboBox" name="player8_combobox"> | 128 | </property> |
| 114 | <property name="minimumSize"> | 129 | <item alignment="Qt::AlignVCenter"> |
| 115 | <size> | 130 | <widget class="QGroupBox" name="handheldGroup"> |
| 116 | <width>110</width> | 131 | <property name="maximumSize"> |
| 117 | <height>0</height> | 132 | <size> |
| 118 | </size> | 133 | <width>16777215</width> |
| 119 | </property> | 134 | <height>16777215</height> |
| 120 | </widget> | 135 | </size> |
| 121 | </item> | 136 | </property> |
| 122 | <item row="2" column="3"> | 137 | <property name="title"> |
| 123 | <widget class="QPushButton" name="player2_configure"> | 138 | <string>Console Mode</string> |
| 124 | <property name="text"> | 139 | </property> |
| 125 | <string>Configure</string> | 140 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| 126 | </property> | 141 | <property name="spacing"> |
| 127 | </widget> | 142 | <number>6</number> |
| 128 | </item> | 143 | </property> |
| 129 | <item row="3" column="3"> | 144 | <property name="leftMargin"> |
| 130 | <widget class="QPushButton" name="player3_configure"> | 145 | <number>3</number> |
| 131 | <property name="text"> | 146 | </property> |
| 132 | <string>Configure</string> | 147 | <property name="topMargin"> |
| 133 | </property> | 148 | <number>6</number> |
| 134 | </widget> | 149 | </property> |
| 135 | </item> | 150 | <property name="rightMargin"> |
| 136 | <item row="4" column="3"> | 151 | <number>3</number> |
| 137 | <widget class="QPushButton" name="player4_configure"> | 152 | </property> |
| 138 | <property name="text"> | 153 | <property name="bottomMargin"> |
| 139 | <string>Configure</string> | 154 | <number>6</number> |
| 140 | </property> | 155 | </property> |
| 141 | </widget> | 156 | <item> |
| 142 | </item> | 157 | <widget class="QRadioButton" name="radioDocked"> |
| 143 | <item row="5" column="3"> | 158 | <property name="text"> |
| 144 | <widget class="QPushButton" name="player5_configure"> | 159 | <string>Docked</string> |
| 145 | <property name="text"> | 160 | </property> |
| 146 | <string>Configure</string> | 161 | <property name="checked"> |
| 147 | </property> | 162 | <bool>true</bool> |
| 148 | </widget> | 163 | </property> |
| 149 | </item> | 164 | </widget> |
| 150 | <item row="6" column="3"> | 165 | </item> |
| 151 | <widget class="QPushButton" name="player6_configure"> | 166 | <item> |
| 152 | <property name="text"> | 167 | <widget class="QRadioButton" name="radioUndocked"> |
| 153 | <string>Configure</string> | 168 | <property name="text"> |
| 154 | </property> | 169 | <string>Undocked</string> |
| 155 | </widget> | 170 | </property> |
| 156 | </item> | 171 | </widget> |
| 157 | <item row="7" column="3"> | 172 | </item> |
| 158 | <widget class="QPushButton" name="player7_configure"> | 173 | </layout> |
| 159 | <property name="text"> | 174 | </widget> |
| 160 | <string>Configure</string> | 175 | </item> |
| 161 | </property> | 176 | <item> |
| 162 | </widget> | 177 | <widget class="QGroupBox" name="vibrationGroup"> |
| 163 | </item> | 178 | <property name="title"> |
| 164 | <item row="8" column="3"> | 179 | <string>Vibration</string> |
| 165 | <widget class="QPushButton" name="player8_configure"> | 180 | </property> |
| 166 | <property name="text"> | 181 | <property name="checkable"> |
| 167 | <string>Configure</string> | 182 | <bool>true</bool> |
| 168 | </property> | 183 | </property> |
| 169 | </widget> | 184 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 170 | </item> | 185 | <property name="leftMargin"> |
| 171 | <item row="0" column="0"> | 186 | <number>3</number> |
| 172 | <spacer name="horizontalSpacer"> | 187 | </property> |
| 173 | <property name="orientation"> | 188 | <property name="topMargin"> |
| 174 | <enum>Qt::Horizontal</enum> | 189 | <number>3</number> |
| 175 | </property> | 190 | </property> |
| 176 | <property name="sizeHint" stdset="0"> | 191 | <property name="rightMargin"> |
| 177 | <size> | 192 | <number>3</number> |
| 178 | <width>40</width> | 193 | </property> |
| 179 | <height>20</height> | 194 | <property name="bottomMargin"> |
| 180 | </size> | 195 | <number>3</number> |
| 181 | </property> | 196 | </property> |
| 182 | </spacer> | 197 | <item> |
| 183 | </item> | 198 | <widget class="QSpinBox" name="vibrationSpin"> |
| 184 | <item row="0" column="4"> | 199 | <property name="minimumSize"> |
| 185 | <spacer name="horizontalSpacer_2"> | 200 | <size> |
| 186 | <property name="orientation"> | 201 | <width>65</width> |
| 187 | <enum>Qt::Horizontal</enum> | 202 | <height>21</height> |
| 188 | </property> | 203 | </size> |
| 189 | <property name="sizeHint" stdset="0"> | 204 | </property> |
| 190 | <size> | 205 | <property name="maximumSize"> |
| 191 | <width>40</width> | 206 | <size> |
| 192 | <height>20</height> | 207 | <width>65</width> |
| 193 | </size> | 208 | <height>16777215</height> |
| 194 | </property> | 209 | </size> |
| 195 | </spacer> | 210 | </property> |
| 196 | </item> | 211 | <property name="suffix"> |
| 197 | <item row="1" column="1"> | 212 | <string>%</string> |
| 198 | <widget class="QLabel" name="label_3"> | 213 | </property> |
| 199 | <property name="minimumSize"> | 214 | <property name="minimum"> |
| 200 | <size> | 215 | <number>1</number> |
| 201 | <width>55</width> | 216 | </property> |
| 202 | <height>0</height> | 217 | <property name="maximum"> |
| 203 | </size> | 218 | <number>200</number> |
| 204 | </property> | 219 | </property> |
| 205 | <property name="text"> | 220 | <property name="value"> |
| 206 | <string>Player 1</string> | 221 | <number>100</number> |
| 207 | </property> | 222 | </property> |
| 208 | </widget> | 223 | </widget> |
| 209 | </item> | 224 | </item> |
| 210 | <item row="2" column="1"> | 225 | </layout> |
| 211 | <widget class="QLabel" name="label_4"> | 226 | </widget> |
| 212 | <property name="text"> | 227 | </item> |
| 213 | <string>Player 2</string> | 228 | <item> |
| 214 | </property> | 229 | <widget class="QGroupBox" name="motionGroup"> |
| 215 | </widget> | 230 | <property name="title"> |
| 216 | </item> | 231 | <string>Motion</string> |
| 217 | <item row="3" column="1"> | 232 | </property> |
| 218 | <widget class="QLabel" name="label_5"> | 233 | <property name="checkable"> |
| 219 | <property name="text"> | 234 | <bool>true</bool> |
| 220 | <string>Player 3</string> | 235 | </property> |
| 221 | </property> | 236 | <layout class="QHBoxLayout" name="horizontalLayout_3"> |
| 222 | </widget> | 237 | <property name="leftMargin"> |
| 223 | </item> | 238 | <number>3</number> |
| 224 | <item row="4" column="1"> | 239 | </property> |
| 225 | <widget class="QLabel" name="label_6"> | 240 | <property name="topMargin"> |
| 226 | <property name="text"> | 241 | <number>3</number> |
| 227 | <string>Player 4</string> | 242 | </property> |
| 228 | </property> | 243 | <property name="rightMargin"> |
| 229 | </widget> | 244 | <number>3</number> |
| 230 | </item> | 245 | </property> |
| 231 | <item row="5" column="1"> | 246 | <property name="bottomMargin"> |
| 232 | <widget class="QLabel" name="label_7"> | 247 | <number>3</number> |
| 233 | <property name="text"> | 248 | </property> |
| 234 | <string>Player 5</string> | 249 | <item> |
| 235 | </property> | 250 | <widget class="QPushButton" name="motionButton"> |
| 236 | </widget> | 251 | <property name="minimumSize"> |
| 237 | </item> | 252 | <size> |
| 238 | <item row="6" column="1"> | 253 | <width>57</width> |
| 239 | <widget class="QLabel" name="label_8"> | 254 | <height>0</height> |
| 240 | <property name="text"> | 255 | </size> |
| 241 | <string>Player 6</string> | 256 | </property> |
| 242 | </property> | 257 | <property name="maximumSize"> |
| 243 | </widget> | 258 | <size> |
| 244 | </item> | 259 | <width>55</width> |
| 245 | <item row="7" column="1"> | 260 | <height>16777215</height> |
| 246 | <widget class="QLabel" name="label_9"> | 261 | </size> |
| 247 | <property name="text"> | 262 | </property> |
| 248 | <string>Player 7</string> | 263 | <property name="styleSheet"> |
| 249 | </property> | 264 | <string notr="true">min-width: 55px;</string> |
| 250 | </widget> | 265 | </property> |
| 251 | </item> | 266 | <property name="text"> |
| 252 | <item row="8" column="1"> | 267 | <string>Configure</string> |
| 253 | <widget class="QLabel" name="label_10"> | 268 | </property> |
| 254 | <property name="text"> | 269 | </widget> |
| 255 | <string>Player 8</string> | 270 | </item> |
| 256 | </property> | 271 | </layout> |
| 257 | </widget> | 272 | </widget> |
| 258 | </item> | 273 | </item> |
| 259 | </layout> | 274 | <item alignment="Qt::AlignVCenter"> |
| 260 | </widget> | 275 | <widget class="QWidget" name="widget" native="true"> |
| 261 | </item> | 276 | <layout class="QGridLayout" name="gridLayout_2"> |
| 262 | <item> | 277 | <property name="leftMargin"> |
| 263 | <widget class="QGroupBox" name="gridGroupBox_2"> | 278 | <number>5</number> |
| 264 | <property name="title"> | 279 | </property> |
| 265 | <string>Handheld</string> | 280 | <property name="topMargin"> |
| 266 | </property> | 281 | <number>0</number> |
| 267 | <layout class="QGridLayout" name="gridLayout_2"> | ||
| 268 | <item row="1" column="2"> | ||
| 269 | <spacer name="horizontalSpacer_5"> | ||
| 270 | <property name="orientation"> | ||
| 271 | <enum>Qt::Horizontal</enum> | ||
| 272 | </property> | ||
| 273 | <property name="sizeType"> | ||
| 274 | <enum>QSizePolicy::Fixed</enum> | ||
| 275 | </property> | ||
| 276 | <property name="sizeHint" stdset="0"> | ||
| 277 | <size> | ||
| 278 | <width>72</width> | ||
| 279 | <height>20</height> | ||
| 280 | </size> | ||
| 281 | </property> | ||
| 282 | </spacer> | ||
| 283 | </item> | ||
| 284 | <item row="1" column="4"> | ||
| 285 | <spacer name="horizontalSpacer_4"> | ||
| 286 | <property name="orientation"> | ||
| 287 | <enum>Qt::Horizontal</enum> | ||
| 288 | </property> | ||
| 289 | <property name="sizeHint" stdset="0"> | ||
| 290 | <size> | ||
| 291 | <width>40</width> | ||
| 292 | <height>20</height> | ||
| 293 | </size> | ||
| 294 | </property> | ||
| 295 | </spacer> | ||
| 296 | </item> | ||
| 297 | <item row="1" column="3"> | ||
| 298 | <widget class="QPushButton" name="handheld_configure"> | ||
| 299 | <property name="text"> | ||
| 300 | <string>Configure</string> | ||
| 301 | </property> | ||
| 302 | </widget> | ||
| 303 | </item> | ||
| 304 | <item row="1" column="0"> | ||
| 305 | <spacer name="horizontalSpacer_3"> | ||
| 306 | <property name="orientation"> | ||
| 307 | <enum>Qt::Horizontal</enum> | ||
| 308 | </property> | ||
| 309 | <property name="sizeHint" stdset="0"> | ||
| 310 | <size> | ||
| 311 | <width>40</width> | ||
| 312 | <height>20</height> | ||
| 313 | </size> | ||
| 314 | </property> | ||
| 315 | </spacer> | ||
| 316 | </item> | ||
| 317 | <item row="1" column="1"> | ||
| 318 | <widget class="QCheckBox" name="handheld_connected"> | ||
| 319 | <property name="text"> | ||
| 320 | <string>Joycons Docked</string> | ||
| 321 | </property> | ||
| 322 | </widget> | ||
| 323 | </item> | ||
| 324 | <item row="0" column="1"> | ||
| 325 | <widget class="QCheckBox" name="use_docked_mode"> | ||
| 326 | <property name="text"> | ||
| 327 | <string>Use Docked Mode</string> | ||
| 328 | </property> | ||
| 329 | </widget> | ||
| 330 | </item> | ||
| 331 | </layout> | ||
| 332 | </widget> | ||
| 333 | </item> | ||
| 334 | <item> | ||
| 335 | <widget class="QGroupBox" name="gridGroupBox_3"> | ||
| 336 | <property name="title"> | ||
| 337 | <string>Other</string> | ||
| 338 | </property> | ||
| 339 | <layout class="QGridLayout" name="gridLayout_3"> | ||
| 340 | <item row="1" column="1"> | ||
| 341 | <widget class="QCheckBox" name="keyboard_enabled"> | ||
| 342 | <property name="minimumSize"> | ||
| 343 | <size> | ||
| 344 | <width>0</width> | ||
| 345 | <height>23</height> | ||
| 346 | </size> | ||
| 347 | </property> | ||
| 348 | <property name="text"> | ||
| 349 | <string>Keyboard</string> | ||
| 350 | </property> | ||
| 351 | </widget> | ||
| 352 | </item> | ||
| 353 | <item row="2" column="1"> | ||
| 354 | <widget class="QCheckBox" name="debug_enabled"> | ||
| 355 | <property name="text"> | ||
| 356 | <string>Debug Controller</string> | ||
| 357 | </property> | ||
| 358 | </widget> | ||
| 359 | </item> | ||
| 360 | <item row="3" column="1"> | ||
| 361 | <widget class="QCheckBox" name="touchscreen_enabled"> | ||
| 362 | <property name="text"> | ||
| 363 | <string>Touchscreen</string> | ||
| 364 | </property> | ||
| 365 | </widget> | ||
| 366 | </item> | ||
| 367 | <item row="0" column="1"> | ||
| 368 | <widget class="QCheckBox" name="mouse_enabled"> | ||
| 369 | <property name="minimumSize"> | ||
| 370 | <size> | ||
| 371 | <width>0</width> | ||
| 372 | <height>23</height> | ||
| 373 | </size> | ||
| 374 | </property> | ||
| 375 | <property name="text"> | ||
| 376 | <string>Mouse</string> | ||
| 377 | </property> | ||
| 378 | </widget> | ||
| 379 | </item> | ||
| 380 | <item row="0" column="4"> | ||
| 381 | <spacer name="horizontalSpacer_7"> | ||
| 382 | <property name="orientation"> | ||
| 383 | <enum>Qt::Horizontal</enum> | ||
| 384 | </property> | ||
| 385 | <property name="sizeHint" stdset="0"> | ||
| 386 | <size> | ||
| 387 | <width>40</width> | ||
| 388 | <height>20</height> | ||
| 389 | </size> | ||
| 390 | </property> | ||
| 391 | </spacer> | ||
| 392 | </item> | ||
| 393 | <item row="0" column="2"> | ||
| 394 | <spacer name="horizontalSpacer_8"> | ||
| 395 | <property name="orientation"> | ||
| 396 | <enum>Qt::Horizontal</enum> | ||
| 397 | </property> | ||
| 398 | <property name="sizeType"> | ||
| 399 | <enum>QSizePolicy::Fixed</enum> | ||
| 400 | </property> | ||
| 401 | <property name="sizeHint" stdset="0"> | ||
| 402 | <size> | ||
| 403 | <width>76</width> | ||
| 404 | <height>20</height> | ||
| 405 | </size> | ||
| 406 | </property> | ||
| 407 | </spacer> | ||
| 408 | </item> | ||
| 409 | <item row="0" column="0"> | ||
| 410 | <spacer name="horizontalSpacer_6"> | ||
| 411 | <property name="orientation"> | ||
| 412 | <enum>Qt::Horizontal</enum> | ||
| 413 | </property> | ||
| 414 | <property name="sizeHint" stdset="0"> | ||
| 415 | <size> | ||
| 416 | <width>40</width> | ||
| 417 | <height>20</height> | ||
| 418 | </size> | ||
| 419 | </property> | ||
| 420 | </spacer> | ||
| 421 | </item> | ||
| 422 | <item row="3" column="3"> | ||
| 423 | <widget class="QPushButton" name="touchscreen_advanced"> | ||
| 424 | <property name="text"> | ||
| 425 | <string>Advanced</string> | ||
| 426 | </property> | ||
| 427 | </widget> | ||
| 428 | </item> | ||
| 429 | <item row="2" column="3"> | ||
| 430 | <widget class="QPushButton" name="debug_configure"> | ||
| 431 | <property name="text"> | ||
| 432 | <string>Configure</string> | ||
| 433 | </property> | ||
| 434 | </widget> | ||
| 435 | </item> | ||
| 436 | <item row="0" column="3"> | ||
| 437 | <widget class="QPushButton" name="mouse_advanced"> | ||
| 438 | <property name="text"> | ||
| 439 | <string>Advanced</string> | ||
| 440 | </property> | ||
| 441 | </widget> | ||
| 442 | </item> | ||
| 443 | </layout> | ||
| 444 | </widget> | ||
| 445 | </item> | ||
| 446 | <item> | ||
| 447 | <spacer name="verticalSpacer"> | ||
| 448 | <property name="orientation"> | ||
| 449 | <enum>Qt::Vertical</enum> | ||
| 450 | </property> | ||
| 451 | <property name="sizeHint" stdset="0"> | ||
| 452 | <size> | ||
| 453 | <width>20</width> | ||
| 454 | <height>40</height> | ||
| 455 | </size> | ||
| 456 | </property> | ||
| 457 | </spacer> | ||
| 458 | </item> | ||
| 459 | <item> | ||
| 460 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 461 | <item> | ||
| 462 | <widget class="QPushButton" name="restore_defaults_button"> | ||
| 463 | <property name="text"> | ||
| 464 | <string>Restore Defaults</string> | ||
| 465 | </property> | 282 | </property> |
| 466 | </widget> | 283 | <property name="rightMargin"> |
| 467 | </item> | 284 | <number>0</number> |
| 468 | <item> | ||
| 469 | <spacer name="horizontalSpacer_9"> | ||
| 470 | <property name="orientation"> | ||
| 471 | <enum>Qt::Horizontal</enum> | ||
| 472 | </property> | 285 | </property> |
| 473 | <property name="sizeHint" stdset="0"> | 286 | <property name="bottomMargin"> |
| 474 | <size> | 287 | <number>0</number> |
| 475 | <width>40</width> | ||
| 476 | <height>20</height> | ||
| 477 | </size> | ||
| 478 | </property> | 288 | </property> |
| 479 | </spacer> | 289 | <property name="spacing"> |
| 480 | </item> | 290 | <number>3</number> |
| 481 | <item> | ||
| 482 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 483 | <property name="standardButtons"> | ||
| 484 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 485 | </property> | 291 | </property> |
| 486 | </widget> | 292 | <item row="1" column="2"> |
| 487 | </item> | 293 | <widget class="QCheckBox" name="checkboxPlayer2Connected"> |
| 488 | </layout> | 294 | <property name="text"> |
| 489 | </item> | 295 | <string/> |
| 490 | </layout> | 296 | </property> |
| 297 | </widget> | ||
| 298 | </item> | ||
| 299 | <item row="1" column="0"> | ||
| 300 | <widget class="QLabel" name="label_2"> | ||
| 301 | <property name="text"> | ||
| 302 | <string>Controllers</string> | ||
| 303 | </property> | ||
| 304 | </widget> | ||
| 305 | </item> | ||
| 306 | <item row="1" column="4"> | ||
| 307 | <widget class="QCheckBox" name="checkboxPlayer4Connected"> | ||
| 308 | <property name="text"> | ||
| 309 | <string/> | ||
| 310 | </property> | ||
| 311 | </widget> | ||
| 312 | </item> | ||
| 313 | <item row="1" column="3"> | ||
| 314 | <widget class="QCheckBox" name="checkboxPlayer3Connected"> | ||
| 315 | <property name="text"> | ||
| 316 | <string/> | ||
| 317 | </property> | ||
| 318 | </widget> | ||
| 319 | </item> | ||
| 320 | <item row="1" column="5"> | ||
| 321 | <widget class="QCheckBox" name="checkboxPlayer5Connected"> | ||
| 322 | <property name="text"> | ||
| 323 | <string/> | ||
| 324 | </property> | ||
| 325 | </widget> | ||
| 326 | </item> | ||
| 327 | <item row="0" column="1"> | ||
| 328 | <widget class="QLabel" name="label"> | ||
| 329 | <property name="text"> | ||
| 330 | <string>1</string> | ||
| 331 | </property> | ||
| 332 | <property name="alignment"> | ||
| 333 | <set>Qt::AlignCenter</set> | ||
| 334 | </property> | ||
| 335 | </widget> | ||
| 336 | </item> | ||
| 337 | <item row="1" column="7"> | ||
| 338 | <widget class="QCheckBox" name="checkboxPlayer7Connected"> | ||
| 339 | <property name="text"> | ||
| 340 | <string/> | ||
| 341 | </property> | ||
| 342 | </widget> | ||
| 343 | </item> | ||
| 344 | <item row="1" column="6"> | ||
| 345 | <widget class="QCheckBox" name="checkboxPlayer6Connected"> | ||
| 346 | <property name="text"> | ||
| 347 | <string/> | ||
| 348 | </property> | ||
| 349 | </widget> | ||
| 350 | </item> | ||
| 351 | <item row="1" column="1"> | ||
| 352 | <widget class="QCheckBox" name="checkboxPlayer1Connected"> | ||
| 353 | <property name="layoutDirection"> | ||
| 354 | <enum>Qt::LeftToRight</enum> | ||
| 355 | </property> | ||
| 356 | <property name="checked"> | ||
| 357 | <bool>true</bool> | ||
| 358 | </property> | ||
| 359 | </widget> | ||
| 360 | </item> | ||
| 361 | <item row="1" column="8"> | ||
| 362 | <widget class="QCheckBox" name="checkboxPlayer8Connected"> | ||
| 363 | <property name="text"> | ||
| 364 | <string/> | ||
| 365 | </property> | ||
| 366 | </widget> | ||
| 367 | </item> | ||
| 368 | <item row="0" column="2"> | ||
| 369 | <widget class="QLabel" name="label_3"> | ||
| 370 | <property name="text"> | ||
| 371 | <string>2</string> | ||
| 372 | </property> | ||
| 373 | <property name="alignment"> | ||
| 374 | <set>Qt::AlignCenter</set> | ||
| 375 | </property> | ||
| 376 | </widget> | ||
| 377 | </item> | ||
| 378 | <item row="0" column="3"> | ||
| 379 | <widget class="QLabel" name="label_4"> | ||
| 380 | <property name="text"> | ||
| 381 | <string>3</string> | ||
| 382 | </property> | ||
| 383 | <property name="alignment"> | ||
| 384 | <set>Qt::AlignCenter</set> | ||
| 385 | </property> | ||
| 386 | </widget> | ||
| 387 | </item> | ||
| 388 | <item row="0" column="4"> | ||
| 389 | <widget class="QLabel" name="label_5"> | ||
| 390 | <property name="text"> | ||
| 391 | <string>4</string> | ||
| 392 | </property> | ||
| 393 | <property name="alignment"> | ||
| 394 | <set>Qt::AlignCenter</set> | ||
| 395 | </property> | ||
| 396 | </widget> | ||
| 397 | </item> | ||
| 398 | <item row="0" column="5"> | ||
| 399 | <widget class="QLabel" name="label_6"> | ||
| 400 | <property name="text"> | ||
| 401 | <string>5</string> | ||
| 402 | </property> | ||
| 403 | <property name="alignment"> | ||
| 404 | <set>Qt::AlignCenter</set> | ||
| 405 | </property> | ||
| 406 | </widget> | ||
| 407 | </item> | ||
| 408 | <item row="0" column="6"> | ||
| 409 | <widget class="QLabel" name="label_7"> | ||
| 410 | <property name="text"> | ||
| 411 | <string>6</string> | ||
| 412 | </property> | ||
| 413 | <property name="alignment"> | ||
| 414 | <set>Qt::AlignCenter</set> | ||
| 415 | </property> | ||
| 416 | </widget> | ||
| 417 | </item> | ||
| 418 | <item row="0" column="7"> | ||
| 419 | <widget class="QLabel" name="label_8"> | ||
| 420 | <property name="text"> | ||
| 421 | <string>7</string> | ||
| 422 | </property> | ||
| 423 | <property name="alignment"> | ||
| 424 | <set>Qt::AlignCenter</set> | ||
| 425 | </property> | ||
| 426 | </widget> | ||
| 427 | </item> | ||
| 428 | <item row="0" column="8"> | ||
| 429 | <widget class="QLabel" name="label_9"> | ||
| 430 | <property name="text"> | ||
| 431 | <string>8</string> | ||
| 432 | </property> | ||
| 433 | <property name="alignment"> | ||
| 434 | <set>Qt::AlignCenter</set> | ||
| 435 | </property> | ||
| 436 | </widget> | ||
| 437 | </item> | ||
| 438 | <item row="0" column="0"> | ||
| 439 | <widget class="QLabel" name="label_10"> | ||
| 440 | <property name="text"> | ||
| 441 | <string>Connected</string> | ||
| 442 | </property> | ||
| 443 | </widget> | ||
| 444 | </item> | ||
| 445 | </layout> | ||
| 446 | </widget> | ||
| 447 | </item> | ||
| 448 | <item> | ||
| 449 | <spacer name="horizontalSpacer"> | ||
| 450 | <property name="orientation"> | ||
| 451 | <enum>Qt::Horizontal</enum> | ||
| 452 | </property> | ||
| 453 | <property name="sizeHint" stdset="0"> | ||
| 454 | <size> | ||
| 455 | <width>40</width> | ||
| 456 | <height>20</height> | ||
| 457 | </size> | ||
| 458 | </property> | ||
| 459 | </spacer> | ||
| 460 | </item> | ||
| 461 | <item alignment="Qt::AlignBottom"> | ||
| 462 | <widget class="QPushButton" name="buttonRestoreDefaults"> | ||
| 463 | <property name="sizePolicy"> | ||
| 464 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 465 | <horstretch>0</horstretch> | ||
| 466 | <verstretch>0</verstretch> | ||
| 467 | </sizepolicy> | ||
| 468 | </property> | ||
| 469 | <property name="minimumSize"> | ||
| 470 | <size> | ||
| 471 | <width>57</width> | ||
| 472 | <height>0</height> | ||
| 473 | </size> | ||
| 474 | </property> | ||
| 475 | <property name="maximumSize"> | ||
| 476 | <size> | ||
| 477 | <width>55</width> | ||
| 478 | <height>16777215</height> | ||
| 479 | </size> | ||
| 480 | </property> | ||
| 481 | <property name="sizeIncrement"> | ||
| 482 | <size> | ||
| 483 | <width>0</width> | ||
| 484 | <height>0</height> | ||
| 485 | </size> | ||
| 486 | </property> | ||
| 487 | <property name="baseSize"> | ||
| 488 | <size> | ||
| 489 | <width>0</width> | ||
| 490 | <height>0</height> | ||
| 491 | </size> | ||
| 492 | </property> | ||
| 493 | <property name="layoutDirection"> | ||
| 494 | <enum>Qt::LeftToRight</enum> | ||
| 495 | </property> | ||
| 496 | <property name="styleSheet"> | ||
| 497 | <string notr="true">min-width: 55px;</string> | ||
| 498 | </property> | ||
| 499 | <property name="text"> | ||
| 500 | <string>Defaults</string> | ||
| 501 | </property> | ||
| 502 | </widget> | ||
| 503 | </item> | ||
| 504 | <item alignment="Qt::AlignBottom"> | ||
| 505 | <widget class="QPushButton" name="buttonClearAll"> | ||
| 506 | <property name="sizePolicy"> | ||
| 507 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 508 | <horstretch>0</horstretch> | ||
| 509 | <verstretch>0</verstretch> | ||
| 510 | </sizepolicy> | ||
| 511 | </property> | ||
| 512 | <property name="minimumSize"> | ||
| 513 | <size> | ||
| 514 | <width>57</width> | ||
| 515 | <height>0</height> | ||
| 516 | </size> | ||
| 517 | </property> | ||
| 518 | <property name="maximumSize"> | ||
| 519 | <size> | ||
| 520 | <width>55</width> | ||
| 521 | <height>16777215</height> | ||
| 522 | </size> | ||
| 523 | </property> | ||
| 524 | <property name="sizeIncrement"> | ||
| 525 | <size> | ||
| 526 | <width>0</width> | ||
| 527 | <height>0</height> | ||
| 528 | </size> | ||
| 529 | </property> | ||
| 530 | <property name="baseSize"> | ||
| 531 | <size> | ||
| 532 | <width>0</width> | ||
| 533 | <height>0</height> | ||
| 534 | </size> | ||
| 535 | </property> | ||
| 536 | <property name="layoutDirection"> | ||
| 537 | <enum>Qt::LeftToRight</enum> | ||
| 538 | </property> | ||
| 539 | <property name="styleSheet"> | ||
| 540 | <string notr="true">min-width: 55px;</string> | ||
| 541 | </property> | ||
| 542 | <property name="text"> | ||
| 543 | <string>Clear</string> | ||
| 544 | </property> | ||
| 545 | </widget> | ||
| 546 | </item> | ||
| 547 | </layout> | ||
| 548 | </widget> | ||
| 491 | </item> | 549 | </item> |
| 492 | </layout> | 550 | </layout> |
| 493 | </widget> | 551 | </widget> |
| 494 | <resources/> | 552 | <resources/> |
| 495 | <connections> | 553 | <connections/> |
| 496 | <connection> | ||
| 497 | <sender>buttonBox</sender> | ||
| 498 | <signal>accepted()</signal> | ||
| 499 | <receiver>ConfigureInput</receiver> | ||
| 500 | <slot>accept()</slot> | ||
| 501 | <hints> | ||
| 502 | <hint type="sourcelabel"> | ||
| 503 | <x>294</x> | ||
| 504 | <y>553</y> | ||
| 505 | </hint> | ||
| 506 | <hint type="destinationlabel"> | ||
| 507 | <x>191</x> | ||
| 508 | <y>287</y> | ||
| 509 | </hint> | ||
| 510 | </hints> | ||
| 511 | </connection> | ||
| 512 | <connection> | ||
| 513 | <sender>buttonBox</sender> | ||
| 514 | <signal>rejected()</signal> | ||
| 515 | <receiver>ConfigureInput</receiver> | ||
| 516 | <slot>reject()</slot> | ||
| 517 | <hints> | ||
| 518 | <hint type="sourcelabel"> | ||
| 519 | <x>294</x> | ||
| 520 | <y>553</y> | ||
| 521 | </hint> | ||
| 522 | <hint type="destinationlabel"> | ||
| 523 | <x>191</x> | ||
| 524 | <y>287</y> | ||
| 525 | </hint> | ||
| 526 | </hints> | ||
| 527 | </connection> | ||
| 528 | </connections> | ||
| 529 | </ui> | 554 | </ui> |
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp new file mode 100644 index 000000000..81f9dc16c --- /dev/null +++ b/src/yuzu/configuration/configure_input_advanced.cpp | |||
| @@ -0,0 +1,171 @@ | |||
| 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 <QColorDialog> | ||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/settings.h" | ||
| 8 | #include "ui_configure_input_advanced.h" | ||
| 9 | #include "yuzu/configuration/configure_input_advanced.h" | ||
| 10 | |||
| 11 | ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) | ||
| 12 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputAdvanced>()) { | ||
| 13 | ui->setupUi(this); | ||
| 14 | |||
| 15 | controllers_color_buttons = {{ | ||
| 16 | { | ||
| 17 | ui->player1_left_body_button, | ||
| 18 | ui->player1_left_buttons_button, | ||
| 19 | ui->player1_right_body_button, | ||
| 20 | ui->player1_right_buttons_button, | ||
| 21 | }, | ||
| 22 | { | ||
| 23 | ui->player2_left_body_button, | ||
| 24 | ui->player2_left_buttons_button, | ||
| 25 | ui->player2_right_body_button, | ||
| 26 | ui->player2_right_buttons_button, | ||
| 27 | }, | ||
| 28 | { | ||
| 29 | ui->player3_left_body_button, | ||
| 30 | ui->player3_left_buttons_button, | ||
| 31 | ui->player3_right_body_button, | ||
| 32 | ui->player3_right_buttons_button, | ||
| 33 | }, | ||
| 34 | { | ||
| 35 | ui->player4_left_body_button, | ||
| 36 | ui->player4_left_buttons_button, | ||
| 37 | ui->player4_right_body_button, | ||
| 38 | ui->player4_right_buttons_button, | ||
| 39 | }, | ||
| 40 | { | ||
| 41 | ui->player5_left_body_button, | ||
| 42 | ui->player5_left_buttons_button, | ||
| 43 | ui->player5_right_body_button, | ||
| 44 | ui->player5_right_buttons_button, | ||
| 45 | }, | ||
| 46 | { | ||
| 47 | ui->player6_left_body_button, | ||
| 48 | ui->player6_left_buttons_button, | ||
| 49 | ui->player6_right_body_button, | ||
| 50 | ui->player6_right_buttons_button, | ||
| 51 | }, | ||
| 52 | { | ||
| 53 | ui->player7_left_body_button, | ||
| 54 | ui->player7_left_buttons_button, | ||
| 55 | ui->player7_right_body_button, | ||
| 56 | ui->player7_right_buttons_button, | ||
| 57 | }, | ||
| 58 | { | ||
| 59 | ui->player8_left_body_button, | ||
| 60 | ui->player8_left_buttons_button, | ||
| 61 | ui->player8_right_body_button, | ||
| 62 | ui->player8_right_buttons_button, | ||
| 63 | }, | ||
| 64 | }}; | ||
| 65 | |||
| 66 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { | ||
| 67 | auto& color_buttons = controllers_color_buttons[player_idx]; | ||
| 68 | for (std::size_t button_idx = 0; button_idx < color_buttons.size(); ++button_idx) { | ||
| 69 | connect(color_buttons[button_idx], &QPushButton::clicked, this, | ||
| 70 | [this, player_idx, button_idx] { | ||
| 71 | OnControllerButtonClick(static_cast<int>(player_idx), | ||
| 72 | static_cast<int>(button_idx)); | ||
| 73 | }); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, | ||
| 78 | &ConfigureInputAdvanced::UpdateUIEnabled); | ||
| 79 | connect(ui->debug_enabled, &QCheckBox::stateChanged, this, | ||
| 80 | &ConfigureInputAdvanced::UpdateUIEnabled); | ||
| 81 | connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this, | ||
| 82 | &ConfigureInputAdvanced::UpdateUIEnabled); | ||
| 83 | |||
| 84 | connect(ui->debug_configure, &QPushButton::clicked, this, | ||
| 85 | [this] { CallDebugControllerDialog(); }); | ||
| 86 | connect(ui->mouse_advanced, &QPushButton::clicked, this, [this] { CallMouseConfigDialog(); }); | ||
| 87 | connect(ui->touchscreen_advanced, &QPushButton::clicked, this, | ||
| 88 | [this] { CallTouchscreenConfigDialog(); }); | ||
| 89 | connect(ui->buttonMotionTouch, &QPushButton::clicked, this, | ||
| 90 | &ConfigureInputAdvanced::CallMotionTouchConfigDialog); | ||
| 91 | |||
| 92 | LoadConfiguration(); | ||
| 93 | } | ||
| 94 | |||
| 95 | ConfigureInputAdvanced::~ConfigureInputAdvanced() = default; | ||
| 96 | |||
| 97 | void ConfigureInputAdvanced::OnControllerButtonClick(int player_idx, int button_idx) { | ||
| 98 | const QColor new_bg_color = QColorDialog::getColor(controllers_colors[player_idx][button_idx]); | ||
| 99 | if (!new_bg_color.isValid()) { | ||
| 100 | return; | ||
| 101 | } | ||
| 102 | controllers_colors[player_idx][button_idx] = new_bg_color; | ||
| 103 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( | ||
| 104 | QStringLiteral("background-color: %1; min-width: 55px;") | ||
| 105 | .arg(controllers_colors[player_idx][button_idx].name())); | ||
| 106 | } | ||
| 107 | |||
| 108 | void ConfigureInputAdvanced::ApplyConfiguration() { | ||
| 109 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { | ||
| 110 | auto& player = Settings::values.players[player_idx]; | ||
| 111 | std::array<u32, 4> colors{}; | ||
| 112 | std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(), | ||
| 113 | colors.begin(), [](QColor color) { return color.rgb(); }); | ||
| 114 | |||
| 115 | player.body_color_left = colors[0]; | ||
| 116 | player.button_color_left = colors[1]; | ||
| 117 | player.body_color_right = colors[2]; | ||
| 118 | player.button_color_right = colors[3]; | ||
| 119 | } | ||
| 120 | |||
| 121 | Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked(); | ||
| 122 | Settings::values.mouse_enabled = ui->mouse_enabled->isChecked(); | ||
| 123 | Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked(); | ||
| 124 | Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); | ||
| 125 | } | ||
| 126 | |||
| 127 | void ConfigureInputAdvanced::LoadConfiguration() { | ||
| 128 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { | ||
| 129 | auto& player = Settings::values.players[player_idx]; | ||
| 130 | std::array<u32, 4> colors = { | ||
| 131 | player.body_color_left, | ||
| 132 | player.button_color_left, | ||
| 133 | player.body_color_right, | ||
| 134 | player.button_color_right, | ||
| 135 | }; | ||
| 136 | |||
| 137 | std::transform(colors.begin(), colors.end(), controllers_colors[player_idx].begin(), | ||
| 138 | [](u32 rgb) { return QColor::fromRgb(rgb); }); | ||
| 139 | |||
| 140 | for (std::size_t button_idx = 0; button_idx < colors.size(); ++button_idx) { | ||
| 141 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( | ||
| 142 | QStringLiteral("background-color: %1; min-width: 55px;") | ||
| 143 | .arg(controllers_colors[player_idx][button_idx].name())); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled); | ||
| 148 | ui->mouse_enabled->setChecked(Settings::values.mouse_enabled); | ||
| 149 | ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); | ||
| 150 | ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); | ||
| 151 | |||
| 152 | UpdateUIEnabled(); | ||
| 153 | } | ||
| 154 | |||
| 155 | void ConfigureInputAdvanced::changeEvent(QEvent* event) { | ||
| 156 | if (event->type() == QEvent::LanguageChange) { | ||
| 157 | RetranslateUI(); | ||
| 158 | } | ||
| 159 | |||
| 160 | QWidget::changeEvent(event); | ||
| 161 | } | ||
| 162 | |||
| 163 | void ConfigureInputAdvanced::RetranslateUI() { | ||
| 164 | ui->retranslateUi(this); | ||
| 165 | } | ||
| 166 | |||
| 167 | void ConfigureInputAdvanced::UpdateUIEnabled() { | ||
| 168 | ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked()); | ||
| 169 | ui->debug_configure->setEnabled(ui->debug_enabled->isChecked()); | ||
| 170 | ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); | ||
| 171 | } | ||
diff --git a/src/yuzu/configuration/configure_input_advanced.h b/src/yuzu/configuration/configure_input_advanced.h new file mode 100644 index 000000000..50bb87768 --- /dev/null +++ b/src/yuzu/configuration/configure_input_advanced.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <memory> | ||
| 9 | #include <QWidget> | ||
| 10 | |||
| 11 | class QColor; | ||
| 12 | class QPushButton; | ||
| 13 | |||
| 14 | namespace Ui { | ||
| 15 | class ConfigureInputAdvanced; | ||
| 16 | } | ||
| 17 | |||
| 18 | class ConfigureInputAdvanced : public QWidget { | ||
| 19 | Q_OBJECT | ||
| 20 | |||
| 21 | public: | ||
| 22 | explicit ConfigureInputAdvanced(QWidget* parent = nullptr); | ||
| 23 | ~ConfigureInputAdvanced() override; | ||
| 24 | |||
| 25 | void ApplyConfiguration(); | ||
| 26 | |||
| 27 | signals: | ||
| 28 | void CallDebugControllerDialog(); | ||
| 29 | void CallMouseConfigDialog(); | ||
| 30 | void CallTouchscreenConfigDialog(); | ||
| 31 | void CallMotionTouchConfigDialog(); | ||
| 32 | |||
| 33 | private: | ||
| 34 | void changeEvent(QEvent* event) override; | ||
| 35 | void RetranslateUI(); | ||
| 36 | void UpdateUIEnabled(); | ||
| 37 | |||
| 38 | void OnControllerButtonClick(int player_idx, int button_idx); | ||
| 39 | |||
| 40 | void LoadConfiguration(); | ||
| 41 | |||
| 42 | std::unique_ptr<Ui::ConfigureInputAdvanced> ui; | ||
| 43 | |||
| 44 | std::array<std::array<QColor, 4>, 8> controllers_colors; | ||
| 45 | std::array<std::array<QPushButton*, 4>, 8> controllers_color_buttons; | ||
| 46 | }; | ||
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui new file mode 100644 index 000000000..5958435fc --- /dev/null +++ b/src/yuzu/configuration/configure_input_advanced.ui | |||
| @@ -0,0 +1,2688 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureInputAdvanced</class> | ||
| 4 | <widget class="QWidget" name="ConfigureInputAdvanced"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>710</width> | ||
| 10 | <height>580</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Configure Input</string> | ||
| 15 | </property> | ||
| 16 | <property name="styleSheet"> | ||
| 17 | <string notr="true"/> | ||
| 18 | </property> | ||
| 19 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 20 | <property name="spacing"> | ||
| 21 | <number>0</number> | ||
| 22 | </property> | ||
| 23 | <property name="leftMargin"> | ||
| 24 | <number>0</number> | ||
| 25 | </property> | ||
| 26 | <property name="topMargin"> | ||
| 27 | <number>0</number> | ||
| 28 | </property> | ||
| 29 | <property name="rightMargin"> | ||
| 30 | <number>0</number> | ||
| 31 | </property> | ||
| 32 | <property name="bottomMargin"> | ||
| 33 | <number>0</number> | ||
| 34 | </property> | ||
| 35 | <item> | ||
| 36 | <widget class="QWidget" name="mainInputAdvanced" native="true"> | ||
| 37 | <layout class="QHBoxLayout" name="main" stretch="1,1"> | ||
| 38 | <property name="spacing"> | ||
| 39 | <number>9</number> | ||
| 40 | </property> | ||
| 41 | <property name="leftMargin"> | ||
| 42 | <number>0</number> | ||
| 43 | </property> | ||
| 44 | <property name="topMargin"> | ||
| 45 | <number>0</number> | ||
| 46 | </property> | ||
| 47 | <property name="rightMargin"> | ||
| 48 | <number>0</number> | ||
| 49 | </property> | ||
| 50 | <property name="bottomMargin"> | ||
| 51 | <number>0</number> | ||
| 52 | </property> | ||
| 53 | <item> | ||
| 54 | <widget class="QWidget" name="leftInputAdvanced" native="true"> | ||
| 55 | <layout class="QVBoxLayout" name="leftLayout" stretch="0"> | ||
| 56 | <property name="spacing"> | ||
| 57 | <number>3</number> | ||
| 58 | </property> | ||
| 59 | <property name="leftMargin"> | ||
| 60 | <number>0</number> | ||
| 61 | </property> | ||
| 62 | <property name="topMargin"> | ||
| 63 | <number>0</number> | ||
| 64 | </property> | ||
| 65 | <property name="rightMargin"> | ||
| 66 | <number>0</number> | ||
| 67 | </property> | ||
| 68 | <property name="bottomMargin"> | ||
| 69 | <number>0</number> | ||
| 70 | </property> | ||
| 71 | <item> | ||
| 72 | <widget class="QGroupBox" name="joyconColorsGroup"> | ||
| 73 | <property name="title"> | ||
| 74 | <string>Joycon Colors</string> | ||
| 75 | </property> | ||
| 76 | <layout class="QVBoxLayout" name="verticalLayout_3" stretch="1,1"> | ||
| 77 | <property name="leftMargin"> | ||
| 78 | <number>9</number> | ||
| 79 | </property> | ||
| 80 | <property name="topMargin"> | ||
| 81 | <number>9</number> | ||
| 82 | </property> | ||
| 83 | <property name="rightMargin"> | ||
| 84 | <number>9</number> | ||
| 85 | </property> | ||
| 86 | <property name="bottomMargin"> | ||
| 87 | <number>9</number> | ||
| 88 | </property> | ||
| 89 | <item> | ||
| 90 | <widget class="QWidget" name="topLeftInputAdvanced" native="true"> | ||
| 91 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 92 | <property name="spacing"> | ||
| 93 | <number>6</number> | ||
| 94 | </property> | ||
| 95 | <property name="leftMargin"> | ||
| 96 | <number>0</number> | ||
| 97 | </property> | ||
| 98 | <property name="topMargin"> | ||
| 99 | <number>0</number> | ||
| 100 | </property> | ||
| 101 | <property name="rightMargin"> | ||
| 102 | <number>0</number> | ||
| 103 | </property> | ||
| 104 | <property name="bottomMargin"> | ||
| 105 | <number>0</number> | ||
| 106 | </property> | ||
| 107 | <item> | ||
| 108 | <widget class="QWidget" name="player12Widget" native="true"> | ||
| 109 | <layout class="QHBoxLayout" name="horizontalLayout_4"> | ||
| 110 | <property name="leftMargin"> | ||
| 111 | <number>0</number> | ||
| 112 | </property> | ||
| 113 | <property name="topMargin"> | ||
| 114 | <number>0</number> | ||
| 115 | </property> | ||
| 116 | <property name="rightMargin"> | ||
| 117 | <number>0</number> | ||
| 118 | </property> | ||
| 119 | <property name="bottomMargin"> | ||
| 120 | <number>0</number> | ||
| 121 | </property> | ||
| 122 | <item> | ||
| 123 | <widget class="QGroupBox" name="player1Group"> | ||
| 124 | <property name="title"> | ||
| 125 | <string>Player 1</string> | ||
| 126 | </property> | ||
| 127 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 128 | <property name="spacing"> | ||
| 129 | <number>6</number> | ||
| 130 | </property> | ||
| 131 | <property name="leftMargin"> | ||
| 132 | <number>6</number> | ||
| 133 | </property> | ||
| 134 | <property name="topMargin"> | ||
| 135 | <number>0</number> | ||
| 136 | </property> | ||
| 137 | <property name="rightMargin"> | ||
| 138 | <number>6</number> | ||
| 139 | </property> | ||
| 140 | <property name="bottomMargin"> | ||
| 141 | <number>6</number> | ||
| 142 | </property> | ||
| 143 | <item> | ||
| 144 | <widget class="QWidget" name="player1LeftJoycon" native="true"> | ||
| 145 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_14"> | ||
| 146 | <property name="spacing"> | ||
| 147 | <number>0</number> | ||
| 148 | </property> | ||
| 149 | <property name="leftMargin"> | ||
| 150 | <number>0</number> | ||
| 151 | </property> | ||
| 152 | <property name="topMargin"> | ||
| 153 | <number>0</number> | ||
| 154 | </property> | ||
| 155 | <property name="rightMargin"> | ||
| 156 | <number>0</number> | ||
| 157 | </property> | ||
| 158 | <property name="bottomMargin"> | ||
| 159 | <number>0</number> | ||
| 160 | </property> | ||
| 161 | <item alignment="Qt::AlignHCenter"> | ||
| 162 | <widget class="QGroupBox" name="player1LeftBodyGroup"> | ||
| 163 | <property name="title"> | ||
| 164 | <string>L Body</string> | ||
| 165 | </property> | ||
| 166 | <property name="alignment"> | ||
| 167 | <set>Qt::AlignCenter</set> | ||
| 168 | </property> | ||
| 169 | <layout class="QVBoxLayout" name="verticalLayout_66"> | ||
| 170 | <property name="spacing"> | ||
| 171 | <number>3</number> | ||
| 172 | </property> | ||
| 173 | <property name="leftMargin"> | ||
| 174 | <number>3</number> | ||
| 175 | </property> | ||
| 176 | <property name="topMargin"> | ||
| 177 | <number>3</number> | ||
| 178 | </property> | ||
| 179 | <property name="rightMargin"> | ||
| 180 | <number>3</number> | ||
| 181 | </property> | ||
| 182 | <property name="bottomMargin"> | ||
| 183 | <number>3</number> | ||
| 184 | </property> | ||
| 185 | <item> | ||
| 186 | <widget class="QPushButton" name="player1_left_body_button"> | ||
| 187 | <property name="sizePolicy"> | ||
| 188 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 189 | <horstretch>0</horstretch> | ||
| 190 | <verstretch>0</verstretch> | ||
| 191 | </sizepolicy> | ||
| 192 | </property> | ||
| 193 | <property name="minimumSize"> | ||
| 194 | <size> | ||
| 195 | <width>57</width> | ||
| 196 | <height>0</height> | ||
| 197 | </size> | ||
| 198 | </property> | ||
| 199 | <property name="maximumSize"> | ||
| 200 | <size> | ||
| 201 | <width>55</width> | ||
| 202 | <height>16777215</height> | ||
| 203 | </size> | ||
| 204 | </property> | ||
| 205 | <property name="styleSheet"> | ||
| 206 | <string notr="true">min-width: 55px;</string> | ||
| 207 | </property> | ||
| 208 | <property name="text"> | ||
| 209 | <string/> | ||
| 210 | </property> | ||
| 211 | </widget> | ||
| 212 | </item> | ||
| 213 | </layout> | ||
| 214 | </widget> | ||
| 215 | </item> | ||
| 216 | <item alignment="Qt::AlignHCenter"> | ||
| 217 | <widget class="QGroupBox" name="player1LeftButtonsGroup"> | ||
| 218 | <property name="title"> | ||
| 219 | <string>L Button</string> | ||
| 220 | </property> | ||
| 221 | <property name="alignment"> | ||
| 222 | <set>Qt::AlignCenter</set> | ||
| 223 | </property> | ||
| 224 | <layout class="QVBoxLayout" name="verticalLayout_67"> | ||
| 225 | <property name="spacing"> | ||
| 226 | <number>3</number> | ||
| 227 | </property> | ||
| 228 | <property name="leftMargin"> | ||
| 229 | <number>3</number> | ||
| 230 | </property> | ||
| 231 | <property name="topMargin"> | ||
| 232 | <number>3</number> | ||
| 233 | </property> | ||
| 234 | <property name="rightMargin"> | ||
| 235 | <number>3</number> | ||
| 236 | </property> | ||
| 237 | <property name="bottomMargin"> | ||
| 238 | <number>3</number> | ||
| 239 | </property> | ||
| 240 | <item> | ||
| 241 | <widget class="QPushButton" name="player1_left_buttons_button"> | ||
| 242 | <property name="sizePolicy"> | ||
| 243 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 244 | <horstretch>0</horstretch> | ||
| 245 | <verstretch>0</verstretch> | ||
| 246 | </sizepolicy> | ||
| 247 | </property> | ||
| 248 | <property name="minimumSize"> | ||
| 249 | <size> | ||
| 250 | <width>57</width> | ||
| 251 | <height>0</height> | ||
| 252 | </size> | ||
| 253 | </property> | ||
| 254 | <property name="maximumSize"> | ||
| 255 | <size> | ||
| 256 | <width>55</width> | ||
| 257 | <height>16777215</height> | ||
| 258 | </size> | ||
| 259 | </property> | ||
| 260 | <property name="styleSheet"> | ||
| 261 | <string notr="true">min-width: 55px;</string> | ||
| 262 | </property> | ||
| 263 | <property name="text"> | ||
| 264 | <string/> | ||
| 265 | </property> | ||
| 266 | </widget> | ||
| 267 | </item> | ||
| 268 | </layout> | ||
| 269 | </widget> | ||
| 270 | </item> | ||
| 271 | </layout> | ||
| 272 | </widget> | ||
| 273 | </item> | ||
| 274 | <item> | ||
| 275 | <widget class="QWidget" name="player1RightJoycon" native="true"> | ||
| 276 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_14"> | ||
| 277 | <property name="spacing"> | ||
| 278 | <number>0</number> | ||
| 279 | </property> | ||
| 280 | <property name="leftMargin"> | ||
| 281 | <number>0</number> | ||
| 282 | </property> | ||
| 283 | <property name="topMargin"> | ||
| 284 | <number>0</number> | ||
| 285 | </property> | ||
| 286 | <property name="rightMargin"> | ||
| 287 | <number>0</number> | ||
| 288 | </property> | ||
| 289 | <property name="bottomMargin"> | ||
| 290 | <number>0</number> | ||
| 291 | </property> | ||
| 292 | <item alignment="Qt::AlignHCenter"> | ||
| 293 | <widget class="QGroupBox" name="player1RightBodyGroup"> | ||
| 294 | <property name="title"> | ||
| 295 | <string>R Body</string> | ||
| 296 | </property> | ||
| 297 | <property name="alignment"> | ||
| 298 | <set>Qt::AlignCenter</set> | ||
| 299 | </property> | ||
| 300 | <layout class="QVBoxLayout" name="verticalLayout_64"> | ||
| 301 | <property name="spacing"> | ||
| 302 | <number>3</number> | ||
| 303 | </property> | ||
| 304 | <property name="leftMargin"> | ||
| 305 | <number>3</number> | ||
| 306 | </property> | ||
| 307 | <property name="topMargin"> | ||
| 308 | <number>3</number> | ||
| 309 | </property> | ||
| 310 | <property name="rightMargin"> | ||
| 311 | <number>3</number> | ||
| 312 | </property> | ||
| 313 | <property name="bottomMargin"> | ||
| 314 | <number>3</number> | ||
| 315 | </property> | ||
| 316 | <item> | ||
| 317 | <widget class="QPushButton" name="player1_right_body_button"> | ||
| 318 | <property name="sizePolicy"> | ||
| 319 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 320 | <horstretch>0</horstretch> | ||
| 321 | <verstretch>0</verstretch> | ||
| 322 | </sizepolicy> | ||
| 323 | </property> | ||
| 324 | <property name="minimumSize"> | ||
| 325 | <size> | ||
| 326 | <width>57</width> | ||
| 327 | <height>0</height> | ||
| 328 | </size> | ||
| 329 | </property> | ||
| 330 | <property name="maximumSize"> | ||
| 331 | <size> | ||
| 332 | <width>55</width> | ||
| 333 | <height>16777215</height> | ||
| 334 | </size> | ||
| 335 | </property> | ||
| 336 | <property name="styleSheet"> | ||
| 337 | <string notr="true">min-width: 55px;</string> | ||
| 338 | </property> | ||
| 339 | <property name="text"> | ||
| 340 | <string/> | ||
| 341 | </property> | ||
| 342 | </widget> | ||
| 343 | </item> | ||
| 344 | </layout> | ||
| 345 | </widget> | ||
| 346 | </item> | ||
| 347 | <item alignment="Qt::AlignHCenter"> | ||
| 348 | <widget class="QGroupBox" name="player1RightButtonsGroup"> | ||
| 349 | <property name="title"> | ||
| 350 | <string>R Button</string> | ||
| 351 | </property> | ||
| 352 | <property name="alignment"> | ||
| 353 | <set>Qt::AlignCenter</set> | ||
| 354 | </property> | ||
| 355 | <layout class="QVBoxLayout" name="verticalLayout_65"> | ||
| 356 | <property name="spacing"> | ||
| 357 | <number>3</number> | ||
| 358 | </property> | ||
| 359 | <property name="leftMargin"> | ||
| 360 | <number>3</number> | ||
| 361 | </property> | ||
| 362 | <property name="topMargin"> | ||
| 363 | <number>3</number> | ||
| 364 | </property> | ||
| 365 | <property name="rightMargin"> | ||
| 366 | <number>3</number> | ||
| 367 | </property> | ||
| 368 | <property name="bottomMargin"> | ||
| 369 | <number>3</number> | ||
| 370 | </property> | ||
| 371 | <item> | ||
| 372 | <widget class="QPushButton" name="player1_right_buttons_button"> | ||
| 373 | <property name="sizePolicy"> | ||
| 374 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 375 | <horstretch>0</horstretch> | ||
| 376 | <verstretch>0</verstretch> | ||
| 377 | </sizepolicy> | ||
| 378 | </property> | ||
| 379 | <property name="minimumSize"> | ||
| 380 | <size> | ||
| 381 | <width>57</width> | ||
| 382 | <height>0</height> | ||
| 383 | </size> | ||
| 384 | </property> | ||
| 385 | <property name="maximumSize"> | ||
| 386 | <size> | ||
| 387 | <width>55</width> | ||
| 388 | <height>16777215</height> | ||
| 389 | </size> | ||
| 390 | </property> | ||
| 391 | <property name="styleSheet"> | ||
| 392 | <string notr="true">min-width: 55px;</string> | ||
| 393 | </property> | ||
| 394 | <property name="text"> | ||
| 395 | <string/> | ||
| 396 | </property> | ||
| 397 | </widget> | ||
| 398 | </item> | ||
| 399 | </layout> | ||
| 400 | </widget> | ||
| 401 | </item> | ||
| 402 | </layout> | ||
| 403 | </widget> | ||
| 404 | </item> | ||
| 405 | </layout> | ||
| 406 | </widget> | ||
| 407 | </item> | ||
| 408 | <item> | ||
| 409 | <widget class="QGroupBox" name="player2Group"> | ||
| 410 | <property name="title"> | ||
| 411 | <string>Player 2</string> | ||
| 412 | </property> | ||
| 413 | <layout class="QHBoxLayout" name="horizontalLayout_14"> | ||
| 414 | <property name="spacing"> | ||
| 415 | <number>6</number> | ||
| 416 | </property> | ||
| 417 | <property name="leftMargin"> | ||
| 418 | <number>6</number> | ||
| 419 | </property> | ||
| 420 | <property name="topMargin"> | ||
| 421 | <number>0</number> | ||
| 422 | </property> | ||
| 423 | <property name="rightMargin"> | ||
| 424 | <number>6</number> | ||
| 425 | </property> | ||
| 426 | <property name="bottomMargin"> | ||
| 427 | <number>6</number> | ||
| 428 | </property> | ||
| 429 | <item> | ||
| 430 | <widget class="QWidget" name="player2LeftJoycon" native="true"> | ||
| 431 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_15"> | ||
| 432 | <property name="spacing"> | ||
| 433 | <number>0</number> | ||
| 434 | </property> | ||
| 435 | <property name="leftMargin"> | ||
| 436 | <number>0</number> | ||
| 437 | </property> | ||
| 438 | <property name="topMargin"> | ||
| 439 | <number>0</number> | ||
| 440 | </property> | ||
| 441 | <property name="rightMargin"> | ||
| 442 | <number>0</number> | ||
| 443 | </property> | ||
| 444 | <property name="bottomMargin"> | ||
| 445 | <number>0</number> | ||
| 446 | </property> | ||
| 447 | <item alignment="Qt::AlignHCenter"> | ||
| 448 | <widget class="QGroupBox" name="player2LeftBodyGroup"> | ||
| 449 | <property name="title"> | ||
| 450 | <string>L Body</string> | ||
| 451 | </property> | ||
| 452 | <property name="alignment"> | ||
| 453 | <set>Qt::AlignCenter</set> | ||
| 454 | </property> | ||
| 455 | <layout class="QVBoxLayout" name="verticalLayout_70"> | ||
| 456 | <property name="spacing"> | ||
| 457 | <number>3</number> | ||
| 458 | </property> | ||
| 459 | <property name="leftMargin"> | ||
| 460 | <number>3</number> | ||
| 461 | </property> | ||
| 462 | <property name="topMargin"> | ||
| 463 | <number>3</number> | ||
| 464 | </property> | ||
| 465 | <property name="rightMargin"> | ||
| 466 | <number>3</number> | ||
| 467 | </property> | ||
| 468 | <property name="bottomMargin"> | ||
| 469 | <number>3</number> | ||
| 470 | </property> | ||
| 471 | <item> | ||
| 472 | <widget class="QPushButton" name="player2_left_body_button"> | ||
| 473 | <property name="sizePolicy"> | ||
| 474 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 475 | <horstretch>0</horstretch> | ||
| 476 | <verstretch>0</verstretch> | ||
| 477 | </sizepolicy> | ||
| 478 | </property> | ||
| 479 | <property name="minimumSize"> | ||
| 480 | <size> | ||
| 481 | <width>57</width> | ||
| 482 | <height>0</height> | ||
| 483 | </size> | ||
| 484 | </property> | ||
| 485 | <property name="maximumSize"> | ||
| 486 | <size> | ||
| 487 | <width>55</width> | ||
| 488 | <height>16777215</height> | ||
| 489 | </size> | ||
| 490 | </property> | ||
| 491 | <property name="styleSheet"> | ||
| 492 | <string notr="true">min-width: 55px;</string> | ||
| 493 | </property> | ||
| 494 | <property name="text"> | ||
| 495 | <string/> | ||
| 496 | </property> | ||
| 497 | </widget> | ||
| 498 | </item> | ||
| 499 | </layout> | ||
| 500 | </widget> | ||
| 501 | </item> | ||
| 502 | <item alignment="Qt::AlignHCenter"> | ||
| 503 | <widget class="QGroupBox" name="player2LeftButtonsGroup"> | ||
| 504 | <property name="title"> | ||
| 505 | <string>L Button</string> | ||
| 506 | </property> | ||
| 507 | <property name="alignment"> | ||
| 508 | <set>Qt::AlignCenter</set> | ||
| 509 | </property> | ||
| 510 | <layout class="QVBoxLayout" name="verticalLayout_71"> | ||
| 511 | <property name="spacing"> | ||
| 512 | <number>3</number> | ||
| 513 | </property> | ||
| 514 | <property name="leftMargin"> | ||
| 515 | <number>3</number> | ||
| 516 | </property> | ||
| 517 | <property name="topMargin"> | ||
| 518 | <number>3</number> | ||
| 519 | </property> | ||
| 520 | <property name="rightMargin"> | ||
| 521 | <number>3</number> | ||
| 522 | </property> | ||
| 523 | <property name="bottomMargin"> | ||
| 524 | <number>3</number> | ||
| 525 | </property> | ||
| 526 | <item> | ||
| 527 | <widget class="QPushButton" name="player2_left_buttons_button"> | ||
| 528 | <property name="sizePolicy"> | ||
| 529 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 530 | <horstretch>0</horstretch> | ||
| 531 | <verstretch>0</verstretch> | ||
| 532 | </sizepolicy> | ||
| 533 | </property> | ||
| 534 | <property name="minimumSize"> | ||
| 535 | <size> | ||
| 536 | <width>57</width> | ||
| 537 | <height>0</height> | ||
| 538 | </size> | ||
| 539 | </property> | ||
| 540 | <property name="maximumSize"> | ||
| 541 | <size> | ||
| 542 | <width>55</width> | ||
| 543 | <height>16777215</height> | ||
| 544 | </size> | ||
| 545 | </property> | ||
| 546 | <property name="styleSheet"> | ||
| 547 | <string notr="true">min-width: 55px;</string> | ||
| 548 | </property> | ||
| 549 | <property name="text"> | ||
| 550 | <string/> | ||
| 551 | </property> | ||
| 552 | </widget> | ||
| 553 | </item> | ||
| 554 | </layout> | ||
| 555 | </widget> | ||
| 556 | </item> | ||
| 557 | </layout> | ||
| 558 | </widget> | ||
| 559 | </item> | ||
| 560 | <item> | ||
| 561 | <widget class="QWidget" name="player2RightJoycon" native="true"> | ||
| 562 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_15"> | ||
| 563 | <property name="spacing"> | ||
| 564 | <number>0</number> | ||
| 565 | </property> | ||
| 566 | <property name="leftMargin"> | ||
| 567 | <number>0</number> | ||
| 568 | </property> | ||
| 569 | <property name="topMargin"> | ||
| 570 | <number>0</number> | ||
| 571 | </property> | ||
| 572 | <property name="rightMargin"> | ||
| 573 | <number>0</number> | ||
| 574 | </property> | ||
| 575 | <property name="bottomMargin"> | ||
| 576 | <number>0</number> | ||
| 577 | </property> | ||
| 578 | <item alignment="Qt::AlignHCenter"> | ||
| 579 | <widget class="QGroupBox" name="player2RightBodyGroup"> | ||
| 580 | <property name="title"> | ||
| 581 | <string>R Body</string> | ||
| 582 | </property> | ||
| 583 | <property name="alignment"> | ||
| 584 | <set>Qt::AlignCenter</set> | ||
| 585 | </property> | ||
| 586 | <layout class="QVBoxLayout" name="verticalLayout_68"> | ||
| 587 | <property name="spacing"> | ||
| 588 | <number>3</number> | ||
| 589 | </property> | ||
| 590 | <property name="leftMargin"> | ||
| 591 | <number>3</number> | ||
| 592 | </property> | ||
| 593 | <property name="topMargin"> | ||
| 594 | <number>3</number> | ||
| 595 | </property> | ||
| 596 | <property name="rightMargin"> | ||
| 597 | <number>3</number> | ||
| 598 | </property> | ||
| 599 | <property name="bottomMargin"> | ||
| 600 | <number>3</number> | ||
| 601 | </property> | ||
| 602 | <item> | ||
| 603 | <widget class="QPushButton" name="player2_right_body_button"> | ||
| 604 | <property name="sizePolicy"> | ||
| 605 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 606 | <horstretch>0</horstretch> | ||
| 607 | <verstretch>0</verstretch> | ||
| 608 | </sizepolicy> | ||
| 609 | </property> | ||
| 610 | <property name="minimumSize"> | ||
| 611 | <size> | ||
| 612 | <width>57</width> | ||
| 613 | <height>0</height> | ||
| 614 | </size> | ||
| 615 | </property> | ||
| 616 | <property name="maximumSize"> | ||
| 617 | <size> | ||
| 618 | <width>55</width> | ||
| 619 | <height>16777215</height> | ||
| 620 | </size> | ||
| 621 | </property> | ||
| 622 | <property name="styleSheet"> | ||
| 623 | <string notr="true">min-width: 55px;</string> | ||
| 624 | </property> | ||
| 625 | <property name="text"> | ||
| 626 | <string/> | ||
| 627 | </property> | ||
| 628 | </widget> | ||
| 629 | </item> | ||
| 630 | </layout> | ||
| 631 | </widget> | ||
| 632 | </item> | ||
| 633 | <item alignment="Qt::AlignHCenter"> | ||
| 634 | <widget class="QGroupBox" name="player2RightButtonsGroup"> | ||
| 635 | <property name="title"> | ||
| 636 | <string>R Button</string> | ||
| 637 | </property> | ||
| 638 | <property name="alignment"> | ||
| 639 | <set>Qt::AlignCenter</set> | ||
| 640 | </property> | ||
| 641 | <layout class="QVBoxLayout" name="verticalLayout_69"> | ||
| 642 | <property name="spacing"> | ||
| 643 | <number>3</number> | ||
| 644 | </property> | ||
| 645 | <property name="leftMargin"> | ||
| 646 | <number>3</number> | ||
| 647 | </property> | ||
| 648 | <property name="topMargin"> | ||
| 649 | <number>3</number> | ||
| 650 | </property> | ||
| 651 | <property name="rightMargin"> | ||
| 652 | <number>3</number> | ||
| 653 | </property> | ||
| 654 | <property name="bottomMargin"> | ||
| 655 | <number>3</number> | ||
| 656 | </property> | ||
| 657 | <item> | ||
| 658 | <widget class="QPushButton" name="player2_right_buttons_button"> | ||
| 659 | <property name="sizePolicy"> | ||
| 660 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 661 | <horstretch>0</horstretch> | ||
| 662 | <verstretch>0</verstretch> | ||
| 663 | </sizepolicy> | ||
| 664 | </property> | ||
| 665 | <property name="minimumSize"> | ||
| 666 | <size> | ||
| 667 | <width>57</width> | ||
| 668 | <height>0</height> | ||
| 669 | </size> | ||
| 670 | </property> | ||
| 671 | <property name="maximumSize"> | ||
| 672 | <size> | ||
| 673 | <width>55</width> | ||
| 674 | <height>16777215</height> | ||
| 675 | </size> | ||
| 676 | </property> | ||
| 677 | <property name="styleSheet"> | ||
| 678 | <string notr="true">min-width: 55px;</string> | ||
| 679 | </property> | ||
| 680 | <property name="text"> | ||
| 681 | <string/> | ||
| 682 | </property> | ||
| 683 | </widget> | ||
| 684 | </item> | ||
| 685 | </layout> | ||
| 686 | </widget> | ||
| 687 | </item> | ||
| 688 | </layout> | ||
| 689 | </widget> | ||
| 690 | </item> | ||
| 691 | </layout> | ||
| 692 | </widget> | ||
| 693 | </item> | ||
| 694 | </layout> | ||
| 695 | </widget> | ||
| 696 | </item> | ||
| 697 | <item> | ||
| 698 | <widget class="QWidget" name="player34Widget" native="true"> | ||
| 699 | <layout class="QHBoxLayout" name="horizontalLayout_5"> | ||
| 700 | <property name="leftMargin"> | ||
| 701 | <number>0</number> | ||
| 702 | </property> | ||
| 703 | <property name="topMargin"> | ||
| 704 | <number>0</number> | ||
| 705 | </property> | ||
| 706 | <property name="rightMargin"> | ||
| 707 | <number>0</number> | ||
| 708 | </property> | ||
| 709 | <property name="bottomMargin"> | ||
| 710 | <number>0</number> | ||
| 711 | </property> | ||
| 712 | <item> | ||
| 713 | <widget class="QGroupBox" name="player3Group"> | ||
| 714 | <property name="title"> | ||
| 715 | <string>Player 3</string> | ||
| 716 | </property> | ||
| 717 | <layout class="QHBoxLayout" name="horizontalLayout_15"> | ||
| 718 | <property name="spacing"> | ||
| 719 | <number>6</number> | ||
| 720 | </property> | ||
| 721 | <property name="leftMargin"> | ||
| 722 | <number>6</number> | ||
| 723 | </property> | ||
| 724 | <property name="topMargin"> | ||
| 725 | <number>0</number> | ||
| 726 | </property> | ||
| 727 | <property name="rightMargin"> | ||
| 728 | <number>6</number> | ||
| 729 | </property> | ||
| 730 | <property name="bottomMargin"> | ||
| 731 | <number>6</number> | ||
| 732 | </property> | ||
| 733 | <item> | ||
| 734 | <widget class="QWidget" name="player3LeftJoycon" native="true"> | ||
| 735 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_16"> | ||
| 736 | <property name="spacing"> | ||
| 737 | <number>0</number> | ||
| 738 | </property> | ||
| 739 | <property name="leftMargin"> | ||
| 740 | <number>0</number> | ||
| 741 | </property> | ||
| 742 | <property name="topMargin"> | ||
| 743 | <number>0</number> | ||
| 744 | </property> | ||
| 745 | <property name="rightMargin"> | ||
| 746 | <number>0</number> | ||
| 747 | </property> | ||
| 748 | <property name="bottomMargin"> | ||
| 749 | <number>0</number> | ||
| 750 | </property> | ||
| 751 | <item alignment="Qt::AlignHCenter"> | ||
| 752 | <widget class="QGroupBox" name="player3LeftBodyGroup"> | ||
| 753 | <property name="title"> | ||
| 754 | <string>L Body</string> | ||
| 755 | </property> | ||
| 756 | <property name="alignment"> | ||
| 757 | <set>Qt::AlignCenter</set> | ||
| 758 | </property> | ||
| 759 | <layout class="QVBoxLayout" name="verticalLayout_74"> | ||
| 760 | <property name="spacing"> | ||
| 761 | <number>3</number> | ||
| 762 | </property> | ||
| 763 | <property name="leftMargin"> | ||
| 764 | <number>3</number> | ||
| 765 | </property> | ||
| 766 | <property name="topMargin"> | ||
| 767 | <number>3</number> | ||
| 768 | </property> | ||
| 769 | <property name="rightMargin"> | ||
| 770 | <number>3</number> | ||
| 771 | </property> | ||
| 772 | <property name="bottomMargin"> | ||
| 773 | <number>3</number> | ||
| 774 | </property> | ||
| 775 | <item> | ||
| 776 | <widget class="QPushButton" name="player3_left_body_button"> | ||
| 777 | <property name="sizePolicy"> | ||
| 778 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 779 | <horstretch>0</horstretch> | ||
| 780 | <verstretch>0</verstretch> | ||
| 781 | </sizepolicy> | ||
| 782 | </property> | ||
| 783 | <property name="minimumSize"> | ||
| 784 | <size> | ||
| 785 | <width>57</width> | ||
| 786 | <height>0</height> | ||
| 787 | </size> | ||
| 788 | </property> | ||
| 789 | <property name="maximumSize"> | ||
| 790 | <size> | ||
| 791 | <width>55</width> | ||
| 792 | <height>16777215</height> | ||
| 793 | </size> | ||
| 794 | </property> | ||
| 795 | <property name="styleSheet"> | ||
| 796 | <string notr="true">min-width: 55px;</string> | ||
| 797 | </property> | ||
| 798 | <property name="text"> | ||
| 799 | <string/> | ||
| 800 | </property> | ||
| 801 | </widget> | ||
| 802 | </item> | ||
| 803 | </layout> | ||
| 804 | </widget> | ||
| 805 | </item> | ||
| 806 | <item alignment="Qt::AlignHCenter"> | ||
| 807 | <widget class="QGroupBox" name="player3LeftButtonsGroup"> | ||
| 808 | <property name="title"> | ||
| 809 | <string>L Button</string> | ||
| 810 | </property> | ||
| 811 | <property name="alignment"> | ||
| 812 | <set>Qt::AlignCenter</set> | ||
| 813 | </property> | ||
| 814 | <layout class="QVBoxLayout" name="verticalLayout_75"> | ||
| 815 | <property name="spacing"> | ||
| 816 | <number>3</number> | ||
| 817 | </property> | ||
| 818 | <property name="leftMargin"> | ||
| 819 | <number>3</number> | ||
| 820 | </property> | ||
| 821 | <property name="topMargin"> | ||
| 822 | <number>3</number> | ||
| 823 | </property> | ||
| 824 | <property name="rightMargin"> | ||
| 825 | <number>3</number> | ||
| 826 | </property> | ||
| 827 | <property name="bottomMargin"> | ||
| 828 | <number>3</number> | ||
| 829 | </property> | ||
| 830 | <item> | ||
| 831 | <widget class="QPushButton" name="player3_left_buttons_button"> | ||
| 832 | <property name="sizePolicy"> | ||
| 833 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 834 | <horstretch>0</horstretch> | ||
| 835 | <verstretch>0</verstretch> | ||
| 836 | </sizepolicy> | ||
| 837 | </property> | ||
| 838 | <property name="minimumSize"> | ||
| 839 | <size> | ||
| 840 | <width>57</width> | ||
| 841 | <height>0</height> | ||
| 842 | </size> | ||
| 843 | </property> | ||
| 844 | <property name="maximumSize"> | ||
| 845 | <size> | ||
| 846 | <width>55</width> | ||
| 847 | <height>16777215</height> | ||
| 848 | </size> | ||
| 849 | </property> | ||
| 850 | <property name="styleSheet"> | ||
| 851 | <string notr="true">min-width: 55px;</string> | ||
| 852 | </property> | ||
| 853 | <property name="text"> | ||
| 854 | <string/> | ||
| 855 | </property> | ||
| 856 | </widget> | ||
| 857 | </item> | ||
| 858 | </layout> | ||
| 859 | </widget> | ||
| 860 | </item> | ||
| 861 | </layout> | ||
| 862 | </widget> | ||
| 863 | </item> | ||
| 864 | <item> | ||
| 865 | <widget class="QWidget" name="player3RightJoycon" native="true"> | ||
| 866 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_16"> | ||
| 867 | <property name="spacing"> | ||
| 868 | <number>0</number> | ||
| 869 | </property> | ||
| 870 | <property name="leftMargin"> | ||
| 871 | <number>0</number> | ||
| 872 | </property> | ||
| 873 | <property name="topMargin"> | ||
| 874 | <number>0</number> | ||
| 875 | </property> | ||
| 876 | <property name="rightMargin"> | ||
| 877 | <number>0</number> | ||
| 878 | </property> | ||
| 879 | <property name="bottomMargin"> | ||
| 880 | <number>0</number> | ||
| 881 | </property> | ||
| 882 | <item alignment="Qt::AlignHCenter"> | ||
| 883 | <widget class="QGroupBox" name="player3RightBodyGroup"> | ||
| 884 | <property name="title"> | ||
| 885 | <string>R Body</string> | ||
| 886 | </property> | ||
| 887 | <property name="alignment"> | ||
| 888 | <set>Qt::AlignCenter</set> | ||
| 889 | </property> | ||
| 890 | <layout class="QVBoxLayout" name="verticalLayout_72"> | ||
| 891 | <property name="spacing"> | ||
| 892 | <number>3</number> | ||
| 893 | </property> | ||
| 894 | <property name="leftMargin"> | ||
| 895 | <number>3</number> | ||
| 896 | </property> | ||
| 897 | <property name="topMargin"> | ||
| 898 | <number>3</number> | ||
| 899 | </property> | ||
| 900 | <property name="rightMargin"> | ||
| 901 | <number>3</number> | ||
| 902 | </property> | ||
| 903 | <property name="bottomMargin"> | ||
| 904 | <number>3</number> | ||
| 905 | </property> | ||
| 906 | <item> | ||
| 907 | <widget class="QPushButton" name="player3_right_body_button"> | ||
| 908 | <property name="sizePolicy"> | ||
| 909 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 910 | <horstretch>0</horstretch> | ||
| 911 | <verstretch>0</verstretch> | ||
| 912 | </sizepolicy> | ||
| 913 | </property> | ||
| 914 | <property name="minimumSize"> | ||
| 915 | <size> | ||
| 916 | <width>57</width> | ||
| 917 | <height>0</height> | ||
| 918 | </size> | ||
| 919 | </property> | ||
| 920 | <property name="maximumSize"> | ||
| 921 | <size> | ||
| 922 | <width>55</width> | ||
| 923 | <height>16777215</height> | ||
| 924 | </size> | ||
| 925 | </property> | ||
| 926 | <property name="styleSheet"> | ||
| 927 | <string notr="true">min-width: 55px;</string> | ||
| 928 | </property> | ||
| 929 | <property name="text"> | ||
| 930 | <string/> | ||
| 931 | </property> | ||
| 932 | </widget> | ||
| 933 | </item> | ||
| 934 | </layout> | ||
| 935 | </widget> | ||
| 936 | </item> | ||
| 937 | <item alignment="Qt::AlignHCenter"> | ||
| 938 | <widget class="QGroupBox" name="player3RightButtonsGroup"> | ||
| 939 | <property name="title"> | ||
| 940 | <string>R Button</string> | ||
| 941 | </property> | ||
| 942 | <property name="alignment"> | ||
| 943 | <set>Qt::AlignCenter</set> | ||
| 944 | </property> | ||
| 945 | <layout class="QVBoxLayout" name="verticalLayout_73"> | ||
| 946 | <property name="spacing"> | ||
| 947 | <number>3</number> | ||
| 948 | </property> | ||
| 949 | <property name="leftMargin"> | ||
| 950 | <number>3</number> | ||
| 951 | </property> | ||
| 952 | <property name="topMargin"> | ||
| 953 | <number>3</number> | ||
| 954 | </property> | ||
| 955 | <property name="rightMargin"> | ||
| 956 | <number>3</number> | ||
| 957 | </property> | ||
| 958 | <property name="bottomMargin"> | ||
| 959 | <number>3</number> | ||
| 960 | </property> | ||
| 961 | <item> | ||
| 962 | <widget class="QPushButton" name="player3_right_buttons_button"> | ||
| 963 | <property name="sizePolicy"> | ||
| 964 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 965 | <horstretch>0</horstretch> | ||
| 966 | <verstretch>0</verstretch> | ||
| 967 | </sizepolicy> | ||
| 968 | </property> | ||
| 969 | <property name="minimumSize"> | ||
| 970 | <size> | ||
| 971 | <width>57</width> | ||
| 972 | <height>0</height> | ||
| 973 | </size> | ||
| 974 | </property> | ||
| 975 | <property name="maximumSize"> | ||
| 976 | <size> | ||
| 977 | <width>55</width> | ||
| 978 | <height>16777215</height> | ||
| 979 | </size> | ||
| 980 | </property> | ||
| 981 | <property name="styleSheet"> | ||
| 982 | <string notr="true">min-width: 55px;</string> | ||
| 983 | </property> | ||
| 984 | <property name="text"> | ||
| 985 | <string/> | ||
| 986 | </property> | ||
| 987 | </widget> | ||
| 988 | </item> | ||
| 989 | </layout> | ||
| 990 | </widget> | ||
| 991 | </item> | ||
| 992 | </layout> | ||
| 993 | </widget> | ||
| 994 | </item> | ||
| 995 | </layout> | ||
| 996 | </widget> | ||
| 997 | </item> | ||
| 998 | <item> | ||
| 999 | <widget class="QGroupBox" name="player4Group"> | ||
| 1000 | <property name="title"> | ||
| 1001 | <string>Player 4</string> | ||
| 1002 | </property> | ||
| 1003 | <layout class="QHBoxLayout" name="horizontalLayout_16"> | ||
| 1004 | <property name="spacing"> | ||
| 1005 | <number>6</number> | ||
| 1006 | </property> | ||
| 1007 | <property name="leftMargin"> | ||
| 1008 | <number>6</number> | ||
| 1009 | </property> | ||
| 1010 | <property name="topMargin"> | ||
| 1011 | <number>0</number> | ||
| 1012 | </property> | ||
| 1013 | <property name="rightMargin"> | ||
| 1014 | <number>6</number> | ||
| 1015 | </property> | ||
| 1016 | <property name="bottomMargin"> | ||
| 1017 | <number>6</number> | ||
| 1018 | </property> | ||
| 1019 | <item> | ||
| 1020 | <widget class="QWidget" name="player4LeftJoycon" native="true"> | ||
| 1021 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_17"> | ||
| 1022 | <property name="spacing"> | ||
| 1023 | <number>0</number> | ||
| 1024 | </property> | ||
| 1025 | <property name="leftMargin"> | ||
| 1026 | <number>0</number> | ||
| 1027 | </property> | ||
| 1028 | <property name="topMargin"> | ||
| 1029 | <number>0</number> | ||
| 1030 | </property> | ||
| 1031 | <property name="rightMargin"> | ||
| 1032 | <number>0</number> | ||
| 1033 | </property> | ||
| 1034 | <property name="bottomMargin"> | ||
| 1035 | <number>0</number> | ||
| 1036 | </property> | ||
| 1037 | <item alignment="Qt::AlignHCenter"> | ||
| 1038 | <widget class="QGroupBox" name="player4LeftBodyGroup"> | ||
| 1039 | <property name="title"> | ||
| 1040 | <string>L Body</string> | ||
| 1041 | </property> | ||
| 1042 | <property name="alignment"> | ||
| 1043 | <set>Qt::AlignCenter</set> | ||
| 1044 | </property> | ||
| 1045 | <layout class="QVBoxLayout" name="verticalLayout_78"> | ||
| 1046 | <property name="spacing"> | ||
| 1047 | <number>3</number> | ||
| 1048 | </property> | ||
| 1049 | <property name="leftMargin"> | ||
| 1050 | <number>3</number> | ||
| 1051 | </property> | ||
| 1052 | <property name="topMargin"> | ||
| 1053 | <number>3</number> | ||
| 1054 | </property> | ||
| 1055 | <property name="rightMargin"> | ||
| 1056 | <number>3</number> | ||
| 1057 | </property> | ||
| 1058 | <property name="bottomMargin"> | ||
| 1059 | <number>3</number> | ||
| 1060 | </property> | ||
| 1061 | <item> | ||
| 1062 | <widget class="QPushButton" name="player4_left_body_button"> | ||
| 1063 | <property name="sizePolicy"> | ||
| 1064 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1065 | <horstretch>0</horstretch> | ||
| 1066 | <verstretch>0</verstretch> | ||
| 1067 | </sizepolicy> | ||
| 1068 | </property> | ||
| 1069 | <property name="minimumSize"> | ||
| 1070 | <size> | ||
| 1071 | <width>57</width> | ||
| 1072 | <height>0</height> | ||
| 1073 | </size> | ||
| 1074 | </property> | ||
| 1075 | <property name="maximumSize"> | ||
| 1076 | <size> | ||
| 1077 | <width>55</width> | ||
| 1078 | <height>16777215</height> | ||
| 1079 | </size> | ||
| 1080 | </property> | ||
| 1081 | <property name="styleSheet"> | ||
| 1082 | <string notr="true">min-width: 55px;</string> | ||
| 1083 | </property> | ||
| 1084 | <property name="text"> | ||
| 1085 | <string/> | ||
| 1086 | </property> | ||
| 1087 | </widget> | ||
| 1088 | </item> | ||
| 1089 | </layout> | ||
| 1090 | </widget> | ||
| 1091 | </item> | ||
| 1092 | <item alignment="Qt::AlignHCenter"> | ||
| 1093 | <widget class="QGroupBox" name="player4LeftButtonsGroup"> | ||
| 1094 | <property name="title"> | ||
| 1095 | <string>L Button</string> | ||
| 1096 | </property> | ||
| 1097 | <property name="alignment"> | ||
| 1098 | <set>Qt::AlignCenter</set> | ||
| 1099 | </property> | ||
| 1100 | <layout class="QVBoxLayout" name="verticalLayout_79"> | ||
| 1101 | <property name="spacing"> | ||
| 1102 | <number>3</number> | ||
| 1103 | </property> | ||
| 1104 | <property name="leftMargin"> | ||
| 1105 | <number>3</number> | ||
| 1106 | </property> | ||
| 1107 | <property name="topMargin"> | ||
| 1108 | <number>3</number> | ||
| 1109 | </property> | ||
| 1110 | <property name="rightMargin"> | ||
| 1111 | <number>3</number> | ||
| 1112 | </property> | ||
| 1113 | <property name="bottomMargin"> | ||
| 1114 | <number>3</number> | ||
| 1115 | </property> | ||
| 1116 | <item> | ||
| 1117 | <widget class="QPushButton" name="player4_left_buttons_button"> | ||
| 1118 | <property name="sizePolicy"> | ||
| 1119 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1120 | <horstretch>0</horstretch> | ||
| 1121 | <verstretch>0</verstretch> | ||
| 1122 | </sizepolicy> | ||
| 1123 | </property> | ||
| 1124 | <property name="minimumSize"> | ||
| 1125 | <size> | ||
| 1126 | <width>57</width> | ||
| 1127 | <height>0</height> | ||
| 1128 | </size> | ||
| 1129 | </property> | ||
| 1130 | <property name="maximumSize"> | ||
| 1131 | <size> | ||
| 1132 | <width>55</width> | ||
| 1133 | <height>16777215</height> | ||
| 1134 | </size> | ||
| 1135 | </property> | ||
| 1136 | <property name="styleSheet"> | ||
| 1137 | <string notr="true">min-width: 55px;</string> | ||
| 1138 | </property> | ||
| 1139 | <property name="text"> | ||
| 1140 | <string/> | ||
| 1141 | </property> | ||
| 1142 | </widget> | ||
| 1143 | </item> | ||
| 1144 | </layout> | ||
| 1145 | </widget> | ||
| 1146 | </item> | ||
| 1147 | </layout> | ||
| 1148 | </widget> | ||
| 1149 | </item> | ||
| 1150 | <item> | ||
| 1151 | <widget class="QWidget" name="player4RightJoycon" native="true"> | ||
| 1152 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_17"> | ||
| 1153 | <property name="spacing"> | ||
| 1154 | <number>0</number> | ||
| 1155 | </property> | ||
| 1156 | <property name="leftMargin"> | ||
| 1157 | <number>0</number> | ||
| 1158 | </property> | ||
| 1159 | <property name="topMargin"> | ||
| 1160 | <number>0</number> | ||
| 1161 | </property> | ||
| 1162 | <property name="rightMargin"> | ||
| 1163 | <number>0</number> | ||
| 1164 | </property> | ||
| 1165 | <property name="bottomMargin"> | ||
| 1166 | <number>0</number> | ||
| 1167 | </property> | ||
| 1168 | <item alignment="Qt::AlignHCenter"> | ||
| 1169 | <widget class="QGroupBox" name="player4RightBodyGroup"> | ||
| 1170 | <property name="title"> | ||
| 1171 | <string>R Body</string> | ||
| 1172 | </property> | ||
| 1173 | <property name="alignment"> | ||
| 1174 | <set>Qt::AlignCenter</set> | ||
| 1175 | </property> | ||
| 1176 | <layout class="QVBoxLayout" name="verticalLayout_76"> | ||
| 1177 | <property name="spacing"> | ||
| 1178 | <number>3</number> | ||
| 1179 | </property> | ||
| 1180 | <property name="leftMargin"> | ||
| 1181 | <number>3</number> | ||
| 1182 | </property> | ||
| 1183 | <property name="topMargin"> | ||
| 1184 | <number>3</number> | ||
| 1185 | </property> | ||
| 1186 | <property name="rightMargin"> | ||
| 1187 | <number>3</number> | ||
| 1188 | </property> | ||
| 1189 | <property name="bottomMargin"> | ||
| 1190 | <number>3</number> | ||
| 1191 | </property> | ||
| 1192 | <item> | ||
| 1193 | <widget class="QPushButton" name="player4_right_body_button"> | ||
| 1194 | <property name="sizePolicy"> | ||
| 1195 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1196 | <horstretch>0</horstretch> | ||
| 1197 | <verstretch>0</verstretch> | ||
| 1198 | </sizepolicy> | ||
| 1199 | </property> | ||
| 1200 | <property name="minimumSize"> | ||
| 1201 | <size> | ||
| 1202 | <width>57</width> | ||
| 1203 | <height>0</height> | ||
| 1204 | </size> | ||
| 1205 | </property> | ||
| 1206 | <property name="maximumSize"> | ||
| 1207 | <size> | ||
| 1208 | <width>55</width> | ||
| 1209 | <height>16777215</height> | ||
| 1210 | </size> | ||
| 1211 | </property> | ||
| 1212 | <property name="styleSheet"> | ||
| 1213 | <string notr="true">min-width: 55px;</string> | ||
| 1214 | </property> | ||
| 1215 | <property name="text"> | ||
| 1216 | <string/> | ||
| 1217 | </property> | ||
| 1218 | </widget> | ||
| 1219 | </item> | ||
| 1220 | </layout> | ||
| 1221 | </widget> | ||
| 1222 | </item> | ||
| 1223 | <item alignment="Qt::AlignHCenter"> | ||
| 1224 | <widget class="QGroupBox" name="player4RightButtonsGroup"> | ||
| 1225 | <property name="title"> | ||
| 1226 | <string>R Button</string> | ||
| 1227 | </property> | ||
| 1228 | <property name="alignment"> | ||
| 1229 | <set>Qt::AlignCenter</set> | ||
| 1230 | </property> | ||
| 1231 | <layout class="QVBoxLayout" name="verticalLayout_77"> | ||
| 1232 | <property name="spacing"> | ||
| 1233 | <number>3</number> | ||
| 1234 | </property> | ||
| 1235 | <property name="leftMargin"> | ||
| 1236 | <number>3</number> | ||
| 1237 | </property> | ||
| 1238 | <property name="topMargin"> | ||
| 1239 | <number>3</number> | ||
| 1240 | </property> | ||
| 1241 | <property name="rightMargin"> | ||
| 1242 | <number>3</number> | ||
| 1243 | </property> | ||
| 1244 | <property name="bottomMargin"> | ||
| 1245 | <number>3</number> | ||
| 1246 | </property> | ||
| 1247 | <item> | ||
| 1248 | <widget class="QPushButton" name="player4_right_buttons_button"> | ||
| 1249 | <property name="sizePolicy"> | ||
| 1250 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1251 | <horstretch>0</horstretch> | ||
| 1252 | <verstretch>0</verstretch> | ||
| 1253 | </sizepolicy> | ||
| 1254 | </property> | ||
| 1255 | <property name="minimumSize"> | ||
| 1256 | <size> | ||
| 1257 | <width>57</width> | ||
| 1258 | <height>0</height> | ||
| 1259 | </size> | ||
| 1260 | </property> | ||
| 1261 | <property name="maximumSize"> | ||
| 1262 | <size> | ||
| 1263 | <width>55</width> | ||
| 1264 | <height>16777215</height> | ||
| 1265 | </size> | ||
| 1266 | </property> | ||
| 1267 | <property name="styleSheet"> | ||
| 1268 | <string notr="true">min-width: 55px;</string> | ||
| 1269 | </property> | ||
| 1270 | <property name="text"> | ||
| 1271 | <string/> | ||
| 1272 | </property> | ||
| 1273 | </widget> | ||
| 1274 | </item> | ||
| 1275 | </layout> | ||
| 1276 | </widget> | ||
| 1277 | </item> | ||
| 1278 | </layout> | ||
| 1279 | </widget> | ||
| 1280 | </item> | ||
| 1281 | </layout> | ||
| 1282 | </widget> | ||
| 1283 | </item> | ||
| 1284 | </layout> | ||
| 1285 | </widget> | ||
| 1286 | </item> | ||
| 1287 | </layout> | ||
| 1288 | </widget> | ||
| 1289 | </item> | ||
| 1290 | <item> | ||
| 1291 | <widget class="QWidget" name="bottomLeftInputAdvanced" native="true"> | ||
| 1292 | <layout class="QVBoxLayout" name="verticalLayout_5"> | ||
| 1293 | <property name="spacing"> | ||
| 1294 | <number>6</number> | ||
| 1295 | </property> | ||
| 1296 | <property name="leftMargin"> | ||
| 1297 | <number>0</number> | ||
| 1298 | </property> | ||
| 1299 | <property name="topMargin"> | ||
| 1300 | <number>0</number> | ||
| 1301 | </property> | ||
| 1302 | <property name="rightMargin"> | ||
| 1303 | <number>0</number> | ||
| 1304 | </property> | ||
| 1305 | <property name="bottomMargin"> | ||
| 1306 | <number>0</number> | ||
| 1307 | </property> | ||
| 1308 | <item> | ||
| 1309 | <widget class="QWidget" name="player56Widget" native="true"> | ||
| 1310 | <layout class="QHBoxLayout" name="horizontalLayout_6"> | ||
| 1311 | <property name="leftMargin"> | ||
| 1312 | <number>0</number> | ||
| 1313 | </property> | ||
| 1314 | <property name="topMargin"> | ||
| 1315 | <number>0</number> | ||
| 1316 | </property> | ||
| 1317 | <property name="rightMargin"> | ||
| 1318 | <number>0</number> | ||
| 1319 | </property> | ||
| 1320 | <property name="bottomMargin"> | ||
| 1321 | <number>0</number> | ||
| 1322 | </property> | ||
| 1323 | <item> | ||
| 1324 | <widget class="QGroupBox" name="player5Group"> | ||
| 1325 | <property name="title"> | ||
| 1326 | <string>Player 5</string> | ||
| 1327 | </property> | ||
| 1328 | <layout class="QHBoxLayout" name="horizontalLayout_10"> | ||
| 1329 | <property name="spacing"> | ||
| 1330 | <number>6</number> | ||
| 1331 | </property> | ||
| 1332 | <property name="leftMargin"> | ||
| 1333 | <number>6</number> | ||
| 1334 | </property> | ||
| 1335 | <property name="topMargin"> | ||
| 1336 | <number>0</number> | ||
| 1337 | </property> | ||
| 1338 | <property name="rightMargin"> | ||
| 1339 | <number>6</number> | ||
| 1340 | </property> | ||
| 1341 | <property name="bottomMargin"> | ||
| 1342 | <number>6</number> | ||
| 1343 | </property> | ||
| 1344 | <item> | ||
| 1345 | <widget class="QWidget" name="player5LeftJoycon" native="true"> | ||
| 1346 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_10"> | ||
| 1347 | <property name="spacing"> | ||
| 1348 | <number>0</number> | ||
| 1349 | </property> | ||
| 1350 | <property name="leftMargin"> | ||
| 1351 | <number>0</number> | ||
| 1352 | </property> | ||
| 1353 | <property name="topMargin"> | ||
| 1354 | <number>0</number> | ||
| 1355 | </property> | ||
| 1356 | <property name="rightMargin"> | ||
| 1357 | <number>0</number> | ||
| 1358 | </property> | ||
| 1359 | <property name="bottomMargin"> | ||
| 1360 | <number>0</number> | ||
| 1361 | </property> | ||
| 1362 | <item alignment="Qt::AlignHCenter"> | ||
| 1363 | <widget class="QGroupBox" name="player5LeftBodyGroup"> | ||
| 1364 | <property name="title"> | ||
| 1365 | <string>L Body</string> | ||
| 1366 | </property> | ||
| 1367 | <property name="alignment"> | ||
| 1368 | <set>Qt::AlignCenter</set> | ||
| 1369 | </property> | ||
| 1370 | <layout class="QVBoxLayout" name="verticalLayout_50"> | ||
| 1371 | <property name="spacing"> | ||
| 1372 | <number>3</number> | ||
| 1373 | </property> | ||
| 1374 | <property name="leftMargin"> | ||
| 1375 | <number>3</number> | ||
| 1376 | </property> | ||
| 1377 | <property name="topMargin"> | ||
| 1378 | <number>3</number> | ||
| 1379 | </property> | ||
| 1380 | <property name="rightMargin"> | ||
| 1381 | <number>3</number> | ||
| 1382 | </property> | ||
| 1383 | <property name="bottomMargin"> | ||
| 1384 | <number>3</number> | ||
| 1385 | </property> | ||
| 1386 | <item> | ||
| 1387 | <widget class="QPushButton" name="player5_left_body_button"> | ||
| 1388 | <property name="sizePolicy"> | ||
| 1389 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1390 | <horstretch>0</horstretch> | ||
| 1391 | <verstretch>0</verstretch> | ||
| 1392 | </sizepolicy> | ||
| 1393 | </property> | ||
| 1394 | <property name="minimumSize"> | ||
| 1395 | <size> | ||
| 1396 | <width>57</width> | ||
| 1397 | <height>0</height> | ||
| 1398 | </size> | ||
| 1399 | </property> | ||
| 1400 | <property name="maximumSize"> | ||
| 1401 | <size> | ||
| 1402 | <width>55</width> | ||
| 1403 | <height>16777215</height> | ||
| 1404 | </size> | ||
| 1405 | </property> | ||
| 1406 | <property name="styleSheet"> | ||
| 1407 | <string notr="true">min-width: 55px;</string> | ||
| 1408 | </property> | ||
| 1409 | <property name="text"> | ||
| 1410 | <string/> | ||
| 1411 | </property> | ||
| 1412 | </widget> | ||
| 1413 | </item> | ||
| 1414 | </layout> | ||
| 1415 | </widget> | ||
| 1416 | </item> | ||
| 1417 | <item alignment="Qt::AlignHCenter"> | ||
| 1418 | <widget class="QGroupBox" name="player5LeftButtonsGroup"> | ||
| 1419 | <property name="title"> | ||
| 1420 | <string>L Button</string> | ||
| 1421 | </property> | ||
| 1422 | <property name="alignment"> | ||
| 1423 | <set>Qt::AlignCenter</set> | ||
| 1424 | </property> | ||
| 1425 | <layout class="QVBoxLayout" name="verticalLayout_51"> | ||
| 1426 | <property name="spacing"> | ||
| 1427 | <number>3</number> | ||
| 1428 | </property> | ||
| 1429 | <property name="leftMargin"> | ||
| 1430 | <number>3</number> | ||
| 1431 | </property> | ||
| 1432 | <property name="topMargin"> | ||
| 1433 | <number>3</number> | ||
| 1434 | </property> | ||
| 1435 | <property name="rightMargin"> | ||
| 1436 | <number>3</number> | ||
| 1437 | </property> | ||
| 1438 | <property name="bottomMargin"> | ||
| 1439 | <number>3</number> | ||
| 1440 | </property> | ||
| 1441 | <item> | ||
| 1442 | <widget class="QPushButton" name="player5_left_buttons_button"> | ||
| 1443 | <property name="sizePolicy"> | ||
| 1444 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1445 | <horstretch>0</horstretch> | ||
| 1446 | <verstretch>0</verstretch> | ||
| 1447 | </sizepolicy> | ||
| 1448 | </property> | ||
| 1449 | <property name="minimumSize"> | ||
| 1450 | <size> | ||
| 1451 | <width>57</width> | ||
| 1452 | <height>0</height> | ||
| 1453 | </size> | ||
| 1454 | </property> | ||
| 1455 | <property name="maximumSize"> | ||
| 1456 | <size> | ||
| 1457 | <width>55</width> | ||
| 1458 | <height>16777215</height> | ||
| 1459 | </size> | ||
| 1460 | </property> | ||
| 1461 | <property name="styleSheet"> | ||
| 1462 | <string notr="true">min-width: 55px;</string> | ||
| 1463 | </property> | ||
| 1464 | <property name="text"> | ||
| 1465 | <string/> | ||
| 1466 | </property> | ||
| 1467 | </widget> | ||
| 1468 | </item> | ||
| 1469 | </layout> | ||
| 1470 | </widget> | ||
| 1471 | </item> | ||
| 1472 | </layout> | ||
| 1473 | </widget> | ||
| 1474 | </item> | ||
| 1475 | <item> | ||
| 1476 | <widget class="QWidget" name="player5RightJoycon" native="true"> | ||
| 1477 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_10"> | ||
| 1478 | <property name="spacing"> | ||
| 1479 | <number>0</number> | ||
| 1480 | </property> | ||
| 1481 | <property name="leftMargin"> | ||
| 1482 | <number>0</number> | ||
| 1483 | </property> | ||
| 1484 | <property name="topMargin"> | ||
| 1485 | <number>0</number> | ||
| 1486 | </property> | ||
| 1487 | <property name="rightMargin"> | ||
| 1488 | <number>0</number> | ||
| 1489 | </property> | ||
| 1490 | <property name="bottomMargin"> | ||
| 1491 | <number>0</number> | ||
| 1492 | </property> | ||
| 1493 | <item alignment="Qt::AlignHCenter"> | ||
| 1494 | <widget class="QGroupBox" name="player5RightBodyGroup"> | ||
| 1495 | <property name="title"> | ||
| 1496 | <string>R Body</string> | ||
| 1497 | </property> | ||
| 1498 | <property name="alignment"> | ||
| 1499 | <set>Qt::AlignCenter</set> | ||
| 1500 | </property> | ||
| 1501 | <layout class="QVBoxLayout" name="verticalLayout_48"> | ||
| 1502 | <property name="spacing"> | ||
| 1503 | <number>3</number> | ||
| 1504 | </property> | ||
| 1505 | <property name="leftMargin"> | ||
| 1506 | <number>3</number> | ||
| 1507 | </property> | ||
| 1508 | <property name="topMargin"> | ||
| 1509 | <number>3</number> | ||
| 1510 | </property> | ||
| 1511 | <property name="rightMargin"> | ||
| 1512 | <number>3</number> | ||
| 1513 | </property> | ||
| 1514 | <property name="bottomMargin"> | ||
| 1515 | <number>3</number> | ||
| 1516 | </property> | ||
| 1517 | <item> | ||
| 1518 | <widget class="QPushButton" name="player5_right_body_button"> | ||
| 1519 | <property name="sizePolicy"> | ||
| 1520 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1521 | <horstretch>0</horstretch> | ||
| 1522 | <verstretch>0</verstretch> | ||
| 1523 | </sizepolicy> | ||
| 1524 | </property> | ||
| 1525 | <property name="minimumSize"> | ||
| 1526 | <size> | ||
| 1527 | <width>57</width> | ||
| 1528 | <height>0</height> | ||
| 1529 | </size> | ||
| 1530 | </property> | ||
| 1531 | <property name="maximumSize"> | ||
| 1532 | <size> | ||
| 1533 | <width>55</width> | ||
| 1534 | <height>16777215</height> | ||
| 1535 | </size> | ||
| 1536 | </property> | ||
| 1537 | <property name="styleSheet"> | ||
| 1538 | <string notr="true">min-width: 55px;</string> | ||
| 1539 | </property> | ||
| 1540 | <property name="text"> | ||
| 1541 | <string/> | ||
| 1542 | </property> | ||
| 1543 | </widget> | ||
| 1544 | </item> | ||
| 1545 | </layout> | ||
| 1546 | </widget> | ||
| 1547 | </item> | ||
| 1548 | <item alignment="Qt::AlignHCenter"> | ||
| 1549 | <widget class="QGroupBox" name="player5RightButtonsGroup"> | ||
| 1550 | <property name="title"> | ||
| 1551 | <string>R Button</string> | ||
| 1552 | </property> | ||
| 1553 | <property name="alignment"> | ||
| 1554 | <set>Qt::AlignCenter</set> | ||
| 1555 | </property> | ||
| 1556 | <layout class="QVBoxLayout" name="verticalLayout_49"> | ||
| 1557 | <property name="spacing"> | ||
| 1558 | <number>3</number> | ||
| 1559 | </property> | ||
| 1560 | <property name="leftMargin"> | ||
| 1561 | <number>3</number> | ||
| 1562 | </property> | ||
| 1563 | <property name="topMargin"> | ||
| 1564 | <number>3</number> | ||
| 1565 | </property> | ||
| 1566 | <property name="rightMargin"> | ||
| 1567 | <number>3</number> | ||
| 1568 | </property> | ||
| 1569 | <property name="bottomMargin"> | ||
| 1570 | <number>3</number> | ||
| 1571 | </property> | ||
| 1572 | <item> | ||
| 1573 | <widget class="QPushButton" name="player5_right_buttons_button"> | ||
| 1574 | <property name="sizePolicy"> | ||
| 1575 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1576 | <horstretch>0</horstretch> | ||
| 1577 | <verstretch>0</verstretch> | ||
| 1578 | </sizepolicy> | ||
| 1579 | </property> | ||
| 1580 | <property name="minimumSize"> | ||
| 1581 | <size> | ||
| 1582 | <width>57</width> | ||
| 1583 | <height>0</height> | ||
| 1584 | </size> | ||
| 1585 | </property> | ||
| 1586 | <property name="maximumSize"> | ||
| 1587 | <size> | ||
| 1588 | <width>55</width> | ||
| 1589 | <height>16777215</height> | ||
| 1590 | </size> | ||
| 1591 | </property> | ||
| 1592 | <property name="styleSheet"> | ||
| 1593 | <string notr="true">min-width: 55px;</string> | ||
| 1594 | </property> | ||
| 1595 | <property name="text"> | ||
| 1596 | <string/> | ||
| 1597 | </property> | ||
| 1598 | </widget> | ||
| 1599 | </item> | ||
| 1600 | </layout> | ||
| 1601 | </widget> | ||
| 1602 | </item> | ||
| 1603 | </layout> | ||
| 1604 | </widget> | ||
| 1605 | </item> | ||
| 1606 | </layout> | ||
| 1607 | </widget> | ||
| 1608 | </item> | ||
| 1609 | <item> | ||
| 1610 | <widget class="QGroupBox" name="player6Group"> | ||
| 1611 | <property name="title"> | ||
| 1612 | <string>Player 6</string> | ||
| 1613 | </property> | ||
| 1614 | <layout class="QHBoxLayout" name="horizontalLayout_11"> | ||
| 1615 | <property name="spacing"> | ||
| 1616 | <number>6</number> | ||
| 1617 | </property> | ||
| 1618 | <property name="leftMargin"> | ||
| 1619 | <number>6</number> | ||
| 1620 | </property> | ||
| 1621 | <property name="topMargin"> | ||
| 1622 | <number>0</number> | ||
| 1623 | </property> | ||
| 1624 | <property name="rightMargin"> | ||
| 1625 | <number>6</number> | ||
| 1626 | </property> | ||
| 1627 | <property name="bottomMargin"> | ||
| 1628 | <number>6</number> | ||
| 1629 | </property> | ||
| 1630 | <item> | ||
| 1631 | <widget class="QWidget" name="player6LeftJoycon" native="true"> | ||
| 1632 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_11"> | ||
| 1633 | <property name="spacing"> | ||
| 1634 | <number>0</number> | ||
| 1635 | </property> | ||
| 1636 | <property name="leftMargin"> | ||
| 1637 | <number>0</number> | ||
| 1638 | </property> | ||
| 1639 | <property name="topMargin"> | ||
| 1640 | <number>0</number> | ||
| 1641 | </property> | ||
| 1642 | <property name="rightMargin"> | ||
| 1643 | <number>0</number> | ||
| 1644 | </property> | ||
| 1645 | <property name="bottomMargin"> | ||
| 1646 | <number>0</number> | ||
| 1647 | </property> | ||
| 1648 | <item alignment="Qt::AlignHCenter"> | ||
| 1649 | <widget class="QGroupBox" name="player6LeftBodyGroup"> | ||
| 1650 | <property name="title"> | ||
| 1651 | <string>L Body</string> | ||
| 1652 | </property> | ||
| 1653 | <property name="alignment"> | ||
| 1654 | <set>Qt::AlignCenter</set> | ||
| 1655 | </property> | ||
| 1656 | <layout class="QVBoxLayout" name="verticalLayout_54"> | ||
| 1657 | <property name="spacing"> | ||
| 1658 | <number>3</number> | ||
| 1659 | </property> | ||
| 1660 | <property name="leftMargin"> | ||
| 1661 | <number>3</number> | ||
| 1662 | </property> | ||
| 1663 | <property name="topMargin"> | ||
| 1664 | <number>3</number> | ||
| 1665 | </property> | ||
| 1666 | <property name="rightMargin"> | ||
| 1667 | <number>3</number> | ||
| 1668 | </property> | ||
| 1669 | <property name="bottomMargin"> | ||
| 1670 | <number>3</number> | ||
| 1671 | </property> | ||
| 1672 | <item> | ||
| 1673 | <widget class="QPushButton" name="player6_left_body_button"> | ||
| 1674 | <property name="sizePolicy"> | ||
| 1675 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1676 | <horstretch>0</horstretch> | ||
| 1677 | <verstretch>0</verstretch> | ||
| 1678 | </sizepolicy> | ||
| 1679 | </property> | ||
| 1680 | <property name="minimumSize"> | ||
| 1681 | <size> | ||
| 1682 | <width>57</width> | ||
| 1683 | <height>0</height> | ||
| 1684 | </size> | ||
| 1685 | </property> | ||
| 1686 | <property name="maximumSize"> | ||
| 1687 | <size> | ||
| 1688 | <width>55</width> | ||
| 1689 | <height>16777215</height> | ||
| 1690 | </size> | ||
| 1691 | </property> | ||
| 1692 | <property name="styleSheet"> | ||
| 1693 | <string notr="true">min-width: 55px;</string> | ||
| 1694 | </property> | ||
| 1695 | <property name="text"> | ||
| 1696 | <string/> | ||
| 1697 | </property> | ||
| 1698 | </widget> | ||
| 1699 | </item> | ||
| 1700 | </layout> | ||
| 1701 | </widget> | ||
| 1702 | </item> | ||
| 1703 | <item alignment="Qt::AlignHCenter"> | ||
| 1704 | <widget class="QGroupBox" name="player6LeftButtonsGroup"> | ||
| 1705 | <property name="title"> | ||
| 1706 | <string>L Button</string> | ||
| 1707 | </property> | ||
| 1708 | <property name="alignment"> | ||
| 1709 | <set>Qt::AlignCenter</set> | ||
| 1710 | </property> | ||
| 1711 | <layout class="QVBoxLayout" name="verticalLayout_55"> | ||
| 1712 | <property name="spacing"> | ||
| 1713 | <number>3</number> | ||
| 1714 | </property> | ||
| 1715 | <property name="leftMargin"> | ||
| 1716 | <number>3</number> | ||
| 1717 | </property> | ||
| 1718 | <property name="topMargin"> | ||
| 1719 | <number>3</number> | ||
| 1720 | </property> | ||
| 1721 | <property name="rightMargin"> | ||
| 1722 | <number>3</number> | ||
| 1723 | </property> | ||
| 1724 | <property name="bottomMargin"> | ||
| 1725 | <number>3</number> | ||
| 1726 | </property> | ||
| 1727 | <item> | ||
| 1728 | <widget class="QPushButton" name="player6_left_buttons_button"> | ||
| 1729 | <property name="sizePolicy"> | ||
| 1730 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1731 | <horstretch>0</horstretch> | ||
| 1732 | <verstretch>0</verstretch> | ||
| 1733 | </sizepolicy> | ||
| 1734 | </property> | ||
| 1735 | <property name="minimumSize"> | ||
| 1736 | <size> | ||
| 1737 | <width>57</width> | ||
| 1738 | <height>0</height> | ||
| 1739 | </size> | ||
| 1740 | </property> | ||
| 1741 | <property name="maximumSize"> | ||
| 1742 | <size> | ||
| 1743 | <width>55</width> | ||
| 1744 | <height>16777215</height> | ||
| 1745 | </size> | ||
| 1746 | </property> | ||
| 1747 | <property name="styleSheet"> | ||
| 1748 | <string notr="true">min-width: 55px;</string> | ||
| 1749 | </property> | ||
| 1750 | <property name="text"> | ||
| 1751 | <string/> | ||
| 1752 | </property> | ||
| 1753 | </widget> | ||
| 1754 | </item> | ||
| 1755 | </layout> | ||
| 1756 | </widget> | ||
| 1757 | </item> | ||
| 1758 | </layout> | ||
| 1759 | </widget> | ||
| 1760 | </item> | ||
| 1761 | <item> | ||
| 1762 | <widget class="QWidget" name="player6RightJoycon" native="true"> | ||
| 1763 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_11"> | ||
| 1764 | <property name="spacing"> | ||
| 1765 | <number>0</number> | ||
| 1766 | </property> | ||
| 1767 | <property name="leftMargin"> | ||
| 1768 | <number>0</number> | ||
| 1769 | </property> | ||
| 1770 | <property name="topMargin"> | ||
| 1771 | <number>0</number> | ||
| 1772 | </property> | ||
| 1773 | <property name="rightMargin"> | ||
| 1774 | <number>0</number> | ||
| 1775 | </property> | ||
| 1776 | <property name="bottomMargin"> | ||
| 1777 | <number>0</number> | ||
| 1778 | </property> | ||
| 1779 | <item alignment="Qt::AlignHCenter"> | ||
| 1780 | <widget class="QGroupBox" name="player6RightBodyGroup"> | ||
| 1781 | <property name="title"> | ||
| 1782 | <string>R Body</string> | ||
| 1783 | </property> | ||
| 1784 | <property name="alignment"> | ||
| 1785 | <set>Qt::AlignCenter</set> | ||
| 1786 | </property> | ||
| 1787 | <layout class="QVBoxLayout" name="verticalLayout_52"> | ||
| 1788 | <property name="spacing"> | ||
| 1789 | <number>3</number> | ||
| 1790 | </property> | ||
| 1791 | <property name="leftMargin"> | ||
| 1792 | <number>3</number> | ||
| 1793 | </property> | ||
| 1794 | <property name="topMargin"> | ||
| 1795 | <number>3</number> | ||
| 1796 | </property> | ||
| 1797 | <property name="rightMargin"> | ||
| 1798 | <number>3</number> | ||
| 1799 | </property> | ||
| 1800 | <property name="bottomMargin"> | ||
| 1801 | <number>3</number> | ||
| 1802 | </property> | ||
| 1803 | <item> | ||
| 1804 | <widget class="QPushButton" name="player6_right_body_button"> | ||
| 1805 | <property name="sizePolicy"> | ||
| 1806 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1807 | <horstretch>0</horstretch> | ||
| 1808 | <verstretch>0</verstretch> | ||
| 1809 | </sizepolicy> | ||
| 1810 | </property> | ||
| 1811 | <property name="minimumSize"> | ||
| 1812 | <size> | ||
| 1813 | <width>57</width> | ||
| 1814 | <height>0</height> | ||
| 1815 | </size> | ||
| 1816 | </property> | ||
| 1817 | <property name="maximumSize"> | ||
| 1818 | <size> | ||
| 1819 | <width>55</width> | ||
| 1820 | <height>16777215</height> | ||
| 1821 | </size> | ||
| 1822 | </property> | ||
| 1823 | <property name="styleSheet"> | ||
| 1824 | <string notr="true">min-width: 55px;</string> | ||
| 1825 | </property> | ||
| 1826 | <property name="text"> | ||
| 1827 | <string/> | ||
| 1828 | </property> | ||
| 1829 | </widget> | ||
| 1830 | </item> | ||
| 1831 | </layout> | ||
| 1832 | </widget> | ||
| 1833 | </item> | ||
| 1834 | <item alignment="Qt::AlignHCenter"> | ||
| 1835 | <widget class="QGroupBox" name="player6RightButtonsGroup"> | ||
| 1836 | <property name="title"> | ||
| 1837 | <string>R Button</string> | ||
| 1838 | </property> | ||
| 1839 | <property name="alignment"> | ||
| 1840 | <set>Qt::AlignCenter</set> | ||
| 1841 | </property> | ||
| 1842 | <layout class="QVBoxLayout" name="verticalLayout_53"> | ||
| 1843 | <property name="spacing"> | ||
| 1844 | <number>3</number> | ||
| 1845 | </property> | ||
| 1846 | <property name="leftMargin"> | ||
| 1847 | <number>3</number> | ||
| 1848 | </property> | ||
| 1849 | <property name="topMargin"> | ||
| 1850 | <number>3</number> | ||
| 1851 | </property> | ||
| 1852 | <property name="rightMargin"> | ||
| 1853 | <number>3</number> | ||
| 1854 | </property> | ||
| 1855 | <property name="bottomMargin"> | ||
| 1856 | <number>3</number> | ||
| 1857 | </property> | ||
| 1858 | <item> | ||
| 1859 | <widget class="QPushButton" name="player6_right_buttons_button"> | ||
| 1860 | <property name="sizePolicy"> | ||
| 1861 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1862 | <horstretch>0</horstretch> | ||
| 1863 | <verstretch>0</verstretch> | ||
| 1864 | </sizepolicy> | ||
| 1865 | </property> | ||
| 1866 | <property name="minimumSize"> | ||
| 1867 | <size> | ||
| 1868 | <width>57</width> | ||
| 1869 | <height>0</height> | ||
| 1870 | </size> | ||
| 1871 | </property> | ||
| 1872 | <property name="maximumSize"> | ||
| 1873 | <size> | ||
| 1874 | <width>55</width> | ||
| 1875 | <height>16777215</height> | ||
| 1876 | </size> | ||
| 1877 | </property> | ||
| 1878 | <property name="styleSheet"> | ||
| 1879 | <string notr="true">min-width: 55px;</string> | ||
| 1880 | </property> | ||
| 1881 | <property name="text"> | ||
| 1882 | <string/> | ||
| 1883 | </property> | ||
| 1884 | </widget> | ||
| 1885 | </item> | ||
| 1886 | </layout> | ||
| 1887 | </widget> | ||
| 1888 | </item> | ||
| 1889 | </layout> | ||
| 1890 | </widget> | ||
| 1891 | </item> | ||
| 1892 | </layout> | ||
| 1893 | </widget> | ||
| 1894 | </item> | ||
| 1895 | </layout> | ||
| 1896 | </widget> | ||
| 1897 | </item> | ||
| 1898 | <item> | ||
| 1899 | <widget class="QWidget" name="player78Widget" native="true"> | ||
| 1900 | <layout class="QHBoxLayout" name="horizontalLayout_7"> | ||
| 1901 | <property name="leftMargin"> | ||
| 1902 | <number>0</number> | ||
| 1903 | </property> | ||
| 1904 | <property name="topMargin"> | ||
| 1905 | <number>0</number> | ||
| 1906 | </property> | ||
| 1907 | <property name="rightMargin"> | ||
| 1908 | <number>0</number> | ||
| 1909 | </property> | ||
| 1910 | <property name="bottomMargin"> | ||
| 1911 | <number>0</number> | ||
| 1912 | </property> | ||
| 1913 | <item> | ||
| 1914 | <widget class="QGroupBox" name="player7Group"> | ||
| 1915 | <property name="title"> | ||
| 1916 | <string>Player 7</string> | ||
| 1917 | </property> | ||
| 1918 | <layout class="QHBoxLayout" name="horizontalLayout_12"> | ||
| 1919 | <property name="spacing"> | ||
| 1920 | <number>6</number> | ||
| 1921 | </property> | ||
| 1922 | <property name="leftMargin"> | ||
| 1923 | <number>6</number> | ||
| 1924 | </property> | ||
| 1925 | <property name="topMargin"> | ||
| 1926 | <number>0</number> | ||
| 1927 | </property> | ||
| 1928 | <property name="rightMargin"> | ||
| 1929 | <number>6</number> | ||
| 1930 | </property> | ||
| 1931 | <property name="bottomMargin"> | ||
| 1932 | <number>6</number> | ||
| 1933 | </property> | ||
| 1934 | <item> | ||
| 1935 | <widget class="QWidget" name="player7LeftJoycon" native="true"> | ||
| 1936 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_12"> | ||
| 1937 | <property name="spacing"> | ||
| 1938 | <number>0</number> | ||
| 1939 | </property> | ||
| 1940 | <property name="leftMargin"> | ||
| 1941 | <number>0</number> | ||
| 1942 | </property> | ||
| 1943 | <property name="topMargin"> | ||
| 1944 | <number>0</number> | ||
| 1945 | </property> | ||
| 1946 | <property name="rightMargin"> | ||
| 1947 | <number>0</number> | ||
| 1948 | </property> | ||
| 1949 | <property name="bottomMargin"> | ||
| 1950 | <number>0</number> | ||
| 1951 | </property> | ||
| 1952 | <item alignment="Qt::AlignHCenter"> | ||
| 1953 | <widget class="QGroupBox" name="player7LeftBodyGroup"> | ||
| 1954 | <property name="title"> | ||
| 1955 | <string>L Body</string> | ||
| 1956 | </property> | ||
| 1957 | <property name="alignment"> | ||
| 1958 | <set>Qt::AlignCenter</set> | ||
| 1959 | </property> | ||
| 1960 | <layout class="QVBoxLayout" name="verticalLayout_58"> | ||
| 1961 | <property name="spacing"> | ||
| 1962 | <number>3</number> | ||
| 1963 | </property> | ||
| 1964 | <property name="leftMargin"> | ||
| 1965 | <number>3</number> | ||
| 1966 | </property> | ||
| 1967 | <property name="topMargin"> | ||
| 1968 | <number>3</number> | ||
| 1969 | </property> | ||
| 1970 | <property name="rightMargin"> | ||
| 1971 | <number>3</number> | ||
| 1972 | </property> | ||
| 1973 | <property name="bottomMargin"> | ||
| 1974 | <number>3</number> | ||
| 1975 | </property> | ||
| 1976 | <item> | ||
| 1977 | <widget class="QPushButton" name="player7_left_body_button"> | ||
| 1978 | <property name="sizePolicy"> | ||
| 1979 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 1980 | <horstretch>0</horstretch> | ||
| 1981 | <verstretch>0</verstretch> | ||
| 1982 | </sizepolicy> | ||
| 1983 | </property> | ||
| 1984 | <property name="minimumSize"> | ||
| 1985 | <size> | ||
| 1986 | <width>57</width> | ||
| 1987 | <height>0</height> | ||
| 1988 | </size> | ||
| 1989 | </property> | ||
| 1990 | <property name="maximumSize"> | ||
| 1991 | <size> | ||
| 1992 | <width>55</width> | ||
| 1993 | <height>16777215</height> | ||
| 1994 | </size> | ||
| 1995 | </property> | ||
| 1996 | <property name="styleSheet"> | ||
| 1997 | <string notr="true">min-width: 55px;</string> | ||
| 1998 | </property> | ||
| 1999 | <property name="text"> | ||
| 2000 | <string/> | ||
| 2001 | </property> | ||
| 2002 | </widget> | ||
| 2003 | </item> | ||
| 2004 | </layout> | ||
| 2005 | </widget> | ||
| 2006 | </item> | ||
| 2007 | <item alignment="Qt::AlignHCenter"> | ||
| 2008 | <widget class="QGroupBox" name="player7LeftButtonsGroup"> | ||
| 2009 | <property name="title"> | ||
| 2010 | <string>L Button</string> | ||
| 2011 | </property> | ||
| 2012 | <property name="alignment"> | ||
| 2013 | <set>Qt::AlignCenter</set> | ||
| 2014 | </property> | ||
| 2015 | <layout class="QVBoxLayout" name="verticalLayout_59"> | ||
| 2016 | <property name="spacing"> | ||
| 2017 | <number>3</number> | ||
| 2018 | </property> | ||
| 2019 | <property name="leftMargin"> | ||
| 2020 | <number>3</number> | ||
| 2021 | </property> | ||
| 2022 | <property name="topMargin"> | ||
| 2023 | <number>3</number> | ||
| 2024 | </property> | ||
| 2025 | <property name="rightMargin"> | ||
| 2026 | <number>3</number> | ||
| 2027 | </property> | ||
| 2028 | <property name="bottomMargin"> | ||
| 2029 | <number>3</number> | ||
| 2030 | </property> | ||
| 2031 | <item> | ||
| 2032 | <widget class="QPushButton" name="player7_left_buttons_button"> | ||
| 2033 | <property name="sizePolicy"> | ||
| 2034 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2035 | <horstretch>0</horstretch> | ||
| 2036 | <verstretch>0</verstretch> | ||
| 2037 | </sizepolicy> | ||
| 2038 | </property> | ||
| 2039 | <property name="minimumSize"> | ||
| 2040 | <size> | ||
| 2041 | <width>57</width> | ||
| 2042 | <height>0</height> | ||
| 2043 | </size> | ||
| 2044 | </property> | ||
| 2045 | <property name="maximumSize"> | ||
| 2046 | <size> | ||
| 2047 | <width>55</width> | ||
| 2048 | <height>16777215</height> | ||
| 2049 | </size> | ||
| 2050 | </property> | ||
| 2051 | <property name="styleSheet"> | ||
| 2052 | <string notr="true">min-width: 55px;</string> | ||
| 2053 | </property> | ||
| 2054 | <property name="text"> | ||
| 2055 | <string/> | ||
| 2056 | </property> | ||
| 2057 | </widget> | ||
| 2058 | </item> | ||
| 2059 | </layout> | ||
| 2060 | </widget> | ||
| 2061 | </item> | ||
| 2062 | </layout> | ||
| 2063 | </widget> | ||
| 2064 | </item> | ||
| 2065 | <item> | ||
| 2066 | <widget class="QWidget" name="player7RightJoycon" native="true"> | ||
| 2067 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_12"> | ||
| 2068 | <property name="spacing"> | ||
| 2069 | <number>0</number> | ||
| 2070 | </property> | ||
| 2071 | <property name="leftMargin"> | ||
| 2072 | <number>0</number> | ||
| 2073 | </property> | ||
| 2074 | <property name="topMargin"> | ||
| 2075 | <number>0</number> | ||
| 2076 | </property> | ||
| 2077 | <property name="rightMargin"> | ||
| 2078 | <number>0</number> | ||
| 2079 | </property> | ||
| 2080 | <property name="bottomMargin"> | ||
| 2081 | <number>0</number> | ||
| 2082 | </property> | ||
| 2083 | <item alignment="Qt::AlignHCenter"> | ||
| 2084 | <widget class="QGroupBox" name="player7RightBodyGroup"> | ||
| 2085 | <property name="title"> | ||
| 2086 | <string>R Body</string> | ||
| 2087 | </property> | ||
| 2088 | <property name="alignment"> | ||
| 2089 | <set>Qt::AlignCenter</set> | ||
| 2090 | </property> | ||
| 2091 | <layout class="QVBoxLayout" name="verticalLayout_56"> | ||
| 2092 | <property name="spacing"> | ||
| 2093 | <number>3</number> | ||
| 2094 | </property> | ||
| 2095 | <property name="leftMargin"> | ||
| 2096 | <number>3</number> | ||
| 2097 | </property> | ||
| 2098 | <property name="topMargin"> | ||
| 2099 | <number>3</number> | ||
| 2100 | </property> | ||
| 2101 | <property name="rightMargin"> | ||
| 2102 | <number>3</number> | ||
| 2103 | </property> | ||
| 2104 | <property name="bottomMargin"> | ||
| 2105 | <number>3</number> | ||
| 2106 | </property> | ||
| 2107 | <item> | ||
| 2108 | <widget class="QPushButton" name="player7_right_body_button"> | ||
| 2109 | <property name="sizePolicy"> | ||
| 2110 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2111 | <horstretch>0</horstretch> | ||
| 2112 | <verstretch>0</verstretch> | ||
| 2113 | </sizepolicy> | ||
| 2114 | </property> | ||
| 2115 | <property name="minimumSize"> | ||
| 2116 | <size> | ||
| 2117 | <width>57</width> | ||
| 2118 | <height>0</height> | ||
| 2119 | </size> | ||
| 2120 | </property> | ||
| 2121 | <property name="maximumSize"> | ||
| 2122 | <size> | ||
| 2123 | <width>55</width> | ||
| 2124 | <height>16777215</height> | ||
| 2125 | </size> | ||
| 2126 | </property> | ||
| 2127 | <property name="styleSheet"> | ||
| 2128 | <string notr="true">min-width: 55px;</string> | ||
| 2129 | </property> | ||
| 2130 | <property name="text"> | ||
| 2131 | <string/> | ||
| 2132 | </property> | ||
| 2133 | </widget> | ||
| 2134 | </item> | ||
| 2135 | </layout> | ||
| 2136 | </widget> | ||
| 2137 | </item> | ||
| 2138 | <item alignment="Qt::AlignHCenter"> | ||
| 2139 | <widget class="QGroupBox" name="player7RightButtonsGroup"> | ||
| 2140 | <property name="title"> | ||
| 2141 | <string>R Button</string> | ||
| 2142 | </property> | ||
| 2143 | <property name="alignment"> | ||
| 2144 | <set>Qt::AlignCenter</set> | ||
| 2145 | </property> | ||
| 2146 | <layout class="QVBoxLayout" name="verticalLayout_57"> | ||
| 2147 | <property name="spacing"> | ||
| 2148 | <number>3</number> | ||
| 2149 | </property> | ||
| 2150 | <property name="leftMargin"> | ||
| 2151 | <number>3</number> | ||
| 2152 | </property> | ||
| 2153 | <property name="topMargin"> | ||
| 2154 | <number>3</number> | ||
| 2155 | </property> | ||
| 2156 | <property name="rightMargin"> | ||
| 2157 | <number>3</number> | ||
| 2158 | </property> | ||
| 2159 | <property name="bottomMargin"> | ||
| 2160 | <number>3</number> | ||
| 2161 | </property> | ||
| 2162 | <item> | ||
| 2163 | <widget class="QPushButton" name="player7_right_buttons_button"> | ||
| 2164 | <property name="sizePolicy"> | ||
| 2165 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2166 | <horstretch>0</horstretch> | ||
| 2167 | <verstretch>0</verstretch> | ||
| 2168 | </sizepolicy> | ||
| 2169 | </property> | ||
| 2170 | <property name="minimumSize"> | ||
| 2171 | <size> | ||
| 2172 | <width>57</width> | ||
| 2173 | <height>0</height> | ||
| 2174 | </size> | ||
| 2175 | </property> | ||
| 2176 | <property name="maximumSize"> | ||
| 2177 | <size> | ||
| 2178 | <width>55</width> | ||
| 2179 | <height>16777215</height> | ||
| 2180 | </size> | ||
| 2181 | </property> | ||
| 2182 | <property name="styleSheet"> | ||
| 2183 | <string notr="true">min-width: 55px;</string> | ||
| 2184 | </property> | ||
| 2185 | <property name="text"> | ||
| 2186 | <string/> | ||
| 2187 | </property> | ||
| 2188 | </widget> | ||
| 2189 | </item> | ||
| 2190 | </layout> | ||
| 2191 | </widget> | ||
| 2192 | </item> | ||
| 2193 | </layout> | ||
| 2194 | </widget> | ||
| 2195 | </item> | ||
| 2196 | </layout> | ||
| 2197 | </widget> | ||
| 2198 | </item> | ||
| 2199 | <item> | ||
| 2200 | <widget class="QGroupBox" name="player8Group"> | ||
| 2201 | <property name="title"> | ||
| 2202 | <string>Player 8</string> | ||
| 2203 | </property> | ||
| 2204 | <layout class="QHBoxLayout" name="horizontalLayout_13"> | ||
| 2205 | <property name="spacing"> | ||
| 2206 | <number>6</number> | ||
| 2207 | </property> | ||
| 2208 | <property name="leftMargin"> | ||
| 2209 | <number>6</number> | ||
| 2210 | </property> | ||
| 2211 | <property name="topMargin"> | ||
| 2212 | <number>0</number> | ||
| 2213 | </property> | ||
| 2214 | <property name="rightMargin"> | ||
| 2215 | <number>6</number> | ||
| 2216 | </property> | ||
| 2217 | <property name="bottomMargin"> | ||
| 2218 | <number>6</number> | ||
| 2219 | </property> | ||
| 2220 | <item> | ||
| 2221 | <widget class="QWidget" name="player8LeftJoycon" native="true"> | ||
| 2222 | <layout class="QVBoxLayout" name="buttonMiscButtonsLeftJoyconVerticalLayout_13"> | ||
| 2223 | <property name="spacing"> | ||
| 2224 | <number>0</number> | ||
| 2225 | </property> | ||
| 2226 | <property name="leftMargin"> | ||
| 2227 | <number>0</number> | ||
| 2228 | </property> | ||
| 2229 | <property name="topMargin"> | ||
| 2230 | <number>0</number> | ||
| 2231 | </property> | ||
| 2232 | <property name="rightMargin"> | ||
| 2233 | <number>0</number> | ||
| 2234 | </property> | ||
| 2235 | <property name="bottomMargin"> | ||
| 2236 | <number>0</number> | ||
| 2237 | </property> | ||
| 2238 | <item alignment="Qt::AlignHCenter"> | ||
| 2239 | <widget class="QGroupBox" name="player8LeftBodyGroup"> | ||
| 2240 | <property name="title"> | ||
| 2241 | <string>L Body</string> | ||
| 2242 | </property> | ||
| 2243 | <property name="alignment"> | ||
| 2244 | <set>Qt::AlignCenter</set> | ||
| 2245 | </property> | ||
| 2246 | <layout class="QVBoxLayout" name="verticalLayout_62"> | ||
| 2247 | <property name="spacing"> | ||
| 2248 | <number>3</number> | ||
| 2249 | </property> | ||
| 2250 | <property name="leftMargin"> | ||
| 2251 | <number>3</number> | ||
| 2252 | </property> | ||
| 2253 | <property name="topMargin"> | ||
| 2254 | <number>3</number> | ||
| 2255 | </property> | ||
| 2256 | <property name="rightMargin"> | ||
| 2257 | <number>3</number> | ||
| 2258 | </property> | ||
| 2259 | <property name="bottomMargin"> | ||
| 2260 | <number>3</number> | ||
| 2261 | </property> | ||
| 2262 | <item> | ||
| 2263 | <widget class="QPushButton" name="player8_left_body_button"> | ||
| 2264 | <property name="sizePolicy"> | ||
| 2265 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2266 | <horstretch>0</horstretch> | ||
| 2267 | <verstretch>0</verstretch> | ||
| 2268 | </sizepolicy> | ||
| 2269 | </property> | ||
| 2270 | <property name="minimumSize"> | ||
| 2271 | <size> | ||
| 2272 | <width>57</width> | ||
| 2273 | <height>0</height> | ||
| 2274 | </size> | ||
| 2275 | </property> | ||
| 2276 | <property name="maximumSize"> | ||
| 2277 | <size> | ||
| 2278 | <width>55</width> | ||
| 2279 | <height>16777215</height> | ||
| 2280 | </size> | ||
| 2281 | </property> | ||
| 2282 | <property name="styleSheet"> | ||
| 2283 | <string notr="true">min-width: 55px;</string> | ||
| 2284 | </property> | ||
| 2285 | <property name="text"> | ||
| 2286 | <string/> | ||
| 2287 | </property> | ||
| 2288 | </widget> | ||
| 2289 | </item> | ||
| 2290 | </layout> | ||
| 2291 | </widget> | ||
| 2292 | </item> | ||
| 2293 | <item alignment="Qt::AlignHCenter"> | ||
| 2294 | <widget class="QGroupBox" name="player8LeftButtonsGroup"> | ||
| 2295 | <property name="title"> | ||
| 2296 | <string>L Button</string> | ||
| 2297 | </property> | ||
| 2298 | <property name="alignment"> | ||
| 2299 | <set>Qt::AlignCenter</set> | ||
| 2300 | </property> | ||
| 2301 | <layout class="QVBoxLayout" name="verticalLayout_63"> | ||
| 2302 | <property name="spacing"> | ||
| 2303 | <number>3</number> | ||
| 2304 | </property> | ||
| 2305 | <property name="leftMargin"> | ||
| 2306 | <number>3</number> | ||
| 2307 | </property> | ||
| 2308 | <property name="topMargin"> | ||
| 2309 | <number>3</number> | ||
| 2310 | </property> | ||
| 2311 | <property name="rightMargin"> | ||
| 2312 | <number>3</number> | ||
| 2313 | </property> | ||
| 2314 | <property name="bottomMargin"> | ||
| 2315 | <number>3</number> | ||
| 2316 | </property> | ||
| 2317 | <item> | ||
| 2318 | <widget class="QPushButton" name="player8_left_buttons_button"> | ||
| 2319 | <property name="sizePolicy"> | ||
| 2320 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2321 | <horstretch>0</horstretch> | ||
| 2322 | <verstretch>0</verstretch> | ||
| 2323 | </sizepolicy> | ||
| 2324 | </property> | ||
| 2325 | <property name="minimumSize"> | ||
| 2326 | <size> | ||
| 2327 | <width>57</width> | ||
| 2328 | <height>0</height> | ||
| 2329 | </size> | ||
| 2330 | </property> | ||
| 2331 | <property name="maximumSize"> | ||
| 2332 | <size> | ||
| 2333 | <width>55</width> | ||
| 2334 | <height>16777215</height> | ||
| 2335 | </size> | ||
| 2336 | </property> | ||
| 2337 | <property name="styleSheet"> | ||
| 2338 | <string notr="true">min-width: 55px;</string> | ||
| 2339 | </property> | ||
| 2340 | <property name="text"> | ||
| 2341 | <string/> | ||
| 2342 | </property> | ||
| 2343 | </widget> | ||
| 2344 | </item> | ||
| 2345 | </layout> | ||
| 2346 | </widget> | ||
| 2347 | </item> | ||
| 2348 | </layout> | ||
| 2349 | </widget> | ||
| 2350 | </item> | ||
| 2351 | <item> | ||
| 2352 | <widget class="QWidget" name="player8RightJoycon" native="true"> | ||
| 2353 | <layout class="QVBoxLayout" name="buttonMiscButtonsRightJoyconVerticalLayout_13"> | ||
| 2354 | <property name="spacing"> | ||
| 2355 | <number>0</number> | ||
| 2356 | </property> | ||
| 2357 | <property name="leftMargin"> | ||
| 2358 | <number>0</number> | ||
| 2359 | </property> | ||
| 2360 | <property name="topMargin"> | ||
| 2361 | <number>0</number> | ||
| 2362 | </property> | ||
| 2363 | <property name="rightMargin"> | ||
| 2364 | <number>0</number> | ||
| 2365 | </property> | ||
| 2366 | <property name="bottomMargin"> | ||
| 2367 | <number>0</number> | ||
| 2368 | </property> | ||
| 2369 | <item alignment="Qt::AlignHCenter"> | ||
| 2370 | <widget class="QGroupBox" name="player8RightBodyGroup"> | ||
| 2371 | <property name="title"> | ||
| 2372 | <string>R Body</string> | ||
| 2373 | </property> | ||
| 2374 | <property name="alignment"> | ||
| 2375 | <set>Qt::AlignCenter</set> | ||
| 2376 | </property> | ||
| 2377 | <layout class="QVBoxLayout" name="verticalLayout_60"> | ||
| 2378 | <property name="spacing"> | ||
| 2379 | <number>3</number> | ||
| 2380 | </property> | ||
| 2381 | <property name="leftMargin"> | ||
| 2382 | <number>3</number> | ||
| 2383 | </property> | ||
| 2384 | <property name="topMargin"> | ||
| 2385 | <number>3</number> | ||
| 2386 | </property> | ||
| 2387 | <property name="rightMargin"> | ||
| 2388 | <number>3</number> | ||
| 2389 | </property> | ||
| 2390 | <property name="bottomMargin"> | ||
| 2391 | <number>3</number> | ||
| 2392 | </property> | ||
| 2393 | <item> | ||
| 2394 | <widget class="QPushButton" name="player8_right_body_button"> | ||
| 2395 | <property name="sizePolicy"> | ||
| 2396 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2397 | <horstretch>0</horstretch> | ||
| 2398 | <verstretch>0</verstretch> | ||
| 2399 | </sizepolicy> | ||
| 2400 | </property> | ||
| 2401 | <property name="minimumSize"> | ||
| 2402 | <size> | ||
| 2403 | <width>57</width> | ||
| 2404 | <height>0</height> | ||
| 2405 | </size> | ||
| 2406 | </property> | ||
| 2407 | <property name="maximumSize"> | ||
| 2408 | <size> | ||
| 2409 | <width>55</width> | ||
| 2410 | <height>16777215</height> | ||
| 2411 | </size> | ||
| 2412 | </property> | ||
| 2413 | <property name="styleSheet"> | ||
| 2414 | <string notr="true">min-width: 55px;</string> | ||
| 2415 | </property> | ||
| 2416 | <property name="text"> | ||
| 2417 | <string/> | ||
| 2418 | </property> | ||
| 2419 | </widget> | ||
| 2420 | </item> | ||
| 2421 | </layout> | ||
| 2422 | </widget> | ||
| 2423 | </item> | ||
| 2424 | <item alignment="Qt::AlignHCenter"> | ||
| 2425 | <widget class="QGroupBox" name="player8RightButtonsGroup"> | ||
| 2426 | <property name="title"> | ||
| 2427 | <string>R Button</string> | ||
| 2428 | </property> | ||
| 2429 | <property name="alignment"> | ||
| 2430 | <set>Qt::AlignCenter</set> | ||
| 2431 | </property> | ||
| 2432 | <layout class="QVBoxLayout" name="verticalLayout_61"> | ||
| 2433 | <property name="spacing"> | ||
| 2434 | <number>3</number> | ||
| 2435 | </property> | ||
| 2436 | <property name="leftMargin"> | ||
| 2437 | <number>3</number> | ||
| 2438 | </property> | ||
| 2439 | <property name="topMargin"> | ||
| 2440 | <number>3</number> | ||
| 2441 | </property> | ||
| 2442 | <property name="rightMargin"> | ||
| 2443 | <number>3</number> | ||
| 2444 | </property> | ||
| 2445 | <property name="bottomMargin"> | ||
| 2446 | <number>3</number> | ||
| 2447 | </property> | ||
| 2448 | <item> | ||
| 2449 | <widget class="QPushButton" name="player8_right_buttons_button"> | ||
| 2450 | <property name="sizePolicy"> | ||
| 2451 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2452 | <horstretch>0</horstretch> | ||
| 2453 | <verstretch>0</verstretch> | ||
| 2454 | </sizepolicy> | ||
| 2455 | </property> | ||
| 2456 | <property name="minimumSize"> | ||
| 2457 | <size> | ||
| 2458 | <width>57</width> | ||
| 2459 | <height>0</height> | ||
| 2460 | </size> | ||
| 2461 | </property> | ||
| 2462 | <property name="maximumSize"> | ||
| 2463 | <size> | ||
| 2464 | <width>55</width> | ||
| 2465 | <height>16777215</height> | ||
| 2466 | </size> | ||
| 2467 | </property> | ||
| 2468 | <property name="styleSheet"> | ||
| 2469 | <string notr="true">min-width: 55px;</string> | ||
| 2470 | </property> | ||
| 2471 | <property name="text"> | ||
| 2472 | <string/> | ||
| 2473 | </property> | ||
| 2474 | </widget> | ||
| 2475 | </item> | ||
| 2476 | </layout> | ||
| 2477 | </widget> | ||
| 2478 | </item> | ||
| 2479 | </layout> | ||
| 2480 | </widget> | ||
| 2481 | </item> | ||
| 2482 | </layout> | ||
| 2483 | </widget> | ||
| 2484 | </item> | ||
| 2485 | </layout> | ||
| 2486 | </widget> | ||
| 2487 | </item> | ||
| 2488 | </layout> | ||
| 2489 | </widget> | ||
| 2490 | </item> | ||
| 2491 | </layout> | ||
| 2492 | </widget> | ||
| 2493 | </item> | ||
| 2494 | </layout> | ||
| 2495 | </widget> | ||
| 2496 | </item> | ||
| 2497 | <item> | ||
| 2498 | <widget class="QWidget" name="rightInputAdvanced" native="true"> | ||
| 2499 | <layout class="QVBoxLayout" name="rightLayout" stretch="1,1"> | ||
| 2500 | <property name="spacing"> | ||
| 2501 | <number>3</number> | ||
| 2502 | </property> | ||
| 2503 | <property name="leftMargin"> | ||
| 2504 | <number>0</number> | ||
| 2505 | </property> | ||
| 2506 | <property name="topMargin"> | ||
| 2507 | <number>0</number> | ||
| 2508 | </property> | ||
| 2509 | <property name="rightMargin"> | ||
| 2510 | <number>0</number> | ||
| 2511 | </property> | ||
| 2512 | <property name="bottomMargin"> | ||
| 2513 | <number>0</number> | ||
| 2514 | </property> | ||
| 2515 | <item> | ||
| 2516 | <widget class="QWidget" name="topRightInputAdvanced" native="true"> | ||
| 2517 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 2518 | <property name="leftMargin"> | ||
| 2519 | <number>0</number> | ||
| 2520 | </property> | ||
| 2521 | <property name="topMargin"> | ||
| 2522 | <number>0</number> | ||
| 2523 | </property> | ||
| 2524 | <property name="rightMargin"> | ||
| 2525 | <number>0</number> | ||
| 2526 | </property> | ||
| 2527 | <property name="bottomMargin"> | ||
| 2528 | <number>0</number> | ||
| 2529 | </property> | ||
| 2530 | <item> | ||
| 2531 | <widget class="QGroupBox" name="gridGroupBox_3"> | ||
| 2532 | <property name="title"> | ||
| 2533 | <string>Other</string> | ||
| 2534 | </property> | ||
| 2535 | <layout class="QGridLayout" name="gridLayout_3"> | ||
| 2536 | <item row="0" column="0"> | ||
| 2537 | <widget class="QCheckBox" name="keyboard_enabled"> | ||
| 2538 | <property name="minimumSize"> | ||
| 2539 | <size> | ||
| 2540 | <width>0</width> | ||
| 2541 | <height>23</height> | ||
| 2542 | </size> | ||
| 2543 | </property> | ||
| 2544 | <property name="text"> | ||
| 2545 | <string>Keyboard</string> | ||
| 2546 | </property> | ||
| 2547 | </widget> | ||
| 2548 | </item> | ||
| 2549 | <item row="4" column="2"> | ||
| 2550 | <widget class="QPushButton" name="touchscreen_advanced"> | ||
| 2551 | <property name="text"> | ||
| 2552 | <string>Advanced</string> | ||
| 2553 | </property> | ||
| 2554 | </widget> | ||
| 2555 | </item> | ||
| 2556 | <item row="1" column="1"> | ||
| 2557 | <spacer name="horizontalSpacer_8"> | ||
| 2558 | <property name="orientation"> | ||
| 2559 | <enum>Qt::Horizontal</enum> | ||
| 2560 | </property> | ||
| 2561 | <property name="sizeType"> | ||
| 2562 | <enum>QSizePolicy::Fixed</enum> | ||
| 2563 | </property> | ||
| 2564 | <property name="sizeHint" stdset="0"> | ||
| 2565 | <size> | ||
| 2566 | <width>76</width> | ||
| 2567 | <height>20</height> | ||
| 2568 | </size> | ||
| 2569 | </property> | ||
| 2570 | </spacer> | ||
| 2571 | </item> | ||
| 2572 | <item row="1" column="2"> | ||
| 2573 | <widget class="QPushButton" name="mouse_advanced"> | ||
| 2574 | <property name="text"> | ||
| 2575 | <string>Advanced</string> | ||
| 2576 | </property> | ||
| 2577 | </widget> | ||
| 2578 | </item> | ||
| 2579 | <item row="4" column="0"> | ||
| 2580 | <widget class="QCheckBox" name="touchscreen_enabled"> | ||
| 2581 | <property name="text"> | ||
| 2582 | <string>Touchscreen</string> | ||
| 2583 | </property> | ||
| 2584 | </widget> | ||
| 2585 | </item> | ||
| 2586 | <item row="1" column="0"> | ||
| 2587 | <widget class="QCheckBox" name="mouse_enabled"> | ||
| 2588 | <property name="minimumSize"> | ||
| 2589 | <size> | ||
| 2590 | <width>0</width> | ||
| 2591 | <height>23</height> | ||
| 2592 | </size> | ||
| 2593 | </property> | ||
| 2594 | <property name="text"> | ||
| 2595 | <string>Mouse</string> | ||
| 2596 | </property> | ||
| 2597 | </widget> | ||
| 2598 | </item> | ||
| 2599 | <item row="6" column="0"> | ||
| 2600 | <widget class="QLabel" name="motion_touch"> | ||
| 2601 | <property name="text"> | ||
| 2602 | <string>Motion / Touch</string> | ||
| 2603 | </property> | ||
| 2604 | </widget> | ||
| 2605 | </item> | ||
| 2606 | <item row="6" column="2"> | ||
| 2607 | <widget class="QPushButton" name="buttonMotionTouch"> | ||
| 2608 | <property name="text"> | ||
| 2609 | <string>Configure</string> | ||
| 2610 | </property> | ||
| 2611 | </widget> | ||
| 2612 | </item> | ||
| 2613 | <item row="5" column="0"> | ||
| 2614 | <widget class="QCheckBox" name="debug_enabled"> | ||
| 2615 | <property name="text"> | ||
| 2616 | <string>Debug Controller</string> | ||
| 2617 | </property> | ||
| 2618 | </widget> | ||
| 2619 | </item> | ||
| 2620 | <item row="5" column="2"> | ||
| 2621 | <widget class="QPushButton" name="debug_configure"> | ||
| 2622 | <property name="text"> | ||
| 2623 | <string>Configure</string> | ||
| 2624 | </property> | ||
| 2625 | </widget> | ||
| 2626 | </item> | ||
| 2627 | </layout> | ||
| 2628 | </widget> | ||
| 2629 | </item> | ||
| 2630 | <item> | ||
| 2631 | <spacer name="verticalSpacer"> | ||
| 2632 | <property name="orientation"> | ||
| 2633 | <enum>Qt::Vertical</enum> | ||
| 2634 | </property> | ||
| 2635 | <property name="sizeHint" stdset="0"> | ||
| 2636 | <size> | ||
| 2637 | <width>20</width> | ||
| 2638 | <height>40</height> | ||
| 2639 | </size> | ||
| 2640 | </property> | ||
| 2641 | </spacer> | ||
| 2642 | </item> | ||
| 2643 | </layout> | ||
| 2644 | </widget> | ||
| 2645 | </item> | ||
| 2646 | <item> | ||
| 2647 | <widget class="QWidget" name="bottomRightInputAdvanced" native="true"> | ||
| 2648 | <layout class="QVBoxLayout" name="verticalLayout_2"> | ||
| 2649 | <property name="leftMargin"> | ||
| 2650 | <number>0</number> | ||
| 2651 | </property> | ||
| 2652 | <property name="topMargin"> | ||
| 2653 | <number>0</number> | ||
| 2654 | </property> | ||
| 2655 | <property name="rightMargin"> | ||
| 2656 | <number>0</number> | ||
| 2657 | </property> | ||
| 2658 | <property name="bottomMargin"> | ||
| 2659 | <number>0</number> | ||
| 2660 | </property> | ||
| 2661 | <item> | ||
| 2662 | <spacer name="mainVerticalSpacer"> | ||
| 2663 | <property name="orientation"> | ||
| 2664 | <enum>Qt::Vertical</enum> | ||
| 2665 | </property> | ||
| 2666 | <property name="sizeHint" stdset="0"> | ||
| 2667 | <size> | ||
| 2668 | <width>20</width> | ||
| 2669 | <height>40</height> | ||
| 2670 | </size> | ||
| 2671 | </property> | ||
| 2672 | </spacer> | ||
| 2673 | </item> | ||
| 2674 | </layout> | ||
| 2675 | </widget> | ||
| 2676 | </item> | ||
| 2677 | </layout> | ||
| 2678 | </widget> | ||
| 2679 | </item> | ||
| 2680 | </layout> | ||
| 2681 | </widget> | ||
| 2682 | </item> | ||
| 2683 | </layout> | ||
| 2684 | </widget> | ||
| 2685 | <resources> | ||
| 2686 | </resources> | ||
| 2687 | <connections/> | ||
| 2688 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 597defe8c..13ecb3dc5 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -5,39 +5,97 @@ | |||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <utility> | 7 | #include <utility> |
| 8 | #include <QColorDialog> | ||
| 9 | #include <QGridLayout> | 8 | #include <QGridLayout> |
| 9 | #include <QInputDialog> | ||
| 10 | #include <QKeyEvent> | 10 | #include <QKeyEvent> |
| 11 | #include <QMenu> | 11 | #include <QMenu> |
| 12 | #include <QMessageBox> | 12 | #include <QMessageBox> |
| 13 | #include <QTimer> | 13 | #include <QTimer> |
| 14 | #include "common/assert.h" | ||
| 15 | #include "common/param_package.h" | 14 | #include "common/param_package.h" |
| 15 | #include "core/core.h" | ||
| 16 | #include "core/hle/service/hid/controllers/npad.h" | ||
| 17 | #include "core/hle/service/hid/hid.h" | ||
| 18 | #include "core/hle/service/sm/sm.h" | ||
| 19 | #include "input_common/gcadapter/gc_poller.h" | ||
| 16 | #include "input_common/main.h" | 20 | #include "input_common/main.h" |
| 17 | #include "ui_configure_input_player.h" | 21 | #include "ui_configure_input_player.h" |
| 18 | #include "yuzu/configuration/config.h" | 22 | #include "yuzu/configuration/config.h" |
| 19 | #include "yuzu/configuration/configure_input_player.h" | 23 | #include "yuzu/configuration/configure_input_player.h" |
| 20 | 24 | ||
| 25 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 26 | |||
| 21 | const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> | 27 | const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> |
| 22 | ConfigureInputPlayer::analog_sub_buttons{{ | 28 | ConfigureInputPlayer::analog_sub_buttons{{ |
| 23 | "up", | 29 | "up", |
| 24 | "down", | 30 | "down", |
| 25 | "left", | 31 | "left", |
| 26 | "right", | 32 | "right", |
| 27 | "modifier", | ||
| 28 | }}; | 33 | }}; |
| 29 | 34 | ||
| 30 | static void LayerGridElements(QGridLayout* grid, QWidget* item, QWidget* onTopOf) { | 35 | namespace { |
| 31 | const int index1 = grid->indexOf(item); | 36 | |
| 32 | const int index2 = grid->indexOf(onTopOf); | 37 | void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, |
| 33 | int row, column, rowSpan, columnSpan; | 38 | bool connected) { |
| 34 | grid->getItemPosition(index2, &row, &column, &rowSpan, &columnSpan); | 39 | Core::System& system{Core::System::GetInstance()}; |
| 35 | grid->takeAt(index1); | 40 | if (!system.IsPoweredOn()) { |
| 36 | grid->addWidget(item, row, column, rowSpan, columnSpan); | 41 | return; |
| 42 | } | ||
| 43 | Service::SM::ServiceManager& sm = system.ServiceManager(); | ||
| 44 | |||
| 45 | auto& npad = | ||
| 46 | sm.GetService<Service::HID::Hid>("hid") | ||
| 47 | ->GetAppletResource() | ||
| 48 | ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); | ||
| 49 | |||
| 50 | npad.UpdateControllerAt(npad.MapSettingsTypeToNPad(controller_type), npad_index, connected); | ||
| 51 | } | ||
| 52 | |||
| 53 | /// Maps the controller type combobox index to Controller Type enum | ||
| 54 | constexpr Settings::ControllerType GetControllerTypeFromIndex(int index) { | ||
| 55 | switch (index) { | ||
| 56 | case 0: | ||
| 57 | default: | ||
| 58 | return Settings::ControllerType::ProController; | ||
| 59 | case 1: | ||
| 60 | return Settings::ControllerType::DualJoyconDetached; | ||
| 61 | case 2: | ||
| 62 | return Settings::ControllerType::LeftJoycon; | ||
| 63 | case 3: | ||
| 64 | return Settings::ControllerType::RightJoycon; | ||
| 65 | case 4: | ||
| 66 | return Settings::ControllerType::Handheld; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | /// Maps the Controller Type enum to controller type combobox index | ||
| 71 | constexpr int GetIndexFromControllerType(Settings::ControllerType type) { | ||
| 72 | switch (type) { | ||
| 73 | case Settings::ControllerType::ProController: | ||
| 74 | default: | ||
| 75 | return 0; | ||
| 76 | case Settings::ControllerType::DualJoyconDetached: | ||
| 77 | return 1; | ||
| 78 | case Settings::ControllerType::LeftJoycon: | ||
| 79 | return 2; | ||
| 80 | case Settings::ControllerType::RightJoycon: | ||
| 81 | return 3; | ||
| 82 | case Settings::ControllerType::Handheld: | ||
| 83 | return 4; | ||
| 84 | } | ||
| 37 | } | 85 | } |
| 38 | 86 | ||
| 39 | static QString GetKeyName(int key_code) { | 87 | QString GetKeyName(int key_code) { |
| 40 | switch (key_code) { | 88 | switch (key_code) { |
| 89 | case Qt::LeftButton: | ||
| 90 | return QObject::tr("Click 0"); | ||
| 91 | case Qt::RightButton: | ||
| 92 | return QObject::tr("Click 1"); | ||
| 93 | case Qt::MiddleButton: | ||
| 94 | return QObject::tr("Click 2"); | ||
| 95 | case Qt::BackButton: | ||
| 96 | return QObject::tr("Click 3"); | ||
| 97 | case Qt::ForwardButton: | ||
| 98 | return QObject::tr("Click 4"); | ||
| 41 | case Qt::Key_Shift: | 99 | case Qt::Key_Shift: |
| 42 | return QObject::tr("Shift"); | 100 | return QObject::tr("Shift"); |
| 43 | case Qt::Key_Control: | 101 | case Qt::Key_Control: |
| @@ -51,9 +109,16 @@ static QString GetKeyName(int key_code) { | |||
| 51 | } | 109 | } |
| 52 | } | 110 | } |
| 53 | 111 | ||
| 54 | static void SetAnalogButton(const Common::ParamPackage& input_param, | 112 | void SetAnalogParam(const Common::ParamPackage& input_param, Common::ParamPackage& analog_param, |
| 55 | Common::ParamPackage& analog_param, const std::string& button_name) { | 113 | const std::string& button_name) { |
| 56 | if (analog_param.Get("engine", "") != "analog_from_button") { | 114 | // The poller returned a complete axis, so set all the buttons |
| 115 | if (input_param.Has("axis_x") && input_param.Has("axis_y")) { | ||
| 116 | analog_param = input_param; | ||
| 117 | return; | ||
| 118 | } | ||
| 119 | // Check if the current configuration has either no engine or an axis binding. | ||
| 120 | // Clears out the old binding and adds one with analog_from_button. | ||
| 121 | if (!analog_param.Has("engine") || analog_param.Has("axis_x") || analog_param.Has("axis_y")) { | ||
| 57 | analog_param = { | 122 | analog_param = { |
| 58 | {"engine", "analog_from_button"}, | 123 | {"engine", "analog_from_button"}, |
| 59 | }; | 124 | }; |
| @@ -61,7 +126,7 @@ static void SetAnalogButton(const Common::ParamPackage& input_param, | |||
| 61 | analog_param.Set(button_name, input_param.Serialize()); | 126 | analog_param.Set(button_name, input_param.Serialize()); |
| 62 | } | 127 | } |
| 63 | 128 | ||
| 64 | static QString ButtonToText(const Common::ParamPackage& param) { | 129 | QString ButtonToText(const Common::ParamPackage& param) { |
| 65 | if (!param.Has("engine")) { | 130 | if (!param.Has("engine")) { |
| 66 | return QObject::tr("[not set]"); | 131 | return QObject::tr("[not set]"); |
| 67 | } | 132 | } |
| @@ -111,7 +176,7 @@ static QString ButtonToText(const Common::ParamPackage& param) { | |||
| 111 | return QObject::tr("[unknown]"); | 176 | return QObject::tr("[unknown]"); |
| 112 | } | 177 | } |
| 113 | 178 | ||
| 114 | static QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { | 179 | QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { |
| 115 | if (!param.Has("engine")) { | 180 | if (!param.Has("engine")) { |
| 116 | return QObject::tr("[not set]"); | 181 | return QObject::tr("[not set]"); |
| 117 | } | 182 | } |
| @@ -161,22 +226,25 @@ static QString AnalogToText(const Common::ParamPackage& param, const std::string | |||
| 161 | } | 226 | } |
| 162 | return QObject::tr("[unknown]"); | 227 | return QObject::tr("[unknown]"); |
| 163 | } | 228 | } |
| 164 | 229 | } // namespace | |
| 165 | ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, bool debug) | 230 | |
| 166 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), | 231 | ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, |
| 167 | debug(debug), timeout_timer(std::make_unique<QTimer>()), | 232 | QWidget* bottom_row, |
| 168 | poll_timer(std::make_unique<QTimer>()) { | 233 | InputCommon::InputSubsystem* input_subsystem_, |
| 234 | bool debug) | ||
| 235 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), | ||
| 236 | debug(debug), input_subsystem{input_subsystem_}, timeout_timer(std::make_unique<QTimer>()), | ||
| 237 | poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) { | ||
| 169 | ui->setupUi(this); | 238 | ui->setupUi(this); |
| 239 | |||
| 170 | setFocusPolicy(Qt::ClickFocus); | 240 | setFocusPolicy(Qt::ClickFocus); |
| 171 | 241 | ||
| 172 | button_map = { | 242 | button_map = { |
| 173 | ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, | 243 | ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, |
| 174 | ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, | 244 | ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, |
| 175 | ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, | 245 | ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, |
| 176 | ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, | 246 | ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, |
| 177 | ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown, | 247 | ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, |
| 178 | ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown, | ||
| 179 | ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, | ||
| 180 | }; | 248 | }; |
| 181 | 249 | ||
| 182 | analog_map_buttons = {{ | 250 | analog_map_buttons = {{ |
| @@ -185,223 +253,165 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 185 | ui->buttonLStickDown, | 253 | ui->buttonLStickDown, |
| 186 | ui->buttonLStickLeft, | 254 | ui->buttonLStickLeft, |
| 187 | ui->buttonLStickRight, | 255 | ui->buttonLStickRight, |
| 188 | ui->buttonLStickMod, | ||
| 189 | }, | 256 | }, |
| 190 | { | 257 | { |
| 191 | ui->buttonRStickUp, | 258 | ui->buttonRStickUp, |
| 192 | ui->buttonRStickDown, | 259 | ui->buttonRStickDown, |
| 193 | ui->buttonRStickLeft, | 260 | ui->buttonRStickLeft, |
| 194 | ui->buttonRStickRight, | 261 | ui->buttonRStickRight, |
| 195 | ui->buttonRStickMod, | ||
| 196 | }, | 262 | }, |
| 197 | }}; | 263 | }}; |
| 198 | 264 | ||
| 199 | debug_hidden = { | 265 | analog_map_deadzone_label = {ui->labelLStickDeadzone, ui->labelRStickDeadzone}; |
| 200 | ui->buttonSL, ui->labelSL, | 266 | analog_map_deadzone_slider = {ui->sliderLStickDeadzone, ui->sliderRStickDeadzone}; |
| 201 | ui->buttonSR, ui->labelSR, | 267 | analog_map_modifier_groupbox = {ui->buttonLStickModGroup, ui->buttonRStickModGroup}; |
| 202 | ui->buttonLStick, ui->labelLStickPressed, | 268 | analog_map_modifier_label = {ui->labelLStickModifierRange, ui->labelRStickModifierRange}; |
| 203 | ui->buttonRStick, ui->labelRStickPressed, | 269 | analog_map_modifier_slider = {ui->sliderLStickModifierRange, ui->sliderRStickModifierRange}; |
| 204 | ui->buttonHome, ui->labelHome, | 270 | analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup}; |
| 205 | ui->buttonScreenshot, ui->labelScreenshot, | 271 | analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange}; |
| 206 | }; | ||
| 207 | |||
| 208 | auto layout = Settings::values.players[player_index].type; | ||
| 209 | if (debug) | ||
| 210 | layout = Settings::ControllerType::DualJoycon; | ||
| 211 | |||
| 212 | switch (layout) { | ||
| 213 | case Settings::ControllerType::ProController: | ||
| 214 | case Settings::ControllerType::DualJoycon: | ||
| 215 | layout_hidden = { | ||
| 216 | ui->buttonSL, | ||
| 217 | ui->labelSL, | ||
| 218 | ui->buttonSR, | ||
| 219 | ui->labelSR, | ||
| 220 | }; | ||
| 221 | break; | ||
| 222 | case Settings::ControllerType::LeftJoycon: | ||
| 223 | layout_hidden = { | ||
| 224 | ui->right_body_button, | ||
| 225 | ui->right_buttons_button, | ||
| 226 | ui->right_body_label, | ||
| 227 | ui->right_buttons_label, | ||
| 228 | ui->buttonR, | ||
| 229 | ui->labelR, | ||
| 230 | ui->buttonZR, | ||
| 231 | ui->labelZR, | ||
| 232 | ui->labelHome, | ||
| 233 | ui->buttonHome, | ||
| 234 | ui->buttonPlus, | ||
| 235 | ui->labelPlus, | ||
| 236 | ui->RStick, | ||
| 237 | ui->faceButtons, | ||
| 238 | }; | ||
| 239 | break; | ||
| 240 | case Settings::ControllerType::RightJoycon: | ||
| 241 | layout_hidden = { | ||
| 242 | ui->left_body_button, ui->left_buttons_button, | ||
| 243 | ui->left_body_label, ui->left_buttons_label, | ||
| 244 | ui->buttonL, ui->labelL, | ||
| 245 | ui->buttonZL, ui->labelZL, | ||
| 246 | ui->labelScreenshot, ui->buttonScreenshot, | ||
| 247 | ui->buttonMinus, ui->labelMinus, | ||
| 248 | ui->LStick, ui->Dpad, | ||
| 249 | }; | ||
| 250 | break; | ||
| 251 | } | ||
| 252 | |||
| 253 | if (debug || layout == Settings::ControllerType::ProController) { | ||
| 254 | ui->controller_color->hide(); | ||
| 255 | } else { | ||
| 256 | if (layout == Settings::ControllerType::LeftJoycon || | ||
| 257 | layout == Settings::ControllerType::RightJoycon) { | ||
| 258 | ui->horizontalSpacer_4->setGeometry({0, 0, 0, 0}); | ||
| 259 | |||
| 260 | LayerGridElements(ui->buttons, ui->shoulderButtons, ui->Dpad); | ||
| 261 | LayerGridElements(ui->buttons, ui->misc, ui->RStick); | ||
| 262 | LayerGridElements(ui->buttons, ui->Dpad, ui->faceButtons); | ||
| 263 | LayerGridElements(ui->buttons, ui->RStick, ui->LStick); | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | for (auto* widget : layout_hidden) | ||
| 268 | widget->setVisible(false); | ||
| 269 | |||
| 270 | analog_map_stick = {ui->buttonLStickAnalog, ui->buttonRStickAnalog}; | ||
| 271 | analog_map_deadzone_and_modifier_slider = {ui->sliderLStickDeadzoneAndModifier, | ||
| 272 | ui->sliderRStickDeadzoneAndModifier}; | ||
| 273 | analog_map_deadzone_and_modifier_slider_label = {ui->labelLStickDeadzoneAndModifier, | ||
| 274 | ui->labelRStickDeadzoneAndModifier}; | ||
| 275 | 272 | ||
| 276 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { | 273 | const auto ConfigureButtonClick = [&](QPushButton* button, Common::ParamPackage* param, |
| 277 | auto* const button = button_map[button_id]; | 274 | int default_val) { |
| 278 | if (button == nullptr) { | ||
| 279 | continue; | ||
| 280 | } | ||
| 281 | |||
| 282 | button->setContextMenuPolicy(Qt::CustomContextMenu); | ||
| 283 | connect(button, &QPushButton::clicked, [=, this] { | 275 | connect(button, &QPushButton::clicked, [=, this] { |
| 284 | HandleClick( | 276 | HandleClick( |
| 285 | button_map[button_id], | 277 | button, |
| 286 | [=, this](Common::ParamPackage params) { | 278 | [=, this](Common::ParamPackage params) { |
| 287 | // Workaround for ZL & ZR for analog triggers like on XBOX controllors. | 279 | // Workaround for ZL & ZR for analog triggers like on XBOX |
| 288 | // Analog triggers (from controllers like the XBOX controller) would not | 280 | // controllers. Analog triggers (from controllers like the XBOX |
| 289 | // work due to a different range of their signals (from 0 to 255 on | 281 | // controller) would not work due to a different range of their |
| 290 | // analog triggers instead of -32768 to 32768 on analog joysticks). The | 282 | // signals (from 0 to 255 on analog triggers instead of -32768 to |
| 291 | // SDL driver misinterprets analog triggers as analog joysticks. | 283 | // 32768 on analog joysticks). The SDL driver misinterprets analog |
| 284 | // triggers as analog joysticks. | ||
| 292 | // TODO: reinterpret the signal range for analog triggers to map the | 285 | // TODO: reinterpret the signal range for analog triggers to map the |
| 293 | // values correctly. This is required for the correct emulation of the | 286 | // values correctly. This is required for the correct emulation of |
| 294 | // analog triggers of the GameCube controller. | 287 | // the analog triggers of the GameCube controller. |
| 295 | if (button_id == Settings::NativeButton::ZL || | 288 | if (button == ui->buttonZL || button == ui->buttonZR) { |
| 296 | button_id == Settings::NativeButton::ZR) { | ||
| 297 | params.Set("direction", "+"); | 289 | params.Set("direction", "+"); |
| 298 | params.Set("threshold", "0.5"); | 290 | params.Set("threshold", "0.5"); |
| 299 | } | 291 | } |
| 300 | buttons_param[button_id] = std::move(params); | 292 | *param = std::move(params); |
| 301 | }, | 293 | }, |
| 302 | InputCommon::Polling::DeviceType::Button); | 294 | InputCommon::Polling::DeviceType::Button); |
| 303 | }); | 295 | }); |
| 304 | connect(button, &QPushButton::customContextMenuRequested, | 296 | }; |
| 305 | [=, this](const QPoint& menu_location) { | 297 | |
| 306 | QMenu context_menu; | 298 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { |
| 307 | context_menu.addAction(tr("Clear"), [&] { | 299 | auto* const button = button_map[button_id]; |
| 308 | buttons_param[button_id].Clear(); | 300 | if (button == nullptr) { |
| 309 | button_map[button_id]->setText(tr("[not set]")); | 301 | continue; |
| 310 | }); | 302 | } |
| 311 | context_menu.addAction(tr("Restore Default"), [&] { | 303 | ConfigureButtonClick(button_map[button_id], &buttons_param[button_id], |
| 312 | buttons_param[button_id] = Common::ParamPackage{ | 304 | Config::default_buttons[button_id]); |
| 313 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; | ||
| 314 | button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); | ||
| 315 | }); | ||
| 316 | context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); | ||
| 317 | }); | ||
| 318 | } | 305 | } |
| 319 | 306 | ||
| 320 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 307 | // Handle clicks for the modifier buttons as well. |
| 321 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | 308 | ConfigureButtonClick(ui->buttonLStickMod, &lstick_mod, Config::default_stick_mod[0]); |
| 309 | ConfigureButtonClick(ui->buttonRStickMod, &rstick_mod, Config::default_stick_mod[1]); | ||
| 310 | |||
| 311 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | ||
| 312 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | ||
| 322 | auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; | 313 | auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; |
| 314 | |||
| 323 | if (analog_button == nullptr) { | 315 | if (analog_button == nullptr) { |
| 324 | continue; | 316 | continue; |
| 325 | } | 317 | } |
| 326 | 318 | ||
| 327 | analog_button->setContextMenuPolicy(Qt::CustomContextMenu); | ||
| 328 | connect(analog_button, &QPushButton::clicked, [=, this] { | 319 | connect(analog_button, &QPushButton::clicked, [=, this] { |
| 329 | HandleClick( | 320 | HandleClick( |
| 330 | analog_map_buttons[analog_id][sub_button_id], | 321 | analog_map_buttons[analog_id][sub_button_id], |
| 331 | [=, this](const Common::ParamPackage& params) { | 322 | [=, this](const Common::ParamPackage& params) { |
| 332 | SetAnalogButton(params, analogs_param[analog_id], | 323 | SetAnalogParam(params, analogs_param[analog_id], |
| 333 | analog_sub_buttons[sub_button_id]); | 324 | analog_sub_buttons[sub_button_id]); |
| 334 | }, | 325 | }, |
| 335 | InputCommon::Polling::DeviceType::Button); | 326 | InputCommon::Polling::DeviceType::AnalogPreferred); |
| 336 | }); | 327 | }); |
| 337 | connect(analog_button, &QPushButton::customContextMenuRequested, | ||
| 338 | [=, this](const QPoint& menu_location) { | ||
| 339 | QMenu context_menu; | ||
| 340 | context_menu.addAction(tr("Clear"), [&] { | ||
| 341 | analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]); | ||
| 342 | analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); | ||
| 343 | }); | ||
| 344 | context_menu.addAction(tr("Restore Default"), [&] { | ||
| 345 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( | ||
| 346 | Config::default_analogs[analog_id][sub_button_id])}; | ||
| 347 | SetAnalogButton(params, analogs_param[analog_id], | ||
| 348 | analog_sub_buttons[sub_button_id]); | ||
| 349 | analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( | ||
| 350 | analogs_param[analog_id], analog_sub_buttons[sub_button_id])); | ||
| 351 | }); | ||
| 352 | context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal( | ||
| 353 | menu_location)); | ||
| 354 | }); | ||
| 355 | } | 328 | } |
| 356 | connect(analog_map_stick[analog_id], &QPushButton::clicked, [=, this] { | ||
| 357 | if (QMessageBox::information( | ||
| 358 | this, tr("Information"), | ||
| 359 | tr("After pressing OK, first move your joystick horizontally, " | ||
| 360 | "and then vertically."), | ||
| 361 | QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { | ||
| 362 | HandleClick( | ||
| 363 | analog_map_stick[analog_id], | ||
| 364 | [=, this](const Common::ParamPackage& params) { | ||
| 365 | analogs_param[analog_id] = params; | ||
| 366 | }, | ||
| 367 | InputCommon::Polling::DeviceType::Analog); | ||
| 368 | } | ||
| 369 | }); | ||
| 370 | 329 | ||
| 371 | connect(analog_map_deadzone_and_modifier_slider[analog_id], &QSlider::valueChanged, | 330 | connect(analog_map_range_spinbox[analog_id], qOverload<int>(&QSpinBox::valueChanged), |
| 372 | [=, this] { | 331 | [=, this] { |
| 373 | const float slider_value = | 332 | const auto spinbox_value = analog_map_range_spinbox[analog_id]->value(); |
| 374 | analog_map_deadzone_and_modifier_slider[analog_id]->value(); | 333 | analogs_param[analog_id].Set("range", spinbox_value / 100.0f); |
| 375 | if (analogs_param[analog_id].Get("engine", "") == "sdl" || | ||
| 376 | analogs_param[analog_id].Get("engine", "") == "gcpad") { | ||
| 377 | analog_map_deadzone_and_modifier_slider_label[analog_id]->setText( | ||
| 378 | tr("Deadzone: %1%").arg(slider_value)); | ||
| 379 | analogs_param[analog_id].Set("deadzone", slider_value / 100.0f); | ||
| 380 | } else { | ||
| 381 | analog_map_deadzone_and_modifier_slider_label[analog_id]->setText( | ||
| 382 | tr("Modifier Scale: %1%").arg(slider_value)); | ||
| 383 | analogs_param[analog_id].Set("modifier_scale", slider_value / 100.0f); | ||
| 384 | } | ||
| 385 | }); | 334 | }); |
| 335 | |||
| 336 | connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] { | ||
| 337 | const auto slider_value = analog_map_deadzone_slider[analog_id]->value(); | ||
| 338 | analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value)); | ||
| 339 | analogs_param[analog_id].Set("deadzone", slider_value / 100.0f); | ||
| 340 | }); | ||
| 341 | |||
| 342 | connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] { | ||
| 343 | const auto slider_value = analog_map_modifier_slider[analog_id]->value(); | ||
| 344 | analog_map_modifier_label[analog_id]->setText( | ||
| 345 | tr("Modifier Range: %1%").arg(slider_value)); | ||
| 346 | analogs_param[analog_id].Set("modifier_scale", slider_value / 100.0f); | ||
| 347 | }); | ||
| 386 | } | 348 | } |
| 387 | 349 | ||
| 388 | connect(ui->buttonClearAll, &QPushButton::clicked, [this] { ClearAll(); }); | 350 | // Player Connected checkbox |
| 389 | connect(ui->buttonRestoreDefaults, &QPushButton::clicked, [this] { RestoreDefaults(); }); | 351 | connect(ui->groupConnectedController, &QGroupBox::toggled, |
| 352 | [this](bool checked) { emit Connected(checked); }); | ||
| 353 | |||
| 354 | // Set up controller type. Only Player 1 can choose Handheld. | ||
| 355 | ui->comboControllerType->clear(); | ||
| 356 | |||
| 357 | QStringList controller_types = { | ||
| 358 | tr("Pro Controller"), | ||
| 359 | tr("Dual Joycons"), | ||
| 360 | tr("Left Joycon"), | ||
| 361 | tr("Right Joycon"), | ||
| 362 | }; | ||
| 363 | |||
| 364 | if (player_index == 0) { | ||
| 365 | controller_types.append(tr("Handheld")); | ||
| 366 | connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 367 | [this](int index) { | ||
| 368 | emit HandheldStateChanged(GetControllerTypeFromIndex(index) == | ||
| 369 | Settings::ControllerType::Handheld); | ||
| 370 | }); | ||
| 371 | } | ||
| 372 | |||
| 373 | // The Debug Controller can only choose the Pro Controller. | ||
| 374 | if (debug) { | ||
| 375 | ui->buttonScreenshot->setEnabled(false); | ||
| 376 | ui->buttonHome->setEnabled(false); | ||
| 377 | ui->groupConnectedController->setCheckable(false); | ||
| 378 | QStringList debug_controller_types = { | ||
| 379 | tr("Pro Controller"), | ||
| 380 | }; | ||
| 381 | ui->comboControllerType->addItems(debug_controller_types); | ||
| 382 | } else { | ||
| 383 | ui->comboControllerType->addItems(controller_types); | ||
| 384 | } | ||
| 385 | |||
| 386 | UpdateControllerIcon(); | ||
| 387 | UpdateControllerAvailableButtons(); | ||
| 388 | connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) { | ||
| 389 | UpdateControllerIcon(); | ||
| 390 | UpdateControllerAvailableButtons(); | ||
| 391 | }); | ||
| 392 | |||
| 393 | connect(ui->comboDevices, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||
| 394 | &ConfigureInputPlayer::UpdateMappingWithDefaults); | ||
| 395 | |||
| 396 | ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); | ||
| 397 | UpdateInputDevices(); | ||
| 398 | connect(ui->buttonRefreshDevices, &QPushButton::clicked, | ||
| 399 | [this] { emit RefreshInputDevices(); }); | ||
| 390 | 400 | ||
| 391 | timeout_timer->setSingleShot(true); | 401 | timeout_timer->setSingleShot(true); |
| 392 | connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); | 402 | connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); |
| 393 | 403 | ||
| 394 | connect(poll_timer.get(), &QTimer::timeout, [this] { | 404 | connect(poll_timer.get(), &QTimer::timeout, [this] { |
| 395 | Common::ParamPackage params; | 405 | Common::ParamPackage params; |
| 396 | if (InputCommon::GetGCButtons()->IsPolling()) { | 406 | if (input_subsystem->GetGCButtons()->IsPolling()) { |
| 397 | params = InputCommon::GetGCButtons()->GetNextInput(); | 407 | params = input_subsystem->GetGCButtons()->GetNextInput(); |
| 398 | if (params.Has("engine")) { | 408 | if (params.Has("engine")) { |
| 399 | SetPollingResult(params, false); | 409 | SetPollingResult(params, false); |
| 400 | return; | 410 | return; |
| 401 | } | 411 | } |
| 402 | } | 412 | } |
| 403 | if (InputCommon::GetGCAnalogs()->IsPolling()) { | 413 | if (input_subsystem->GetGCAnalogs()->IsPolling()) { |
| 404 | params = InputCommon::GetGCAnalogs()->GetNextInput(); | 414 | params = input_subsystem->GetGCAnalogs()->GetNextInput(); |
| 405 | if (params.Has("engine")) { | 415 | if (params.Has("engine")) { |
| 406 | SetPollingResult(params, false); | 416 | SetPollingResult(params, false); |
| 407 | return; | 417 | return; |
| @@ -416,20 +426,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 416 | } | 426 | } |
| 417 | }); | 427 | }); |
| 418 | 428 | ||
| 419 | controller_color_buttons = { | ||
| 420 | ui->left_body_button, | ||
| 421 | ui->left_buttons_button, | ||
| 422 | ui->right_body_button, | ||
| 423 | ui->right_buttons_button, | ||
| 424 | }; | ||
| 425 | |||
| 426 | for (std::size_t i = 0; i < controller_color_buttons.size(); ++i) { | ||
| 427 | connect(controller_color_buttons[i], &QPushButton::clicked, this, | ||
| 428 | [this, i] { OnControllerButtonClick(static_cast<int>(i)); }); | ||
| 429 | } | ||
| 430 | |||
| 431 | LoadConfiguration(); | 429 | LoadConfiguration(); |
| 432 | resize(0, 0); | ||
| 433 | 430 | ||
| 434 | // TODO(wwylele): enable this when we actually emulate it | 431 | // TODO(wwylele): enable this when we actually emulate it |
| 435 | ui->buttonHome->setEnabled(false); | 432 | ui->buttonHome->setEnabled(false); |
| @@ -438,27 +435,43 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 438 | ConfigureInputPlayer::~ConfigureInputPlayer() = default; | 435 | ConfigureInputPlayer::~ConfigureInputPlayer() = default; |
| 439 | 436 | ||
| 440 | void ConfigureInputPlayer::ApplyConfiguration() { | 437 | void ConfigureInputPlayer::ApplyConfiguration() { |
| 441 | auto& buttons = | 438 | auto& player = Settings::values.players[player_index]; |
| 442 | debug ? Settings::values.debug_pad_buttons : Settings::values.players[player_index].buttons; | 439 | auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons; |
| 443 | auto& analogs = | 440 | auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs; |
| 444 | debug ? Settings::values.debug_pad_analogs : Settings::values.players[player_index].analogs; | ||
| 445 | 441 | ||
| 446 | std::transform(buttons_param.begin(), buttons_param.end(), buttons.begin(), | 442 | std::transform(buttons_param.begin(), buttons_param.end(), buttons.begin(), |
| 447 | [](const Common::ParamPackage& param) { return param.Serialize(); }); | 443 | [](const Common::ParamPackage& param) { return param.Serialize(); }); |
| 448 | std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(), | 444 | std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(), |
| 449 | [](const Common::ParamPackage& param) { return param.Serialize(); }); | 445 | [](const Common::ParamPackage& param) { return param.Serialize(); }); |
| 450 | 446 | ||
| 451 | if (debug) | 447 | if (debug) { |
| 452 | return; | 448 | return; |
| 449 | } | ||
| 450 | |||
| 451 | player.controller_type = | ||
| 452 | static_cast<Settings::ControllerType>(ui->comboControllerType->currentIndex()); | ||
| 453 | player.connected = ui->groupConnectedController->isChecked(); | ||
| 453 | 454 | ||
| 454 | std::array<u32, 4> colors{}; | 455 | // Player 2-8 |
| 455 | std::transform(controller_colors.begin(), controller_colors.end(), colors.begin(), | 456 | if (player_index != 0) { |
| 456 | [](QColor color) { return color.rgb(); }); | 457 | UpdateController(player.controller_type, player_index, player.connected); |
| 458 | return; | ||
| 459 | } | ||
| 457 | 460 | ||
| 458 | Settings::values.players[player_index].body_color_left = colors[0]; | 461 | // Player 1 and Handheld |
| 459 | Settings::values.players[player_index].button_color_left = colors[1]; | 462 | auto& handheld = Settings::values.players[HANDHELD_INDEX]; |
| 460 | Settings::values.players[player_index].body_color_right = colors[2]; | 463 | // If Handheld is selected, copy all the settings from Player 1 to Handheld. |
| 461 | Settings::values.players[player_index].button_color_right = colors[3]; | 464 | if (player.controller_type == Settings::ControllerType::Handheld) { |
| 465 | handheld = player; | ||
| 466 | handheld.connected = ui->groupConnectedController->isChecked(); | ||
| 467 | player.connected = false; // Disconnect Player 1 | ||
| 468 | } else { | ||
| 469 | player.connected = ui->groupConnectedController->isChecked(); | ||
| 470 | handheld.connected = false; // Disconnect Handheld | ||
| 471 | } | ||
| 472 | |||
| 473 | UpdateController(player.controller_type, player_index, player.connected); | ||
| 474 | UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected); | ||
| 462 | } | 475 | } |
| 463 | 476 | ||
| 464 | void ConfigureInputPlayer::changeEvent(QEvent* event) { | 477 | void ConfigureInputPlayer::changeEvent(QEvent* event) { |
| @@ -466,24 +479,16 @@ void ConfigureInputPlayer::changeEvent(QEvent* event) { | |||
| 466 | RetranslateUI(); | 479 | RetranslateUI(); |
| 467 | } | 480 | } |
| 468 | 481 | ||
| 469 | QDialog::changeEvent(event); | 482 | QWidget::changeEvent(event); |
| 470 | } | 483 | } |
| 471 | 484 | ||
| 472 | void ConfigureInputPlayer::RetranslateUI() { | 485 | void ConfigureInputPlayer::RetranslateUI() { |
| 473 | ui->retranslateUi(this); | 486 | ui->retranslateUi(this); |
| 474 | UpdateButtonLabels(); | 487 | UpdateUI(); |
| 475 | } | ||
| 476 | |||
| 477 | void ConfigureInputPlayer::OnControllerButtonClick(int i) { | ||
| 478 | const QColor new_bg_color = QColorDialog::getColor(controller_colors[i]); | ||
| 479 | if (!new_bg_color.isValid()) | ||
| 480 | return; | ||
| 481 | controller_colors[i] = new_bg_color; | ||
| 482 | controller_color_buttons[i]->setStyleSheet( | ||
| 483 | QStringLiteral("QPushButton { background-color: %1 }").arg(controller_colors[i].name())); | ||
| 484 | } | 488 | } |
| 485 | 489 | ||
| 486 | void ConfigureInputPlayer::LoadConfiguration() { | 490 | void ConfigureInputPlayer::LoadConfiguration() { |
| 491 | auto& player = Settings::values.players[player_index]; | ||
| 487 | if (debug) { | 492 | if (debug) { |
| 488 | std::transform(Settings::values.debug_pad_buttons.begin(), | 493 | std::transform(Settings::values.debug_pad_buttons.begin(), |
| 489 | Settings::values.debug_pad_buttons.end(), buttons_param.begin(), | 494 | Settings::values.debug_pad_buttons.end(), buttons_param.begin(), |
| @@ -492,56 +497,60 @@ void ConfigureInputPlayer::LoadConfiguration() { | |||
| 492 | Settings::values.debug_pad_analogs.end(), analogs_param.begin(), | 497 | Settings::values.debug_pad_analogs.end(), analogs_param.begin(), |
| 493 | [](const std::string& str) { return Common::ParamPackage(str); }); | 498 | [](const std::string& str) { return Common::ParamPackage(str); }); |
| 494 | } else { | 499 | } else { |
| 495 | std::transform(Settings::values.players[player_index].buttons.begin(), | 500 | std::transform(player.buttons.begin(), player.buttons.end(), buttons_param.begin(), |
| 496 | Settings::values.players[player_index].buttons.end(), buttons_param.begin(), | ||
| 497 | [](const std::string& str) { return Common::ParamPackage(str); }); | 501 | [](const std::string& str) { return Common::ParamPackage(str); }); |
| 498 | std::transform(Settings::values.players[player_index].analogs.begin(), | 502 | std::transform(player.analogs.begin(), player.analogs.end(), analogs_param.begin(), |
| 499 | Settings::values.players[player_index].analogs.end(), analogs_param.begin(), | ||
| 500 | [](const std::string& str) { return Common::ParamPackage(str); }); | 503 | [](const std::string& str) { return Common::ParamPackage(str); }); |
| 501 | } | 504 | } |
| 502 | 505 | ||
| 503 | UpdateButtonLabels(); | 506 | UpdateUI(); |
| 504 | 507 | ||
| 505 | if (debug) | 508 | if (debug) { |
| 506 | return; | 509 | return; |
| 510 | } | ||
| 507 | 511 | ||
| 508 | std::array<u32, 4> colors = { | 512 | ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type)); |
| 509 | Settings::values.players[player_index].body_color_left, | 513 | ui->groupConnectedController->setChecked( |
| 510 | Settings::values.players[player_index].button_color_left, | 514 | player.connected || |
| 511 | Settings::values.players[player_index].body_color_right, | 515 | (player_index == 0 && Settings::values.players[HANDHELD_INDEX].connected)); |
| 512 | Settings::values.players[player_index].button_color_right, | 516 | } |
| 513 | }; | ||
| 514 | |||
| 515 | std::transform(colors.begin(), colors.end(), controller_colors.begin(), | ||
| 516 | [](u32 rgb) { return QColor::fromRgb(rgb); }); | ||
| 517 | 517 | ||
| 518 | for (std::size_t i = 0; i < colors.size(); ++i) { | 518 | void ConfigureInputPlayer::UpdateInputDevices() { |
| 519 | controller_color_buttons[i]->setStyleSheet( | 519 | input_devices = input_subsystem->GetInputDevices(); |
| 520 | QStringLiteral("QPushButton { background-color: %1 }") | 520 | ui->comboDevices->clear(); |
| 521 | .arg(controller_colors[i].name())); | 521 | for (auto device : input_devices) { |
| 522 | ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); | ||
| 522 | } | 523 | } |
| 523 | } | 524 | } |
| 524 | 525 | ||
| 525 | void ConfigureInputPlayer::RestoreDefaults() { | 526 | void ConfigureInputPlayer::RestoreDefaults() { |
| 526 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { | 527 | // Reset Buttons |
| 528 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { | ||
| 527 | buttons_param[button_id] = Common::ParamPackage{ | 529 | buttons_param[button_id] = Common::ParamPackage{ |
| 528 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; | 530 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; |
| 529 | } | 531 | } |
| 530 | 532 | ||
| 531 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 533 | // Reset Modifier Buttons |
| 532 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | 534 | lstick_mod = |
| 535 | Common::ParamPackage(InputCommon::GenerateKeyboardParam(Config::default_stick_mod[0])); | ||
| 536 | rstick_mod = | ||
| 537 | Common::ParamPackage(InputCommon::GenerateKeyboardParam(Config::default_stick_mod[1])); | ||
| 538 | |||
| 539 | // Reset Analogs | ||
| 540 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | ||
| 541 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | ||
| 533 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( | 542 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( |
| 534 | Config::default_analogs[analog_id][sub_button_id])}; | 543 | Config::default_analogs[analog_id][sub_button_id])}; |
| 535 | SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); | 544 | SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); |
| 536 | } | 545 | } |
| 537 | } | 546 | } |
| 538 | 547 | UpdateUI(); | |
| 539 | UpdateButtonLabels(); | 548 | UpdateInputDevices(); |
| 540 | ApplyConfiguration(); | 549 | ui->comboControllerType->setCurrentIndex(0); |
| 541 | } | 550 | } |
| 542 | 551 | ||
| 543 | void ConfigureInputPlayer::ClearAll() { | 552 | void ConfigureInputPlayer::ClearAll() { |
| 544 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { | 553 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { |
| 545 | const auto* const button = button_map[button_id]; | 554 | const auto* const button = button_map[button_id]; |
| 546 | if (button == nullptr || !button->isEnabled()) { | 555 | if (button == nullptr || !button->isEnabled()) { |
| 547 | continue; | 556 | continue; |
| @@ -550,8 +559,11 @@ void ConfigureInputPlayer::ClearAll() { | |||
| 550 | buttons_param[button_id].Clear(); | 559 | buttons_param[button_id].Clear(); |
| 551 | } | 560 | } |
| 552 | 561 | ||
| 553 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 562 | lstick_mod.Clear(); |
| 554 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | 563 | rstick_mod.Clear(); |
| 564 | |||
| 565 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | ||
| 566 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | ||
| 555 | const auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; | 567 | const auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; |
| 556 | if (analog_button == nullptr || !analog_button->isEnabled()) { | 568 | if (analog_button == nullptr || !analog_button->isEnabled()) { |
| 557 | continue; | 569 | continue; |
| @@ -561,17 +573,20 @@ void ConfigureInputPlayer::ClearAll() { | |||
| 561 | } | 573 | } |
| 562 | } | 574 | } |
| 563 | 575 | ||
| 564 | UpdateButtonLabels(); | 576 | UpdateUI(); |
| 565 | ApplyConfiguration(); | 577 | UpdateInputDevices(); |
| 566 | } | 578 | } |
| 567 | 579 | ||
| 568 | void ConfigureInputPlayer::UpdateButtonLabels() { | 580 | void ConfigureInputPlayer::UpdateUI() { |
| 569 | for (int button = 0; button < Settings::NativeButton::NumButtons; button++) { | 581 | for (int button = 0; button < Settings::NativeButton::NumButtons; ++button) { |
| 570 | button_map[button]->setText(ButtonToText(buttons_param[button])); | 582 | button_map[button]->setText(ButtonToText(buttons_param[button])); |
| 571 | } | 583 | } |
| 572 | 584 | ||
| 573 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 585 | ui->buttonLStickMod->setText(ButtonToText(lstick_mod)); |
| 574 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | 586 | ui->buttonRStickMod->setText(ButtonToText(rstick_mod)); |
| 587 | |||
| 588 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | ||
| 589 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | ||
| 575 | auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; | 590 | auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; |
| 576 | 591 | ||
| 577 | if (analog_button == nullptr) { | 592 | if (analog_button == nullptr) { |
| @@ -581,99 +596,141 @@ void ConfigureInputPlayer::UpdateButtonLabels() { | |||
| 581 | analog_button->setText( | 596 | analog_button->setText( |
| 582 | AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); | 597 | AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); |
| 583 | } | 598 | } |
| 584 | analog_map_stick[analog_id]->setText(tr("Set Analog Stick")); | ||
| 585 | 599 | ||
| 600 | const auto deadzone_label = analog_map_deadzone_label[analog_id]; | ||
| 601 | const auto deadzone_slider = analog_map_deadzone_slider[analog_id]; | ||
| 602 | const auto modifier_groupbox = analog_map_modifier_groupbox[analog_id]; | ||
| 603 | const auto modifier_label = analog_map_modifier_label[analog_id]; | ||
| 604 | const auto modifier_slider = analog_map_modifier_slider[analog_id]; | ||
| 605 | const auto range_groupbox = analog_map_range_groupbox[analog_id]; | ||
| 606 | const auto range_spinbox = analog_map_range_spinbox[analog_id]; | ||
| 607 | |||
| 608 | int slider_value; | ||
| 586 | auto& param = analogs_param[analog_id]; | 609 | auto& param = analogs_param[analog_id]; |
| 587 | auto* const analog_stick_slider = analog_map_deadzone_and_modifier_slider[analog_id]; | 610 | const bool is_controller = |
| 588 | auto* const analog_stick_slider_label = | 611 | param.Get("engine", "") == "sdl" || param.Get("engine", "") == "gcpad"; |
| 589 | analog_map_deadzone_and_modifier_slider_label[analog_id]; | 612 | |
| 590 | 613 | if (is_controller) { | |
| 591 | if (param.Has("engine")) { | 614 | if (!param.Has("deadzone")) { |
| 592 | if (param.Get("engine", "") == "sdl" || param.Get("engine", "") == "gcpad") { | 615 | param.Set("deadzone", 0.1f); |
| 593 | if (!param.Has("deadzone")) { | ||
| 594 | param.Set("deadzone", 0.1f); | ||
| 595 | } | ||
| 596 | |||
| 597 | analog_stick_slider->setValue(static_cast<int>(param.Get("deadzone", 0.1f) * 100)); | ||
| 598 | if (analog_stick_slider->value() == 0) { | ||
| 599 | analog_stick_slider_label->setText(tr("Deadzone: 0%")); | ||
| 600 | } | ||
| 601 | } else { | ||
| 602 | if (!param.Has("modifier_scale")) { | ||
| 603 | param.Set("modifier_scale", 0.5f); | ||
| 604 | } | ||
| 605 | |||
| 606 | analog_stick_slider->setValue( | ||
| 607 | static_cast<int>(param.Get("modifier_scale", 0.5f) * 100)); | ||
| 608 | if (analog_stick_slider->value() == 0) { | ||
| 609 | analog_stick_slider_label->setText(tr("Modifier Scale: 0%")); | ||
| 610 | } | ||
| 611 | } | 616 | } |
| 617 | slider_value = static_cast<int>(param.Get("deadzone", 0.1f) * 100); | ||
| 618 | deadzone_label->setText(tr("Deadzone: %1%").arg(slider_value)); | ||
| 619 | deadzone_slider->setValue(slider_value); | ||
| 620 | if (!param.Has("range")) { | ||
| 621 | param.Set("range", 1.0f); | ||
| 622 | } | ||
| 623 | range_spinbox->setValue(static_cast<int>(param.Get("range", 1.0f) * 100)); | ||
| 624 | } else { | ||
| 625 | if (!param.Has("modifier_scale")) { | ||
| 626 | param.Set("modifier_scale", 0.5f); | ||
| 627 | } | ||
| 628 | slider_value = static_cast<int>(param.Get("modifier_scale", 0.5f) * 100); | ||
| 629 | modifier_label->setText(tr("Modifier Range: %1%").arg(slider_value)); | ||
| 630 | modifier_slider->setValue(slider_value); | ||
| 612 | } | 631 | } |
| 632 | |||
| 633 | deadzone_label->setVisible(is_controller); | ||
| 634 | deadzone_slider->setVisible(is_controller); | ||
| 635 | modifier_groupbox->setVisible(!is_controller); | ||
| 636 | modifier_label->setVisible(!is_controller); | ||
| 637 | modifier_slider->setVisible(!is_controller); | ||
| 638 | range_groupbox->setVisible(is_controller); | ||
| 613 | } | 639 | } |
| 614 | } | 640 | } |
| 615 | 641 | ||
| 642 | void ConfigureInputPlayer::UpdateMappingWithDefaults() { | ||
| 643 | if (ui->comboDevices->currentIndex() < 2) { | ||
| 644 | return; | ||
| 645 | } | ||
| 646 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; | ||
| 647 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); | ||
| 648 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); | ||
| 649 | for (int i = 0; i < buttons_param.size(); ++i) { | ||
| 650 | buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; | ||
| 651 | } | ||
| 652 | for (int i = 0; i < analogs_param.size(); ++i) { | ||
| 653 | analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; | ||
| 654 | } | ||
| 655 | |||
| 656 | UpdateUI(); | ||
| 657 | } | ||
| 658 | |||
| 616 | void ConfigureInputPlayer::HandleClick( | 659 | void ConfigureInputPlayer::HandleClick( |
| 617 | QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, | 660 | QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, |
| 618 | InputCommon::Polling::DeviceType type) { | 661 | InputCommon::Polling::DeviceType type) { |
| 619 | button->setText(tr("[press key]")); | 662 | button->setText(tr("[waiting]")); |
| 620 | button->setFocus(); | 663 | button->setFocus(); |
| 621 | 664 | ||
| 622 | // Keyboard keys can only be used as button devices | 665 | // The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a |
| 623 | want_keyboard_keys = type == InputCommon::Polling::DeviceType::Button; | 666 | // controller, then they don't want keyboard/mouse input |
| 624 | if (want_keyboard_keys) { | 667 | want_keyboard_mouse = ui->comboDevices->currentIndex() < 2; |
| 625 | const auto iter = std::find(button_map.begin(), button_map.end(), button); | ||
| 626 | ASSERT(iter != button_map.end()); | ||
| 627 | const auto index = std::distance(button_map.begin(), iter); | ||
| 628 | ASSERT(index < Settings::NativeButton::NumButtons && index >= 0); | ||
| 629 | } | ||
| 630 | 668 | ||
| 631 | input_setter = new_input_setter; | 669 | input_setter = new_input_setter; |
| 632 | 670 | ||
| 633 | device_pollers = InputCommon::Polling::GetPollers(type); | 671 | device_pollers = input_subsystem->GetPollers(type); |
| 634 | 672 | ||
| 635 | for (auto& poller : device_pollers) { | 673 | for (auto& poller : device_pollers) { |
| 636 | poller->Start(); | 674 | poller->Start(); |
| 637 | } | 675 | } |
| 638 | 676 | ||
| 639 | grabKeyboard(); | 677 | QWidget::grabMouse(); |
| 640 | grabMouse(); | 678 | QWidget::grabKeyboard(); |
| 679 | |||
| 641 | if (type == InputCommon::Polling::DeviceType::Button) { | 680 | if (type == InputCommon::Polling::DeviceType::Button) { |
| 642 | InputCommon::GetGCButtons()->BeginConfiguration(); | 681 | input_subsystem->GetGCButtons()->BeginConfiguration(); |
| 643 | } else { | 682 | } else { |
| 644 | InputCommon::GetGCAnalogs()->BeginConfiguration(); | 683 | input_subsystem->GetGCAnalogs()->BeginConfiguration(); |
| 645 | } | 684 | } |
| 646 | timeout_timer->start(5000); // Cancel after 5 seconds | 685 | |
| 647 | poll_timer->start(200); // Check for new inputs every 200ms | 686 | timeout_timer->start(2500); // Cancel after 2.5 seconds |
| 687 | poll_timer->start(50); // Check for new inputs every 50ms | ||
| 648 | } | 688 | } |
| 649 | 689 | ||
| 650 | void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { | 690 | void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { |
| 651 | releaseKeyboard(); | ||
| 652 | releaseMouse(); | ||
| 653 | timeout_timer->stop(); | 691 | timeout_timer->stop(); |
| 654 | poll_timer->stop(); | 692 | poll_timer->stop(); |
| 655 | for (auto& poller : device_pollers) { | 693 | for (auto& poller : device_pollers) { |
| 656 | poller->Stop(); | 694 | poller->Stop(); |
| 657 | } | 695 | } |
| 658 | 696 | ||
| 659 | InputCommon::GetGCButtons()->EndConfiguration(); | 697 | QWidget::releaseMouse(); |
| 660 | InputCommon::GetGCAnalogs()->EndConfiguration(); | 698 | QWidget::releaseKeyboard(); |
| 699 | |||
| 700 | input_subsystem->GetGCButtons()->EndConfiguration(); | ||
| 701 | input_subsystem->GetGCAnalogs()->EndConfiguration(); | ||
| 661 | 702 | ||
| 662 | if (!abort) { | 703 | if (!abort) { |
| 663 | (*input_setter)(params); | 704 | (*input_setter)(params); |
| 664 | } | 705 | } |
| 665 | 706 | ||
| 666 | UpdateButtonLabels(); | 707 | UpdateUI(); |
| 667 | input_setter = std::nullopt; | 708 | input_setter = std::nullopt; |
| 668 | } | 709 | } |
| 669 | 710 | ||
| 711 | void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { | ||
| 712 | if (!input_setter || !event) { | ||
| 713 | return; | ||
| 714 | } | ||
| 715 | |||
| 716 | if (want_keyboard_mouse) { | ||
| 717 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())}, | ||
| 718 | false); | ||
| 719 | } else { | ||
| 720 | // We don't want any mouse buttons, so don't stop polling | ||
| 721 | return; | ||
| 722 | } | ||
| 723 | |||
| 724 | SetPollingResult({}, true); | ||
| 725 | } | ||
| 726 | |||
| 670 | void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { | 727 | void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { |
| 671 | if (!input_setter || !event) { | 728 | if (!input_setter || !event) { |
| 672 | return; | 729 | return; |
| 673 | } | 730 | } |
| 674 | 731 | ||
| 675 | if (event->key() != Qt::Key_Escape) { | 732 | if (event->key() != Qt::Key_Escape) { |
| 676 | if (want_keyboard_keys) { | 733 | if (want_keyboard_mouse) { |
| 677 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, | 734 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, |
| 678 | false); | 735 | false); |
| 679 | } else { | 736 | } else { |
| @@ -681,5 +738,108 @@ void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { | |||
| 681 | return; | 738 | return; |
| 682 | } | 739 | } |
| 683 | } | 740 | } |
| 741 | |||
| 684 | SetPollingResult({}, true); | 742 | SetPollingResult({}, true); |
| 685 | } | 743 | } |
| 744 | |||
| 745 | void ConfigureInputPlayer::UpdateControllerIcon() { | ||
| 746 | // We aren't using Qt's built in theme support here since we aren't drawing an icon (and its | ||
| 747 | // "nonstandard" to use an image through the icon support) | ||
| 748 | const QString stylesheet = [this] { | ||
| 749 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | ||
| 750 | case Settings::ControllerType::ProController: | ||
| 751 | return QStringLiteral("image: url(:/controller/pro_controller%0)"); | ||
| 752 | case Settings::ControllerType::DualJoyconDetached: | ||
| 753 | return QStringLiteral("image: url(:/controller/dual_joycon%0)"); | ||
| 754 | case Settings::ControllerType::LeftJoycon: | ||
| 755 | return QStringLiteral("image: url(:/controller/single_joycon_left_vertical%0)"); | ||
| 756 | case Settings::ControllerType::RightJoycon: | ||
| 757 | return QStringLiteral("image: url(:/controller/single_joycon_right_vertical%0)"); | ||
| 758 | case Settings::ControllerType::Handheld: | ||
| 759 | return QStringLiteral("image: url(:/controller/handheld%0)"); | ||
| 760 | default: | ||
| 761 | return QString{}; | ||
| 762 | } | ||
| 763 | }(); | ||
| 764 | |||
| 765 | const QString theme = [this] { | ||
| 766 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { | ||
| 767 | return QStringLiteral("_dark"); | ||
| 768 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | ||
| 769 | return QStringLiteral("_midnight"); | ||
| 770 | } else { | ||
| 771 | return QString{}; | ||
| 772 | } | ||
| 773 | }(); | ||
| 774 | |||
| 775 | ui->controllerFrame->setStyleSheet(stylesheet.arg(theme)); | ||
| 776 | } | ||
| 777 | |||
| 778 | void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | ||
| 779 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); | ||
| 780 | if (debug) { | ||
| 781 | layout = Settings::ControllerType::ProController; | ||
| 782 | } | ||
| 783 | |||
| 784 | // List of all the widgets that will be hidden by any of the following layouts that need | ||
| 785 | // "unhidden" after the controller type changes | ||
| 786 | const std::array<QWidget*, 9> layout_show = { | ||
| 787 | ui->buttonShoulderButtonsSLSR, | ||
| 788 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 789 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 790 | ui->buttonShoulderButtonsLeft, | ||
| 791 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 792 | ui->bottomLeft, | ||
| 793 | ui->buttonShoulderButtonsRight, | ||
| 794 | ui->buttonMiscButtonsPlusHome, | ||
| 795 | ui->bottomRight, | ||
| 796 | }; | ||
| 797 | |||
| 798 | for (auto* widget : layout_show) { | ||
| 799 | widget->show(); | ||
| 800 | } | ||
| 801 | |||
| 802 | std::vector<QWidget*> layout_hidden; | ||
| 803 | switch (layout) { | ||
| 804 | case Settings::ControllerType::ProController: | ||
| 805 | case Settings::ControllerType::DualJoyconDetached: | ||
| 806 | case Settings::ControllerType::Handheld: | ||
| 807 | layout_hidden = { | ||
| 808 | ui->buttonShoulderButtonsSLSR, | ||
| 809 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 810 | }; | ||
| 811 | break; | ||
| 812 | case Settings::ControllerType::LeftJoycon: | ||
| 813 | layout_hidden = { | ||
| 814 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 815 | ui->buttonShoulderButtonsRight, | ||
| 816 | ui->buttonMiscButtonsPlusHome, | ||
| 817 | ui->bottomRight, | ||
| 818 | }; | ||
| 819 | break; | ||
| 820 | case Settings::ControllerType::RightJoycon: | ||
| 821 | layout_hidden = { | ||
| 822 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 823 | ui->buttonShoulderButtonsLeft, | ||
| 824 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 825 | ui->bottomLeft, | ||
| 826 | }; | ||
| 827 | break; | ||
| 828 | } | ||
| 829 | |||
| 830 | for (auto* widget : layout_hidden) { | ||
| 831 | widget->hide(); | ||
| 832 | } | ||
| 833 | } | ||
| 834 | |||
| 835 | void ConfigureInputPlayer::showEvent(QShowEvent* event) { | ||
| 836 | if (bottom_row == nullptr) { | ||
| 837 | return; | ||
| 838 | } | ||
| 839 | QWidget::showEvent(event); | ||
| 840 | ui->main->addWidget(bottom_row); | ||
| 841 | } | ||
| 842 | |||
| 843 | void ConfigureInputPlayer::ConnectPlayer(bool connected) { | ||
| 844 | ui->groupConnectedController->setChecked(connected); | ||
| 845 | } | ||
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index 95afa5375..a25bc3bd9 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h | |||
| @@ -10,16 +10,25 @@ | |||
| 10 | #include <optional> | 10 | #include <optional> |
| 11 | #include <string> | 11 | #include <string> |
| 12 | 12 | ||
| 13 | #include <QDialog> | 13 | #include <QWidget> |
| 14 | 14 | ||
| 15 | #include "common/param_package.h" | 15 | #include "common/param_package.h" |
| 16 | #include "core/settings.h" | 16 | #include "core/settings.h" |
| 17 | #include "ui_configure_input.h" | 17 | #include "ui_configure_input.h" |
| 18 | 18 | ||
| 19 | class QCheckBox; | ||
| 19 | class QKeyEvent; | 20 | class QKeyEvent; |
| 21 | class QLabel; | ||
| 20 | class QPushButton; | 22 | class QPushButton; |
| 23 | class QSlider; | ||
| 24 | class QSpinBox; | ||
| 21 | class QString; | 25 | class QString; |
| 22 | class QTimer; | 26 | class QTimer; |
| 27 | class QWidget; | ||
| 28 | |||
| 29 | namespace InputCommon { | ||
| 30 | class InputSubsystem; | ||
| 31 | } | ||
| 23 | 32 | ||
| 24 | namespace InputCommon::Polling { | 33 | namespace InputCommon::Polling { |
| 25 | class DevicePoller; | 34 | class DevicePoller; |
| @@ -30,77 +39,116 @@ namespace Ui { | |||
| 30 | class ConfigureInputPlayer; | 39 | class ConfigureInputPlayer; |
| 31 | } | 40 | } |
| 32 | 41 | ||
| 33 | class ConfigureInputPlayer : public QDialog { | 42 | class ConfigureInputPlayer : public QWidget { |
| 34 | Q_OBJECT | 43 | Q_OBJECT |
| 35 | 44 | ||
| 36 | public: | 45 | public: |
| 37 | explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, bool debug = false); | 46 | explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row, |
| 47 | InputCommon::InputSubsystem* input_subsystem_, | ||
| 48 | bool debug = false); | ||
| 38 | ~ConfigureInputPlayer() override; | 49 | ~ConfigureInputPlayer() override; |
| 39 | 50 | ||
| 40 | /// Save all button configurations to settings file | 51 | /// Save all button configurations to settings file. |
| 41 | void ApplyConfiguration(); | 52 | void ApplyConfiguration(); |
| 42 | 53 | ||
| 54 | /// Update the input devices combobox. | ||
| 55 | void UpdateInputDevices(); | ||
| 56 | |||
| 57 | /// Restore all buttons to their default values. | ||
| 58 | void RestoreDefaults(); | ||
| 59 | |||
| 60 | /// Clear all input configuration. | ||
| 61 | void ClearAll(); | ||
| 62 | |||
| 63 | /// Set the connection state checkbox (used to sync state). | ||
| 64 | void ConnectPlayer(bool connected); | ||
| 65 | |||
| 66 | signals: | ||
| 67 | /// Emitted when this controller is connected by the user. | ||
| 68 | void Connected(bool connected); | ||
| 69 | /// Emitted when the Handheld mode is selected (undocked with dual joycons attached). | ||
| 70 | void HandheldStateChanged(bool is_handheld); | ||
| 71 | /// Emitted when the input devices combobox is being refreshed. | ||
| 72 | void RefreshInputDevices(); | ||
| 73 | |||
| 74 | protected: | ||
| 75 | void showEvent(QShowEvent* event) override; | ||
| 76 | |||
| 43 | private: | 77 | private: |
| 44 | void changeEvent(QEvent* event) override; | 78 | void changeEvent(QEvent* event) override; |
| 45 | void RetranslateUI(); | 79 | void RetranslateUI(); |
| 46 | 80 | ||
| 47 | void OnControllerButtonClick(int i); | ||
| 48 | |||
| 49 | /// Load configuration settings. | 81 | /// Load configuration settings. |
| 50 | void LoadConfiguration(); | 82 | void LoadConfiguration(); |
| 51 | /// Restore all buttons to their default values. | ||
| 52 | void RestoreDefaults(); | ||
| 53 | /// Clear all input configuration | ||
| 54 | void ClearAll(); | ||
| 55 | |||
| 56 | /// Update UI to reflect current configuration. | ||
| 57 | void UpdateButtonLabels(); | ||
| 58 | 83 | ||
| 59 | /// Called when the button was pressed. | 84 | /// Called when the button was pressed. |
| 60 | void HandleClick(QPushButton* button, | 85 | void HandleClick(QPushButton* button, |
| 61 | std::function<void(const Common::ParamPackage&)> new_input_setter, | 86 | std::function<void(const Common::ParamPackage&)> new_input_setter, |
| 62 | InputCommon::Polling::DeviceType type); | 87 | InputCommon::Polling::DeviceType type); |
| 63 | 88 | ||
| 64 | /// Finish polling and configure input using the input_setter | 89 | /// Finish polling and configure input using the input_setter. |
| 65 | void SetPollingResult(const Common::ParamPackage& params, bool abort); | 90 | void SetPollingResult(const Common::ParamPackage& params, bool abort); |
| 66 | 91 | ||
| 92 | /// Handle mouse button press events. | ||
| 93 | void mousePressEvent(QMouseEvent* event) override; | ||
| 94 | |||
| 67 | /// Handle key press events. | 95 | /// Handle key press events. |
| 68 | void keyPressEvent(QKeyEvent* event) override; | 96 | void keyPressEvent(QKeyEvent* event) override; |
| 69 | 97 | ||
| 98 | /// Update UI to reflect current configuration. | ||
| 99 | void UpdateUI(); | ||
| 100 | |||
| 101 | /// Update the controller selection combobox | ||
| 102 | void UpdateControllerCombobox(); | ||
| 103 | |||
| 104 | /// Update the current controller icon. | ||
| 105 | void UpdateControllerIcon(); | ||
| 106 | |||
| 107 | /// Hides and disables controller settings based on the current controller type. | ||
| 108 | void UpdateControllerAvailableButtons(); | ||
| 109 | |||
| 110 | /// Gets the default controller mapping for this device and auto configures the input to match. | ||
| 111 | void UpdateMappingWithDefaults(); | ||
| 112 | |||
| 70 | std::unique_ptr<Ui::ConfigureInputPlayer> ui; | 113 | std::unique_ptr<Ui::ConfigureInputPlayer> ui; |
| 71 | 114 | ||
| 72 | std::size_t player_index; | 115 | std::size_t player_index; |
| 73 | bool debug; | 116 | bool debug; |
| 74 | 117 | ||
| 118 | InputCommon::InputSubsystem* input_subsystem; | ||
| 119 | |||
| 75 | std::unique_ptr<QTimer> timeout_timer; | 120 | std::unique_ptr<QTimer> timeout_timer; |
| 76 | std::unique_ptr<QTimer> poll_timer; | 121 | std::unique_ptr<QTimer> poll_timer; |
| 77 | 122 | ||
| 123 | static constexpr int PLAYER_COUNT = 8; | ||
| 124 | std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox; | ||
| 125 | |||
| 78 | /// This will be the the setting function when an input is awaiting configuration. | 126 | /// This will be the the setting function when an input is awaiting configuration. |
| 79 | std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; | 127 | std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; |
| 80 | 128 | ||
| 81 | std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param; | 129 | std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param; |
| 82 | std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param; | 130 | std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param; |
| 83 | 131 | ||
| 84 | static constexpr int ANALOG_SUB_BUTTONS_NUM = 5; | 132 | static constexpr int ANALOG_SUB_BUTTONS_NUM = 4; |
| 85 | 133 | ||
| 86 | /// Each button input is represented by a QPushButton. | 134 | /// Each button input is represented by a QPushButton. |
| 87 | std::array<QPushButton*, Settings::NativeButton::NumButtons> button_map; | 135 | std::array<QPushButton*, Settings::NativeButton::NumButtons> button_map; |
| 136 | /// Extra buttons for the modifiers. | ||
| 137 | Common::ParamPackage lstick_mod; | ||
| 138 | Common::ParamPackage rstick_mod; | ||
| 88 | 139 | ||
| 89 | std::vector<QWidget*> debug_hidden; | 140 | /// A group of four QPushButtons represent one analog input. The buttons each represent up, |
| 90 | std::vector<QWidget*> layout_hidden; | 141 | /// down, left, right, respectively. |
| 91 | |||
| 92 | /// A group of five QPushButtons represent one analog input. The buttons each represent up, | ||
| 93 | /// down, left, right, and modifier, respectively. | ||
| 94 | std::array<std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM>, Settings::NativeAnalog::NumAnalogs> | 142 | std::array<std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM>, Settings::NativeAnalog::NumAnalogs> |
| 95 | analog_map_buttons; | 143 | analog_map_buttons; |
| 96 | 144 | ||
| 97 | /// Analog inputs are also represented each with a single button, used to configure with an | 145 | std::array<QLabel*, Settings::NativeAnalog::NumAnalogs> analog_map_deadzone_label; |
| 98 | /// actual analog stick | 146 | std::array<QSlider*, Settings::NativeAnalog::NumAnalogs> analog_map_deadzone_slider; |
| 99 | std::array<QPushButton*, Settings::NativeAnalog::NumAnalogs> analog_map_stick; | 147 | std::array<QGroupBox*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_groupbox; |
| 100 | std::array<QSlider*, Settings::NativeAnalog::NumAnalogs> | 148 | std::array<QLabel*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_label; |
| 101 | analog_map_deadzone_and_modifier_slider; | 149 | std::array<QSlider*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_slider; |
| 102 | std::array<QLabel*, Settings::NativeAnalog::NumAnalogs> | 150 | std::array<QGroupBox*, Settings::NativeAnalog::NumAnalogs> analog_map_range_groupbox; |
| 103 | analog_map_deadzone_and_modifier_slider_label; | 151 | std::array<QSpinBox*, Settings::NativeAnalog::NumAnalogs> analog_map_range_spinbox; |
| 104 | 152 | ||
| 105 | static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons; | 153 | static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons; |
| 106 | 154 | ||
| @@ -108,8 +156,14 @@ private: | |||
| 108 | 156 | ||
| 109 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, | 157 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, |
| 110 | /// keyboard events are ignored. | 158 | /// keyboard events are ignored. |
| 111 | bool want_keyboard_keys = false; | 159 | bool want_keyboard_mouse = false; |
| 160 | |||
| 161 | /// List of physical devices users can map with. If a SDL backed device is selected, then you | ||
| 162 | /// can usue this device to get a default mapping. | ||
| 163 | std::vector<Common::ParamPackage> input_devices; | ||
| 112 | 164 | ||
| 113 | std::array<QPushButton*, 4> controller_color_buttons; | 165 | /// Bottom row is where console wide settings are held, and its "owned" by the parent |
| 114 | std::array<QColor, 4> controller_colors; | 166 | /// ConfigureInput widget. On show, add this widget to the main layout. This will change the |
| 167 | /// parent of the widget to this widget (but thats fine). | ||
| 168 | QWidget* bottom_row; | ||
| 115 | }; | 169 | }; |
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui index f27a77180..9bc681894 100644 --- a/src/yuzu/configuration/configure_input_player.ui +++ b/src/yuzu/configuration/configure_input_player.ui | |||
| @@ -1,1243 +1,2974 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
| 2 | <ui version="4.0"> | 2 | <ui version="4.0"> |
| 3 | <class>ConfigureInputPlayer</class> | 3 | <class>ConfigureInputPlayer</class> |
| 4 | <widget class="QDialog" name="ConfigureInputPlayer"> | 4 | <widget class="QWidget" name="ConfigureInputPlayer"> |
| 5 | <property name="geometry"> | 5 | <property name="geometry"> |
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>408</width> | 9 | <width>780</width> |
| 10 | <height>731</height> | 10 | <height>487</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Configure Input</string> | 14 | <string>Configure Input</string> |
| 15 | </property> | 15 | </property> |
| 16 | <layout class="QVBoxLayout" name="verticalLayout_5"> | 16 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 17 | <property name="spacing"> | ||
| 18 | <number>0</number> | ||
| 19 | </property> | ||
| 20 | <property name="leftMargin"> | ||
| 21 | <number>0</number> | ||
| 22 | </property> | ||
| 23 | <property name="topMargin"> | ||
| 24 | <number>0</number> | ||
| 25 | </property> | ||
| 26 | <property name="rightMargin"> | ||
| 27 | <number>0</number> | ||
| 28 | </property> | ||
| 29 | <property name="bottomMargin"> | ||
| 30 | <number>0</number> | ||
| 31 | </property> | ||
| 17 | <item> | 32 | <item> |
| 18 | <layout class="QGridLayout" name="buttons"> | 33 | <layout class="QVBoxLayout" name="main"> |
| 19 | <item row="1" column="1"> | 34 | <property name="spacing"> |
| 20 | <widget class="QGroupBox" name="RStick"> | 35 | <number>0</number> |
| 21 | <property name="title"> | 36 | </property> |
| 22 | <string>Right Stick</string> | 37 | <property name="leftMargin"> |
| 23 | </property> | 38 | <number>0</number> |
| 24 | <property name="alignment"> | 39 | </property> |
| 25 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> | 40 | <property name="topMargin"> |
| 26 | </property> | 41 | <number>0</number> |
| 27 | <property name="flat"> | 42 | </property> |
| 28 | <bool>false</bool> | 43 | <property name="rightMargin"> |
| 44 | <number>0</number> | ||
| 45 | </property> | ||
| 46 | <property name="bottomMargin"> | ||
| 47 | <number>0</number> | ||
| 48 | </property> | ||
| 49 | <item> | ||
| 50 | <layout class="QHBoxLayout" name="top" stretch="0,1,2"> | ||
| 51 | <property name="spacing"> | ||
| 52 | <number>3</number> | ||
| 29 | </property> | 53 | </property> |
| 30 | <property name="checkable"> | 54 | <property name="topMargin"> |
| 31 | <bool>false</bool> | 55 | <number>0</number> |
| 32 | </property> | 56 | </property> |
| 33 | <layout class="QGridLayout" name="gridLayout_5"> | 57 | <item> |
| 34 | <item row="1" column="1"> | 58 | <widget class="QGroupBox" name="groupConnectedController"> |
| 35 | <layout class="QVBoxLayout" name="buttonRStickDownVerticalLayout"> | 59 | <property name="layoutDirection"> |
| 60 | <enum>Qt::LeftToRight</enum> | ||
| 61 | </property> | ||
| 62 | <property name="title"> | ||
| 63 | <string>Connect Controller</string> | ||
| 64 | </property> | ||
| 65 | <property name="flat"> | ||
| 66 | <bool>false</bool> | ||
| 67 | </property> | ||
| 68 | <property name="checkable"> | ||
| 69 | <bool>true</bool> | ||
| 70 | </property> | ||
| 71 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||
| 72 | <property name="leftMargin"> | ||
| 73 | <number>5</number> | ||
| 74 | </property> | ||
| 75 | <property name="topMargin"> | ||
| 76 | <number>5</number> | ||
| 77 | </property> | ||
| 78 | <property name="rightMargin"> | ||
| 79 | <number>5</number> | ||
| 80 | </property> | ||
| 81 | <property name="bottomMargin"> | ||
| 82 | <number>5</number> | ||
| 83 | </property> | ||
| 36 | <item> | 84 | <item> |
| 37 | <layout class="QHBoxLayout" name="buttonRStickDownHorizontalLayout"> | 85 | <widget class="QComboBox" name="comboControllerType"> |
| 38 | <item> | 86 | <item> |
| 39 | <widget class="QLabel" name="labelRStickDown"> | 87 | <property name="text"> |
| 40 | <property name="text"> | 88 | <string>Pro Controller</string> |
| 41 | <string>Down:</string> | 89 | </property> |
| 42 | </property> | ||
| 43 | </widget> | ||
| 44 | </item> | 90 | </item> |
| 45 | </layout> | ||
| 46 | </item> | ||
| 47 | <item> | ||
| 48 | <widget class="QPushButton" name="buttonRStickDown"> | ||
| 49 | <property name="text"> | ||
| 50 | <string/> | ||
| 51 | </property> | ||
| 52 | </widget> | ||
| 53 | </item> | ||
| 54 | </layout> | ||
| 55 | </item> | ||
| 56 | <item row="0" column="1"> | ||
| 57 | <layout class="QVBoxLayout" name="buttonRStickRightVerticalLayout"> | ||
| 58 | <item> | ||
| 59 | <layout class="QHBoxLayout" name="buttonRStickRightHorizontalLayout"> | ||
| 60 | <item> | 91 | <item> |
| 61 | <widget class="QLabel" name="labelRStickRight"> | 92 | <property name="text"> |
| 62 | <property name="text"> | 93 | <string>Dual Joycons</string> |
| 63 | <string>Right:</string> | 94 | </property> |
| 64 | </property> | ||
| 65 | </widget> | ||
| 66 | </item> | 95 | </item> |
| 67 | </layout> | ||
| 68 | </item> | ||
| 69 | <item> | ||
| 70 | <widget class="QPushButton" name="buttonRStickRight"> | ||
| 71 | <property name="text"> | ||
| 72 | <string/> | ||
| 73 | </property> | ||
| 74 | </widget> | ||
| 75 | </item> | ||
| 76 | </layout> | ||
| 77 | </item> | ||
| 78 | <item row="3" column="0" colspan="2"> | ||
| 79 | <widget class="QPushButton" name="buttonRStickAnalog"> | ||
| 80 | <property name="text"> | ||
| 81 | <string>Set Analog Stick</string> | ||
| 82 | </property> | ||
| 83 | </widget> | ||
| 84 | </item> | ||
| 85 | <item row="0" column="0"> | ||
| 86 | <layout class="QVBoxLayout" name="buttonRStickLeftVerticalLayout"> | ||
| 87 | <item> | ||
| 88 | <layout class="QHBoxLayout" name="buttonRStickLeftHorizontalLayout"> | ||
| 89 | <item> | 96 | <item> |
| 90 | <widget class="QLabel" name="labelRStickLeft"> | 97 | <property name="text"> |
| 91 | <property name="text"> | 98 | <string>Left Joycon</string> |
| 92 | <string>Left:</string> | 99 | </property> |
| 93 | </property> | ||
| 94 | </widget> | ||
| 95 | </item> | 100 | </item> |
| 96 | </layout> | ||
| 97 | </item> | ||
| 98 | <item> | ||
| 99 | <widget class="QPushButton" name="buttonRStickLeft"> | ||
| 100 | <property name="text"> | ||
| 101 | <string/> | ||
| 102 | </property> | ||
| 103 | </widget> | ||
| 104 | </item> | ||
| 105 | </layout> | ||
| 106 | </item> | ||
| 107 | <item row="1" column="0"> | ||
| 108 | <layout class="QVBoxLayout" name="buttonRStickUpVerticalLayout"> | ||
| 109 | <item> | ||
| 110 | <layout class="QHBoxLayout" name="buttonRStickUpHorizontalLayout"> | ||
| 111 | <item> | 101 | <item> |
| 112 | <widget class="QLabel" name="labelRStickUp"> | 102 | <property name="text"> |
| 113 | <property name="text"> | 103 | <string>Right Joycon</string> |
| 114 | <string>Up:</string> | 104 | </property> |
| 115 | </property> | ||
| 116 | </widget> | ||
| 117 | </item> | 105 | </item> |
| 118 | </layout> | ||
| 119 | </item> | ||
| 120 | <item> | ||
| 121 | <widget class="QPushButton" name="buttonRStickUp"> | ||
| 122 | <property name="text"> | ||
| 123 | <string/> | ||
| 124 | </property> | ||
| 125 | </widget> | ||
| 126 | </item> | ||
| 127 | </layout> | ||
| 128 | </item> | ||
| 129 | <item row="2" column="0"> | ||
| 130 | <layout class="QVBoxLayout" name="buttonRStickPressedVerticalLayout"> | ||
| 131 | <item> | ||
| 132 | <layout class="QHBoxLayout" name="buttonRStickPressedHorizontalLayout"> | ||
| 133 | <item> | 106 | <item> |
| 134 | <widget class="QLabel" name="labelRStickPressed"> | 107 | <property name="text"> |
| 135 | <property name="text"> | 108 | <string>Handheld</string> |
| 136 | <string>Pressed:</string> | 109 | </property> |
| 137 | </property> | ||
| 138 | </widget> | ||
| 139 | </item> | 110 | </item> |
| 140 | </layout> | ||
| 141 | </item> | ||
| 142 | <item> | ||
| 143 | <widget class="QPushButton" name="buttonRStick"> | ||
| 144 | <property name="text"> | ||
| 145 | <string/> | ||
| 146 | </property> | ||
| 147 | </widget> | 111 | </widget> |
| 148 | </item> | 112 | </item> |
| 149 | </layout> | 113 | </layout> |
| 150 | </item> | 114 | </widget> |
| 151 | <item row="2" column="1"> | 115 | </item> |
| 152 | <layout class="QVBoxLayout" name="buttonRStickModVerticalLayout"> | 116 | <item> |
| 117 | <widget class="QGroupBox" name="devicesGroup"> | ||
| 118 | <property name="title"> | ||
| 119 | <string>Input Device</string> | ||
| 120 | </property> | ||
| 121 | <layout class="QHBoxLayout" name="horizontalLayout_5"> | ||
| 122 | <property name="spacing"> | ||
| 123 | <number>3</number> | ||
| 124 | </property> | ||
| 125 | <property name="leftMargin"> | ||
| 126 | <number>5</number> | ||
| 127 | </property> | ||
| 128 | <property name="topMargin"> | ||
| 129 | <number>5</number> | ||
| 130 | </property> | ||
| 131 | <property name="rightMargin"> | ||
| 132 | <number>5</number> | ||
| 133 | </property> | ||
| 134 | <property name="bottomMargin"> | ||
| 135 | <number>5</number> | ||
| 136 | </property> | ||
| 153 | <item> | 137 | <item> |
| 154 | <layout class="QHBoxLayout" name="buttonRStickModHorizontalLayout"> | 138 | <widget class="QComboBox" name="comboDevices"> |
| 155 | <item> | 139 | <item> |
| 156 | <widget class="QLabel" name="labelRStickMod"> | 140 | <property name="text"> |
| 157 | <property name="text"> | 141 | <string>Any</string> |
| 158 | <string>Modifier:</string> | 142 | </property> |
| 159 | </property> | ||
| 160 | </widget> | ||
| 161 | </item> | 143 | </item> |
| 162 | </layout> | ||
| 163 | </item> | ||
| 164 | <item> | ||
| 165 | <widget class="QPushButton" name="buttonRStickMod"> | ||
| 166 | <property name="text"> | ||
| 167 | <string/> | ||
| 168 | </property> | ||
| 169 | </widget> | ||
| 170 | </item> | ||
| 171 | </layout> | ||
| 172 | </item> | ||
| 173 | <item row="4" column="0" colspan="2"> | ||
| 174 | <layout class="QVBoxLayout" name="sliderRStickDeadzoneAndModifierVerticalLayout"> | ||
| 175 | <item> | ||
| 176 | <layout class="QHBoxLayout" name="sliderRStickDeadzoneAndModifierHorizontalLayout"> | ||
| 177 | <item> | 144 | <item> |
| 178 | <widget class="QLabel" name="labelRStickDeadzoneAndModifier"> | 145 | <property name="text"> |
| 179 | <property name="text"> | 146 | <string>Keyboard/Mouse</string> |
| 180 | <string>Deadzone: 0</string> | 147 | </property> |
| 181 | </property> | ||
| 182 | <property name="alignment"> | ||
| 183 | <enum>Qt::AlignHCenter</enum> | ||
| 184 | </property> | ||
| 185 | </widget> | ||
| 186 | </item> | 148 | </item> |
| 187 | </layout> | 149 | </widget> |
| 188 | </item> | 150 | </item> |
| 189 | <item> | 151 | <item> |
| 190 | <widget class="QSlider" name="sliderRStickDeadzoneAndModifier"> | 152 | <widget class="QPushButton" name="buttonRefreshDevices"> |
| 191 | <property name="orientation"> | 153 | <property name="minimumSize"> |
| 192 | <enum>Qt::Horizontal</enum> | 154 | <size> |
| 155 | <width>24</width> | ||
| 156 | <height>22</height> | ||
| 157 | </size> | ||
| 158 | </property> | ||
| 159 | <property name="maximumSize"> | ||
| 160 | <size> | ||
| 161 | <width>24</width> | ||
| 162 | <height>22</height> | ||
| 163 | </size> | ||
| 164 | </property> | ||
| 165 | <property name="styleSheet"> | ||
| 166 | <string notr="true"/> | ||
| 193 | </property> | 167 | </property> |
| 194 | </widget> | 168 | </widget> |
| 195 | </item> | 169 | </item> |
| 196 | </layout> | 170 | </layout> |
| 197 | </item> | 171 | </widget> |
| 198 | <item row="5" column="0"> | 172 | </item> |
| 199 | <spacer name="RStick_verticalSpacer"> | 173 | <item> |
| 200 | <property name="orientation"> | 174 | <widget class="QGroupBox" name="profilesGroup"> |
| 201 | <enum>Qt::Vertical</enum> | 175 | <property name="minimumSize"> |
| 176 | <size> | ||
| 177 | <width>0</width> | ||
| 178 | <height>0</height> | ||
| 179 | </size> | ||
| 180 | </property> | ||
| 181 | <property name="title"> | ||
| 182 | <string>Profile</string> | ||
| 183 | </property> | ||
| 184 | <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="2,0,0,0"> | ||
| 185 | <property name="spacing"> | ||
| 186 | <number>3</number> | ||
| 202 | </property> | 187 | </property> |
| 203 | <property name="sizeHint" stdset="0"> | 188 | <property name="leftMargin"> |
| 204 | <size> | 189 | <number>5</number> |
| 205 | <width>0</width> | 190 | </property> |
| 206 | <height>0</height> | 191 | <property name="topMargin"> |
| 207 | </size> | 192 | <number>5</number> |
| 193 | </property> | ||
| 194 | <property name="rightMargin"> | ||
| 195 | <number>5</number> | ||
| 196 | </property> | ||
| 197 | <property name="bottomMargin"> | ||
| 198 | <number>5</number> | ||
| 208 | </property> | 199 | </property> |
| 209 | </spacer> | ||
| 210 | </item> | ||
| 211 | </layout> | ||
| 212 | </widget> | ||
| 213 | </item> | ||
| 214 | <item row="0" column="1"> | ||
| 215 | <widget class="QGroupBox" name="Dpad"> | ||
| 216 | <property name="title"> | ||
| 217 | <string>Directional Pad</string> | ||
| 218 | </property> | ||
| 219 | <property name="flat"> | ||
| 220 | <bool>false</bool> | ||
| 221 | </property> | ||
| 222 | <property name="checkable"> | ||
| 223 | <bool>false</bool> | ||
| 224 | </property> | ||
| 225 | <layout class="QGridLayout" name="gridLayout_2"> | ||
| 226 | <item row="1" column="0"> | ||
| 227 | <layout class="QVBoxLayout" name="buttonDpadUpVerticalLayout"> | ||
| 228 | <item> | 200 | <item> |
| 229 | <layout class="QHBoxLayout" name="buttonDpadUpHorizontalLayout"> | 201 | <widget class="QComboBox" name="comboProfiles"/> |
| 230 | <item> | ||
| 231 | <widget class="QLabel" name="labelDpadUp"> | ||
| 232 | <property name="text"> | ||
| 233 | <string>Up:</string> | ||
| 234 | </property> | ||
| 235 | </widget> | ||
| 236 | </item> | ||
| 237 | </layout> | ||
| 238 | </item> | 202 | </item> |
| 239 | <item> | 203 | <item> |
| 240 | <widget class="QPushButton" name="buttonDpadUp"> | 204 | <widget class="QPushButton" name="buttonProfilesSave"> |
| 241 | <property name="text"> | 205 | <property name="maximumSize"> |
| 242 | <string/> | 206 | <size> |
| 207 | <width>55</width> | ||
| 208 | <height>16777215</height> | ||
| 209 | </size> | ||
| 210 | </property> | ||
| 211 | <property name="styleSheet"> | ||
| 212 | <string notr="true">min-width: 55px;</string> | ||
| 243 | </property> | 213 | </property> |
| 244 | </widget> | ||
| 245 | </item> | ||
| 246 | </layout> | ||
| 247 | </item> | ||
| 248 | <item row="1" column="1"> | ||
| 249 | <layout class="QVBoxLayout" name="buttonDpadDownVerticalLayout"> | ||
| 250 | <item> | ||
| 251 | <layout class="QHBoxLayout" name="buttonDpadDownHorizontalLayout"> | ||
| 252 | <item> | ||
| 253 | <widget class="QLabel" name="labelDpadDown"> | ||
| 254 | <property name="text"> | ||
| 255 | <string>Down:</string> | ||
| 256 | </property> | ||
| 257 | </widget> | ||
| 258 | </item> | ||
| 259 | </layout> | ||
| 260 | </item> | ||
| 261 | <item> | ||
| 262 | <widget class="QPushButton" name="buttonDpadDown"> | ||
| 263 | <property name="text"> | 214 | <property name="text"> |
| 264 | <string/> | 215 | <string>Save</string> |
| 265 | </property> | 216 | </property> |
| 266 | </widget> | 217 | </widget> |
| 267 | </item> | 218 | </item> |
| 268 | </layout> | ||
| 269 | </item> | ||
| 270 | <item row="0" column="0"> | ||
| 271 | <layout class="QVBoxLayout" name="buttonDpadLeftVerticalLayout"> | ||
| 272 | <item> | ||
| 273 | <layout class="QHBoxLayout" name="buttonDpadLeftHorizontalLayout"> | ||
| 274 | <item> | ||
| 275 | <widget class="QLabel" name="labelDpadLeft"> | ||
| 276 | <property name="minimumSize"> | ||
| 277 | <size> | ||
| 278 | <width>80</width> | ||
| 279 | <height>0</height> | ||
| 280 | </size> | ||
| 281 | </property> | ||
| 282 | <property name="text"> | ||
| 283 | <string>Left:</string> | ||
| 284 | </property> | ||
| 285 | </widget> | ||
| 286 | </item> | ||
| 287 | </layout> | ||
| 288 | </item> | ||
| 289 | <item> | 219 | <item> |
| 290 | <widget class="QPushButton" name="buttonDpadLeft"> | 220 | <widget class="QPushButton" name="buttonProfilesNew"> |
| 221 | <property name="maximumSize"> | ||
| 222 | <size> | ||
| 223 | <width>55</width> | ||
| 224 | <height>16777215</height> | ||
| 225 | </size> | ||
| 226 | </property> | ||
| 227 | <property name="styleSheet"> | ||
| 228 | <string notr="true">min-width: 55px;</string> | ||
| 229 | </property> | ||
| 291 | <property name="text"> | 230 | <property name="text"> |
| 292 | <string/> | 231 | <string>New</string> |
| 293 | </property> | 232 | </property> |
| 294 | </widget> | 233 | </widget> |
| 295 | </item> | 234 | </item> |
| 296 | </layout> | ||
| 297 | </item> | ||
| 298 | <item row="0" column="1"> | ||
| 299 | <layout class="QVBoxLayout" name="buttonDpadRightVerticalLayout"> | ||
| 300 | <item> | ||
| 301 | <layout class="QHBoxLayout" name="buttonDpadRightHorizontalLayout"> | ||
| 302 | <item> | ||
| 303 | <widget class="QLabel" name="labelDpadRight"> | ||
| 304 | <property name="minimumSize"> | ||
| 305 | <size> | ||
| 306 | <width>80</width> | ||
| 307 | <height>0</height> | ||
| 308 | </size> | ||
| 309 | </property> | ||
| 310 | <property name="text"> | ||
| 311 | <string>Right:</string> | ||
| 312 | </property> | ||
| 313 | </widget> | ||
| 314 | </item> | ||
| 315 | </layout> | ||
| 316 | </item> | ||
| 317 | <item> | 235 | <item> |
| 318 | <widget class="QPushButton" name="buttonDpadRight"> | 236 | <widget class="QPushButton" name="buttonProfilesDelete"> |
| 237 | <property name="maximumSize"> | ||
| 238 | <size> | ||
| 239 | <width>55</width> | ||
| 240 | <height>16777215</height> | ||
| 241 | </size> | ||
| 242 | </property> | ||
| 243 | <property name="styleSheet"> | ||
| 244 | <string notr="true">min-width: 55px;</string> | ||
| 245 | </property> | ||
| 319 | <property name="text"> | 246 | <property name="text"> |
| 320 | <string/> | 247 | <string>Delete</string> |
| 321 | </property> | 248 | </property> |
| 322 | </widget> | 249 | </widget> |
| 323 | </item> | 250 | </item> |
| 324 | </layout> | 251 | </layout> |
| 325 | </item> | 252 | </widget> |
| 326 | </layout> | 253 | </item> |
| 327 | </widget> | 254 | </layout> |
| 328 | </item> | 255 | </item> |
| 329 | <item row="0" column="0"> | 256 | <item> |
| 330 | <widget class="QGroupBox" name="faceButtons"> | 257 | <widget class="QFrame" name="bottom"> |
| 331 | <property name="title"> | 258 | <property name="sizePolicy"> |
| 332 | <string>Face Buttons</string> | 259 | <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> |
| 333 | </property> | 260 | <horstretch>0</horstretch> |
| 334 | <property name="flat"> | 261 | <verstretch>0</verstretch> |
| 335 | <bool>false</bool> | 262 | </sizepolicy> |
| 336 | </property> | ||
| 337 | <property name="checkable"> | ||
| 338 | <bool>false</bool> | ||
| 339 | </property> | 263 | </property> |
| 340 | <layout class="QGridLayout" name="gridLayout"> | 264 | <layout class="QHBoxLayout" name="_2"> |
| 341 | <item row="0" column="0"> | 265 | <property name="sizeConstraint"> |
| 342 | <layout class="QVBoxLayout" name="buttonFaceButtonsAVerticalLayout"> | 266 | <enum>QLayout::SetMinimumSize</enum> |
| 343 | <item> | 267 | </property> |
| 344 | <layout class="QHBoxLayout" name="buttonFaceButtonsAHorizontalLayout"> | 268 | <property name="leftMargin"> |
| 345 | <item> | 269 | <number>0</number> |
| 346 | <widget class="QLabel" name="labelA"> | 270 | </property> |
| 347 | <property name="minimumSize"> | 271 | <property name="topMargin"> |
| 348 | <size> | 272 | <number>0</number> |
| 349 | <width>80</width> | 273 | </property> |
| 350 | <height>0</height> | 274 | <property name="rightMargin"> |
| 351 | </size> | 275 | <number>0</number> |
| 276 | </property> | ||
| 277 | <property name="bottomMargin"> | ||
| 278 | <number>0</number> | ||
| 279 | </property> | ||
| 280 | <item> | ||
| 281 | <widget class="QWidget" name="bottomLeft" native="true"> | ||
| 282 | <layout class="QVBoxLayout" name="bottomLeftLayout" stretch="0,0,0,0"> | ||
| 283 | <property name="spacing"> | ||
| 284 | <number>0</number> | ||
| 285 | </property> | ||
| 286 | <property name="sizeConstraint"> | ||
| 287 | <enum>QLayout::SetDefaultConstraint</enum> | ||
| 288 | </property> | ||
| 289 | <property name="leftMargin"> | ||
| 290 | <number>0</number> | ||
| 291 | </property> | ||
| 292 | <property name="topMargin"> | ||
| 293 | <number>0</number> | ||
| 294 | </property> | ||
| 295 | <property name="rightMargin"> | ||
| 296 | <number>0</number> | ||
| 297 | </property> | ||
| 298 | <property name="bottomMargin"> | ||
| 299 | <number>0</number> | ||
| 300 | </property> | ||
| 301 | <item> | ||
| 302 | <widget class="QGroupBox" name="LStick"> | ||
| 303 | <property name="sizePolicy"> | ||
| 304 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 305 | <horstretch>0</horstretch> | ||
| 306 | <verstretch>0</verstretch> | ||
| 307 | </sizepolicy> | ||
| 308 | </property> | ||
| 309 | <property name="title"> | ||
| 310 | <string>Left Stick</string> | ||
| 311 | </property> | ||
| 312 | <property name="alignment"> | ||
| 313 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> | ||
| 314 | </property> | ||
| 315 | <layout class="QVBoxLayout" name="verticalLayout_3"> | ||
| 316 | <property name="spacing"> | ||
| 317 | <number>0</number> | ||
| 352 | </property> | 318 | </property> |
| 353 | <property name="text"> | 319 | <property name="sizeConstraint"> |
| 354 | <string>A:</string> | 320 | <enum>QLayout::SetDefaultConstraint</enum> |
| 355 | </property> | 321 | </property> |
| 356 | </widget> | 322 | <property name="leftMargin"> |
| 357 | </item> | 323 | <number>3</number> |
| 358 | </layout> | ||
| 359 | </item> | ||
| 360 | <item> | ||
| 361 | <widget class="QPushButton" name="buttonA"> | ||
| 362 | <property name="text"> | ||
| 363 | <string/> | ||
| 364 | </property> | ||
| 365 | </widget> | ||
| 366 | </item> | ||
| 367 | </layout> | ||
| 368 | </item> | ||
| 369 | <item row="0" column="1"> | ||
| 370 | <layout class="QVBoxLayout" name="buttonFaceButtonsBVerticalLayout"> | ||
| 371 | <item> | ||
| 372 | <layout class="QHBoxLayout" name="buttonFaceButtonsBHorizontalLayout"> | ||
| 373 | <item> | ||
| 374 | <widget class="QLabel" name="labelB"> | ||
| 375 | <property name="minimumSize"> | ||
| 376 | <size> | ||
| 377 | <width>80</width> | ||
| 378 | <height>0</height> | ||
| 379 | </size> | ||
| 380 | </property> | 324 | </property> |
| 381 | <property name="text"> | 325 | <property name="topMargin"> |
| 382 | <string>B:</string> | 326 | <number>0</number> |
| 383 | </property> | 327 | </property> |
| 384 | </widget> | 328 | <property name="rightMargin"> |
| 385 | </item> | 329 | <number>3</number> |
| 386 | </layout> | ||
| 387 | </item> | ||
| 388 | <item> | ||
| 389 | <widget class="QPushButton" name="buttonB"> | ||
| 390 | <property name="text"> | ||
| 391 | <string/> | ||
| 392 | </property> | ||
| 393 | </widget> | ||
| 394 | </item> | ||
| 395 | </layout> | ||
| 396 | </item> | ||
| 397 | <item row="1" column="0"> | ||
| 398 | <layout class="QVBoxLayout" name="buttonFaceButtonsXVerticalLayout"> | ||
| 399 | <item> | ||
| 400 | <layout class="QHBoxLayout" name="buttonFaceButtonsXHorizontalLayout"> | ||
| 401 | <item> | ||
| 402 | <widget class="QLabel" name="labelX"> | ||
| 403 | <property name="text"> | ||
| 404 | <string>X:</string> | ||
| 405 | </property> | 330 | </property> |
| 406 | </widget> | 331 | <property name="bottomMargin"> |
| 407 | </item> | 332 | <number>0</number> |
| 408 | </layout> | ||
| 409 | </item> | ||
| 410 | <item> | ||
| 411 | <widget class="QPushButton" name="buttonX"> | ||
| 412 | <property name="text"> | ||
| 413 | <string/> | ||
| 414 | </property> | ||
| 415 | </widget> | ||
| 416 | </item> | ||
| 417 | </layout> | ||
| 418 | </item> | ||
| 419 | <item row="1" column="1"> | ||
| 420 | <layout class="QVBoxLayout" name="buttonFaceButtonsYVerticalLayout"> | ||
| 421 | <item> | ||
| 422 | <layout class="QHBoxLayout" name="buttonFaceButtonsYHorizontalLayout"> | ||
| 423 | <item> | ||
| 424 | <widget class="QLabel" name="labelY"> | ||
| 425 | <property name="text"> | ||
| 426 | <string>Y:</string> | ||
| 427 | </property> | 333 | </property> |
| 428 | </widget> | 334 | <item> |
| 429 | </item> | 335 | <widget class="QWidget" name="buttonLStickUpWidget" native="true"> |
| 430 | </layout> | 336 | <layout class="QHBoxLayout" name="horizontalLayout_20"> |
| 431 | </item> | 337 | <property name="spacing"> |
| 432 | <item> | 338 | <number>0</number> |
| 433 | <widget class="QPushButton" name="buttonY"> | 339 | </property> |
| 434 | <property name="text"> | 340 | <property name="leftMargin"> |
| 435 | <string/> | 341 | <number>0</number> |
| 436 | </property> | 342 | </property> |
| 437 | </widget> | 343 | <property name="topMargin"> |
| 438 | </item> | 344 | <number>0</number> |
| 439 | </layout> | 345 | </property> |
| 440 | </item> | 346 | <property name="rightMargin"> |
| 441 | </layout> | 347 | <number>0</number> |
| 442 | </widget> | 348 | </property> |
| 443 | </item> | 349 | <property name="bottomMargin"> |
| 444 | <item row="5" column="0" colspan="2"> | 350 | <number>0</number> |
| 445 | <widget class="QGroupBox" name="controller_color"> | 351 | </property> |
| 446 | <property name="title"> | 352 | <item> |
| 447 | <string>Controller Color</string> | 353 | <spacer name="horizontalSpacerLStickUpLeft"> |
| 448 | </property> | 354 | <property name="orientation"> |
| 449 | <layout class="QGridLayout" name="gridLayout_10" columnstretch="0,0,0,0,0,0,0"> | 355 | <enum>Qt::Horizontal</enum> |
| 450 | <item row="0" column="0"> | 356 | </property> |
| 451 | <spacer name="horizontalSpacer_2"> | 357 | <property name="sizeHint" stdset="0"> |
| 452 | <property name="orientation"> | 358 | <size> |
| 453 | <enum>Qt::Horizontal</enum> | 359 | <width>20</width> |
| 454 | </property> | 360 | <height>20</height> |
| 455 | <property name="sizeHint" stdset="0"> | 361 | </size> |
| 456 | <size> | 362 | </property> |
| 457 | <width>40</width> | 363 | </spacer> |
| 458 | <height>20</height> | 364 | </item> |
| 459 | </size> | 365 | <item alignment="Qt::AlignHCenter"> |
| 460 | </property> | 366 | <widget class="QGroupBox" name="buttonLStickUpGroup"> |
| 461 | </spacer> | 367 | <property name="title"> |
| 462 | </item> | 368 | <string>Up</string> |
| 463 | <item row="0" column="1"> | 369 | </property> |
| 464 | <widget class="QLabel" name="left_body_label"> | 370 | <property name="alignment"> |
| 465 | <property name="text"> | 371 | <set>Qt::AlignCenter</set> |
| 466 | <string>Left Body</string> | 372 | </property> |
| 467 | </property> | 373 | <property name="flat"> |
| 468 | </widget> | 374 | <bool>false</bool> |
| 469 | </item> | 375 | </property> |
| 470 | <item row="0" column="6"> | 376 | <layout class="QVBoxLayout" name="buttonLStickUpVerticalLayout"> |
| 471 | <spacer name="horizontalSpacer_3"> | 377 | <property name="spacing"> |
| 472 | <property name="orientation"> | 378 | <number>3</number> |
| 473 | <enum>Qt::Horizontal</enum> | 379 | </property> |
| 474 | </property> | 380 | <property name="leftMargin"> |
| 475 | <property name="sizeHint" stdset="0"> | 381 | <number>3</number> |
| 476 | <size> | 382 | </property> |
| 477 | <width>40</width> | 383 | <property name="topMargin"> |
| 478 | <height>20</height> | 384 | <number>3</number> |
| 479 | </size> | 385 | </property> |
| 480 | </property> | 386 | <property name="rightMargin"> |
| 481 | </spacer> | 387 | <number>3</number> |
| 482 | </item> | 388 | </property> |
| 483 | <item row="1" column="1"> | 389 | <property name="bottomMargin"> |
| 484 | <widget class="QLabel" name="left_buttons_label"> | 390 | <number>3</number> |
| 485 | <property name="minimumSize"> | 391 | </property> |
| 486 | <size> | 392 | <item> |
| 487 | <width>90</width> | 393 | <widget class="QPushButton" name="buttonLStickUp"> |
| 488 | <height>0</height> | 394 | <property name="minimumSize"> |
| 489 | </size> | 395 | <size> |
| 490 | </property> | 396 | <width>57</width> |
| 491 | <property name="text"> | 397 | <height>0</height> |
| 492 | <string>Left Buttons</string> | 398 | </size> |
| 493 | </property> | 399 | </property> |
| 494 | </widget> | 400 | <property name="maximumSize"> |
| 495 | </item> | 401 | <size> |
| 496 | <item row="1" column="5"> | 402 | <width>55</width> |
| 497 | <widget class="QPushButton" name="right_buttons_button"> | 403 | <height>16777215</height> |
| 498 | <property name="sizePolicy"> | 404 | </size> |
| 499 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 405 | </property> |
| 500 | <horstretch>0</horstretch> | 406 | <property name="styleSheet"> |
| 501 | <verstretch>0</verstretch> | 407 | <string notr="true">min-width: 55px;</string> |
| 502 | </sizepolicy> | 408 | </property> |
| 503 | </property> | 409 | <property name="text"> |
| 504 | <property name="minimumSize"> | 410 | <string>Up</string> |
| 505 | <size> | 411 | </property> |
| 506 | <width>32</width> | 412 | </widget> |
| 507 | <height>0</height> | 413 | </item> |
| 508 | </size> | 414 | </layout> |
| 509 | </property> | 415 | </widget> |
| 510 | <property name="maximumSize"> | 416 | </item> |
| 511 | <size> | 417 | <item> |
| 512 | <width>40</width> | 418 | <spacer name="horizontalSpacerLStickUpRight"> |
| 513 | <height>16777215</height> | 419 | <property name="orientation"> |
| 514 | </size> | 420 | <enum>Qt::Horizontal</enum> |
| 515 | </property> | 421 | </property> |
| 516 | <property name="text"> | 422 | <property name="sizeHint" stdset="0"> |
| 517 | <string/> | 423 | <size> |
| 518 | </property> | 424 | <width>20</width> |
| 519 | </widget> | 425 | <height>20</height> |
| 520 | </item> | 426 | </size> |
| 521 | <item row="0" column="4"> | 427 | </property> |
| 522 | <widget class="QLabel" name="right_body_label"> | 428 | </spacer> |
| 523 | <property name="text"> | 429 | </item> |
| 524 | <string>Right Body</string> | 430 | </layout> |
| 525 | </property> | 431 | </widget> |
| 526 | </widget> | 432 | </item> |
| 527 | </item> | 433 | <item> |
| 528 | <item row="1" column="4"> | 434 | <layout class="QHBoxLayout" name="buttonLStickLeftRightHorizontaLayout"> |
| 529 | <widget class="QLabel" name="right_buttons_label"> | 435 | <property name="spacing"> |
| 530 | <property name="minimumSize"> | 436 | <number>3</number> |
| 531 | <size> | 437 | </property> |
| 532 | <width>90</width> | 438 | <item alignment="Qt::AlignHCenter"> |
| 533 | <height>0</height> | 439 | <widget class="QGroupBox" name="buttonLStickLeftGroup"> |
| 534 | </size> | 440 | <property name="title"> |
| 535 | </property> | 441 | <string>Left</string> |
| 536 | <property name="text"> | 442 | </property> |
| 537 | <string>Right Buttons</string> | 443 | <property name="alignment"> |
| 538 | </property> | 444 | <set>Qt::AlignCenter</set> |
| 539 | </widget> | 445 | </property> |
| 540 | </item> | 446 | <layout class="QVBoxLayout" name="buttonLStickLeftVerticalLayout"> |
| 541 | <item row="1" column="2"> | 447 | <property name="spacing"> |
| 542 | <widget class="QPushButton" name="left_buttons_button"> | 448 | <number>3</number> |
| 543 | <property name="sizePolicy"> | 449 | </property> |
| 544 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 450 | <property name="leftMargin"> |
| 545 | <horstretch>0</horstretch> | 451 | <number>3</number> |
| 546 | <verstretch>0</verstretch> | 452 | </property> |
| 547 | </sizepolicy> | 453 | <property name="topMargin"> |
| 548 | </property> | 454 | <number>3</number> |
| 549 | <property name="minimumSize"> | 455 | </property> |
| 550 | <size> | 456 | <property name="rightMargin"> |
| 551 | <width>32</width> | 457 | <number>3</number> |
| 552 | <height>0</height> | 458 | </property> |
| 553 | </size> | 459 | <property name="bottomMargin"> |
| 554 | </property> | 460 | <number>3</number> |
| 555 | <property name="maximumSize"> | 461 | </property> |
| 556 | <size> | 462 | <item> |
| 557 | <width>40</width> | 463 | <widget class="QPushButton" name="buttonLStickLeft"> |
| 558 | <height>16777215</height> | 464 | <property name="minimumSize"> |
| 559 | </size> | 465 | <size> |
| 560 | </property> | 466 | <width>57</width> |
| 561 | <property name="text"> | 467 | <height>0</height> |
| 562 | <string/> | 468 | </size> |
| 563 | </property> | 469 | </property> |
| 564 | </widget> | 470 | <property name="maximumSize"> |
| 565 | </item> | 471 | <size> |
| 566 | <item row="0" column="2"> | 472 | <width>55</width> |
| 567 | <widget class="QPushButton" name="left_body_button"> | 473 | <height>16777215</height> |
| 568 | <property name="sizePolicy"> | 474 | </size> |
| 569 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 475 | </property> |
| 570 | <horstretch>0</horstretch> | 476 | <property name="styleSheet"> |
| 571 | <verstretch>0</verstretch> | 477 | <string notr="true">min-width: 55px;</string> |
| 572 | </sizepolicy> | 478 | </property> |
| 573 | </property> | 479 | <property name="text"> |
| 574 | <property name="minimumSize"> | 480 | <string>Left</string> |
| 575 | <size> | 481 | </property> |
| 576 | <width>32</width> | 482 | </widget> |
| 577 | <height>0</height> | 483 | </item> |
| 578 | </size> | 484 | </layout> |
| 579 | </property> | 485 | </widget> |
| 580 | <property name="maximumSize"> | 486 | </item> |
| 581 | <size> | 487 | <item alignment="Qt::AlignHCenter"> |
| 582 | <width>40</width> | 488 | <widget class="QGroupBox" name="buttonLStickRightGroup"> |
| 583 | <height>16777215</height> | 489 | <property name="title"> |
| 584 | </size> | 490 | <string>Right</string> |
| 585 | </property> | 491 | </property> |
| 586 | <property name="text"> | 492 | <property name="alignment"> |
| 587 | <string/> | 493 | <set>Qt::AlignCenter</set> |
| 588 | </property> | 494 | </property> |
| 589 | </widget> | 495 | <layout class="QVBoxLayout" name="buttonLStickRightVerticalLayout"> |
| 590 | </item> | 496 | <property name="spacing"> |
| 591 | <item row="0" column="5"> | 497 | <number>3</number> |
| 592 | <widget class="QPushButton" name="right_body_button"> | 498 | </property> |
| 593 | <property name="sizePolicy"> | 499 | <property name="leftMargin"> |
| 594 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 500 | <number>3</number> |
| 595 | <horstretch>0</horstretch> | 501 | </property> |
| 596 | <verstretch>0</verstretch> | 502 | <property name="topMargin"> |
| 597 | </sizepolicy> | 503 | <number>3</number> |
| 598 | </property> | 504 | </property> |
| 599 | <property name="minimumSize"> | 505 | <property name="rightMargin"> |
| 600 | <size> | 506 | <number>3</number> |
| 601 | <width>32</width> | 507 | </property> |
| 602 | <height>0</height> | 508 | <property name="bottomMargin"> |
| 603 | </size> | 509 | <number>3</number> |
| 604 | </property> | 510 | </property> |
| 605 | <property name="maximumSize"> | 511 | <item> |
| 606 | <size> | 512 | <widget class="QPushButton" name="buttonLStickRight"> |
| 607 | <width>40</width> | 513 | <property name="minimumSize"> |
| 608 | <height>16777215</height> | 514 | <size> |
| 609 | </size> | 515 | <width>57</width> |
| 610 | </property> | 516 | <height>0</height> |
| 611 | <property name="text"> | 517 | </size> |
| 612 | <string/> | 518 | </property> |
| 613 | </property> | 519 | <property name="maximumSize"> |
| 614 | </widget> | 520 | <size> |
| 615 | </item> | 521 | <width>55</width> |
| 616 | <item row="0" column="3"> | 522 | <height>16777215</height> |
| 617 | <spacer name="horizontalSpacer_4"> | 523 | </size> |
| 618 | <property name="orientation"> | 524 | </property> |
| 619 | <enum>Qt::Horizontal</enum> | 525 | <property name="styleSheet"> |
| 620 | </property> | 526 | <string notr="true">min-width: 55px;</string> |
| 621 | <property name="sizeType"> | 527 | </property> |
| 622 | <enum>QSizePolicy::Fixed</enum> | 528 | <property name="text"> |
| 623 | </property> | 529 | <string>Right</string> |
| 624 | <property name="sizeHint" stdset="0"> | 530 | </property> |
| 625 | <size> | 531 | </widget> |
| 626 | <width>20</width> | 532 | </item> |
| 627 | <height>20</height> | 533 | </layout> |
| 628 | </size> | 534 | </widget> |
| 629 | </property> | 535 | </item> |
| 630 | </spacer> | 536 | </layout> |
| 631 | </item> | 537 | </item> |
| 632 | </layout> | 538 | <item> |
| 633 | </widget> | 539 | <widget class="QWidget" name="buttonLStickDownWidget" native="true"> |
| 634 | </item> | 540 | <layout class="QHBoxLayout" name="horizontalLayout_22"> |
| 635 | <item row="1" column="0"> | 541 | <property name="spacing"> |
| 636 | <widget class="QGroupBox" name="LStick"> | 542 | <number>0</number> |
| 637 | <property name="title"> | 543 | </property> |
| 638 | <string>Left Stick</string> | 544 | <property name="leftMargin"> |
| 639 | </property> | 545 | <number>0</number> |
| 640 | <property name="flat"> | 546 | </property> |
| 641 | <bool>false</bool> | 547 | <property name="topMargin"> |
| 642 | </property> | 548 | <number>0</number> |
| 643 | <property name="checkable"> | 549 | </property> |
| 644 | <bool>false</bool> | 550 | <property name="rightMargin"> |
| 645 | </property> | 551 | <number>0</number> |
| 646 | <layout class="QGridLayout" name="gridLayout_4"> | 552 | </property> |
| 647 | <item row="1" column="1"> | 553 | <property name="bottomMargin"> |
| 648 | <layout class="QVBoxLayout" name="buttonLStickUpVerticalLayout"> | 554 | <number>0</number> |
| 649 | <item> | 555 | </property> |
| 650 | <layout class="QHBoxLayout" name="buttonLStickUpHorizontalLayout"> | 556 | <item> |
| 651 | <item> | 557 | <spacer name="horizontalSpacerLStickDownLeft"> |
| 652 | <widget class="QLabel" name="labelLStickUp"> | 558 | <property name="orientation"> |
| 653 | <property name="text"> | 559 | <enum>Qt::Horizontal</enum> |
| 654 | <string>Up:</string> | 560 | </property> |
| 561 | <property name="sizeHint" stdset="0"> | ||
| 562 | <size> | ||
| 563 | <width>20</width> | ||
| 564 | <height>20</height> | ||
| 565 | </size> | ||
| 566 | </property> | ||
| 567 | </spacer> | ||
| 568 | </item> | ||
| 569 | <item alignment="Qt::AlignHCenter"> | ||
| 570 | <widget class="QGroupBox" name="buttonLStickDownGroup"> | ||
| 571 | <property name="title"> | ||
| 572 | <string>Down</string> | ||
| 573 | </property> | ||
| 574 | <property name="alignment"> | ||
| 575 | <set>Qt::AlignCenter</set> | ||
| 576 | </property> | ||
| 577 | <layout class="QVBoxLayout" name="buttonLStickDownVerticalLayout"> | ||
| 578 | <property name="spacing"> | ||
| 579 | <number>3</number> | ||
| 580 | </property> | ||
| 581 | <property name="leftMargin"> | ||
| 582 | <number>3</number> | ||
| 583 | </property> | ||
| 584 | <property name="topMargin"> | ||
| 585 | <number>3</number> | ||
| 586 | </property> | ||
| 587 | <property name="rightMargin"> | ||
| 588 | <number>3</number> | ||
| 589 | </property> | ||
| 590 | <property name="bottomMargin"> | ||
| 591 | <number>3</number> | ||
| 592 | </property> | ||
| 593 | <item> | ||
| 594 | <widget class="QPushButton" name="buttonLStickDown"> | ||
| 595 | <property name="minimumSize"> | ||
| 596 | <size> | ||
| 597 | <width>57</width> | ||
| 598 | <height>0</height> | ||
| 599 | </size> | ||
| 600 | </property> | ||
| 601 | <property name="maximumSize"> | ||
| 602 | <size> | ||
| 603 | <width>55</width> | ||
| 604 | <height>16777215</height> | ||
| 605 | </size> | ||
| 606 | </property> | ||
| 607 | <property name="styleSheet"> | ||
| 608 | <string notr="true">min-width: 55px;</string> | ||
| 609 | </property> | ||
| 610 | <property name="text"> | ||
| 611 | <string>Down</string> | ||
| 612 | </property> | ||
| 613 | </widget> | ||
| 614 | </item> | ||
| 615 | </layout> | ||
| 616 | </widget> | ||
| 617 | </item> | ||
| 618 | <item> | ||
| 619 | <spacer name="horizontalSpacerLStickDownRight"> | ||
| 620 | <property name="orientation"> | ||
| 621 | <enum>Qt::Horizontal</enum> | ||
| 622 | </property> | ||
| 623 | <property name="sizeHint" stdset="0"> | ||
| 624 | <size> | ||
| 625 | <width>20</width> | ||
| 626 | <height>20</height> | ||
| 627 | </size> | ||
| 628 | </property> | ||
| 629 | </spacer> | ||
| 630 | </item> | ||
| 631 | </layout> | ||
| 632 | </widget> | ||
| 633 | </item> | ||
| 634 | <item> | ||
| 635 | <layout class="QHBoxLayout" name="buttonLStickPressedModifierHorizontalLayout"> | ||
| 636 | <property name="spacing"> | ||
| 637 | <number>3</number> | ||
| 638 | </property> | ||
| 639 | <item alignment="Qt::AlignHCenter"> | ||
| 640 | <widget class="QGroupBox" name="buttonLStickPressedGroup"> | ||
| 641 | <property name="title"> | ||
| 642 | <string>Pressed</string> | ||
| 643 | </property> | ||
| 644 | <property name="alignment"> | ||
| 645 | <set>Qt::AlignCenter</set> | ||
| 646 | </property> | ||
| 647 | <layout class="QVBoxLayout" name="buttonLStickPressedVerticalLayout" stretch="0"> | ||
| 648 | <property name="spacing"> | ||
| 649 | <number>3</number> | ||
| 650 | </property> | ||
| 651 | <property name="leftMargin"> | ||
| 652 | <number>3</number> | ||
| 653 | </property> | ||
| 654 | <property name="topMargin"> | ||
| 655 | <number>3</number> | ||
| 656 | </property> | ||
| 657 | <property name="rightMargin"> | ||
| 658 | <number>3</number> | ||
| 659 | </property> | ||
| 660 | <property name="bottomMargin"> | ||
| 661 | <number>3</number> | ||
| 662 | </property> | ||
| 663 | <item> | ||
| 664 | <widget class="QPushButton" name="buttonLStick"> | ||
| 665 | <property name="minimumSize"> | ||
| 666 | <size> | ||
| 667 | <width>57</width> | ||
| 668 | <height>0</height> | ||
| 669 | </size> | ||
| 670 | </property> | ||
| 671 | <property name="maximumSize"> | ||
| 672 | <size> | ||
| 673 | <width>55</width> | ||
| 674 | <height>16777215</height> | ||
| 675 | </size> | ||
| 676 | </property> | ||
| 677 | <property name="styleSheet"> | ||
| 678 | <string notr="true">min-width: 55px;</string> | ||
| 679 | </property> | ||
| 680 | <property name="text"> | ||
| 681 | <string>Pressed</string> | ||
| 682 | </property> | ||
| 683 | </widget> | ||
| 684 | </item> | ||
| 685 | </layout> | ||
| 686 | </widget> | ||
| 687 | </item> | ||
| 688 | <item alignment="Qt::AlignHCenter"> | ||
| 689 | <widget class="QGroupBox" name="buttonLStickModGroup"> | ||
| 690 | <property name="title"> | ||
| 691 | <string>Modifier</string> | ||
| 692 | </property> | ||
| 693 | <property name="alignment"> | ||
| 694 | <set>Qt::AlignCenter</set> | ||
| 695 | </property> | ||
| 696 | <layout class="QVBoxLayout" name="buttonLStickModVerticalLayout"> | ||
| 697 | <property name="spacing"> | ||
| 698 | <number>3</number> | ||
| 699 | </property> | ||
| 700 | <property name="leftMargin"> | ||
| 701 | <number>3</number> | ||
| 702 | </property> | ||
| 703 | <property name="topMargin"> | ||
| 704 | <number>3</number> | ||
| 705 | </property> | ||
| 706 | <property name="rightMargin"> | ||
| 707 | <number>3</number> | ||
| 708 | </property> | ||
| 709 | <property name="bottomMargin"> | ||
| 710 | <number>3</number> | ||
| 711 | </property> | ||
| 712 | <item> | ||
| 713 | <widget class="QPushButton" name="buttonLStickMod"> | ||
| 714 | <property name="minimumSize"> | ||
| 715 | <size> | ||
| 716 | <width>57</width> | ||
| 717 | <height>0</height> | ||
| 718 | </size> | ||
| 719 | </property> | ||
| 720 | <property name="maximumSize"> | ||
| 721 | <size> | ||
| 722 | <width>55</width> | ||
| 723 | <height>16777215</height> | ||
| 724 | </size> | ||
| 725 | </property> | ||
| 726 | <property name="styleSheet"> | ||
| 727 | <string notr="true">min-width: 55px;</string> | ||
| 728 | </property> | ||
| 729 | <property name="text"> | ||
| 730 | <string>Modifier</string> | ||
| 731 | </property> | ||
| 732 | </widget> | ||
| 733 | </item> | ||
| 734 | </layout> | ||
| 735 | </widget> | ||
| 736 | </item> | ||
| 737 | <item> | ||
| 738 | <widget class="QGroupBox" name="buttonLStickRangeGroup"> | ||
| 739 | <property name="title"> | ||
| 740 | <string>Range</string> | ||
| 741 | </property> | ||
| 742 | <layout class="QHBoxLayout" name="buttonLStickRangeGroupHorizontalLayout"> | ||
| 743 | <property name="spacing"> | ||
| 744 | <number>3</number> | ||
| 745 | </property> | ||
| 746 | <property name="leftMargin"> | ||
| 747 | <number>3</number> | ||
| 748 | </property> | ||
| 749 | <property name="topMargin"> | ||
| 750 | <number>3</number> | ||
| 751 | </property> | ||
| 752 | <property name="rightMargin"> | ||
| 753 | <number>3</number> | ||
| 754 | </property> | ||
| 755 | <property name="bottomMargin"> | ||
| 756 | <number>3</number> | ||
| 757 | </property> | ||
| 758 | <item> | ||
| 759 | <widget class="QSpinBox" name="spinboxLStickRange"> | ||
| 760 | <property name="minimumSize"> | ||
| 761 | <size> | ||
| 762 | <width>55</width> | ||
| 763 | <height>21</height> | ||
| 764 | </size> | ||
| 765 | </property> | ||
| 766 | <property name="maximumSize"> | ||
| 767 | <size> | ||
| 768 | <width>55</width> | ||
| 769 | <height>16777215</height> | ||
| 770 | </size> | ||
| 771 | </property> | ||
| 772 | <property name="suffix"> | ||
| 773 | <string>%</string> | ||
| 774 | </property> | ||
| 775 | <property name="minimum"> | ||
| 776 | <number>50</number> | ||
| 777 | </property> | ||
| 778 | <property name="maximum"> | ||
| 779 | <number>150</number> | ||
| 780 | </property> | ||
| 781 | <property name="value"> | ||
| 782 | <number>100</number> | ||
| 783 | </property> | ||
| 784 | </widget> | ||
| 785 | </item> | ||
| 786 | </layout> | ||
| 787 | </widget> | ||
| 788 | </item> | ||
| 789 | </layout> | ||
| 790 | </item> | ||
| 791 | <item> | ||
| 792 | <layout class="QVBoxLayout" name="sliderLStickDeadzoneModifierRangeVerticalLayout"> | ||
| 793 | <property name="spacing"> | ||
| 794 | <number>3</number> | ||
| 795 | </property> | ||
| 796 | <property name="sizeConstraint"> | ||
| 797 | <enum>QLayout::SetDefaultConstraint</enum> | ||
| 798 | </property> | ||
| 799 | <property name="leftMargin"> | ||
| 800 | <number>0</number> | ||
| 801 | </property> | ||
| 802 | <property name="topMargin"> | ||
| 803 | <number>2</number> | ||
| 804 | </property> | ||
| 805 | <property name="rightMargin"> | ||
| 806 | <number>0</number> | ||
| 807 | </property> | ||
| 808 | <property name="bottomMargin"> | ||
| 809 | <number>3</number> | ||
| 810 | </property> | ||
| 811 | <item> | ||
| 812 | <layout class="QHBoxLayout" name="sliderLStickDeadzoneHorizontalLayout"> | ||
| 813 | <item> | ||
| 814 | <widget class="QLabel" name="labelLStickDeadzone"> | ||
| 815 | <property name="text"> | ||
| 816 | <string>Deadzone: 0%</string> | ||
| 817 | </property> | ||
| 818 | <property name="alignment"> | ||
| 819 | <set>Qt::AlignHCenter</set> | ||
| 820 | </property> | ||
| 821 | </widget> | ||
| 822 | </item> | ||
| 823 | </layout> | ||
| 824 | </item> | ||
| 825 | <item> | ||
| 826 | <widget class="QSlider" name="sliderLStickDeadzone"> | ||
| 827 | <property name="maximum"> | ||
| 828 | <number>100</number> | ||
| 829 | </property> | ||
| 830 | <property name="orientation"> | ||
| 831 | <enum>Qt::Horizontal</enum> | ||
| 832 | </property> | ||
| 833 | </widget> | ||
| 834 | </item> | ||
| 835 | <item> | ||
| 836 | <layout class="QHBoxLayout" name="sliderLStickModifierRangeHorizontalLayout"> | ||
| 837 | <item> | ||
| 838 | <widget class="QLabel" name="labelLStickModifierRange"> | ||
| 839 | <property name="text"> | ||
| 840 | <string>Modifier Range: 0%</string> | ||
| 841 | </property> | ||
| 842 | <property name="alignment"> | ||
| 843 | <set>Qt::AlignHCenter</set> | ||
| 844 | </property> | ||
| 845 | </widget> | ||
| 846 | </item> | ||
| 847 | </layout> | ||
| 848 | </item> | ||
| 849 | <item> | ||
| 850 | <widget class="QSlider" name="sliderLStickModifierRange"> | ||
| 851 | <property name="maximum"> | ||
| 852 | <number>100</number> | ||
| 853 | </property> | ||
| 854 | <property name="orientation"> | ||
| 855 | <enum>Qt::Horizontal</enum> | ||
| 856 | </property> | ||
| 857 | </widget> | ||
| 858 | </item> | ||
| 859 | </layout> | ||
| 860 | </item> | ||
| 861 | </layout> | ||
| 862 | </widget> | ||
| 863 | </item> | ||
| 864 | <item> | ||
| 865 | <spacer name="verticalSpacerBottomLeft"> | ||
| 866 | <property name="orientation"> | ||
| 867 | <enum>Qt::Vertical</enum> | ||
| 868 | </property> | ||
| 869 | <property name="sizeHint" stdset="0"> | ||
| 870 | <size> | ||
| 871 | <width>20</width> | ||
| 872 | <height>0</height> | ||
| 873 | </size> | ||
| 874 | </property> | ||
| 875 | </spacer> | ||
| 876 | </item> | ||
| 877 | <item> | ||
| 878 | <widget class="QGroupBox" name="Dpad"> | ||
| 879 | <property name="sizePolicy"> | ||
| 880 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 881 | <horstretch>0</horstretch> | ||
| 882 | <verstretch>0</verstretch> | ||
| 883 | </sizepolicy> | ||
| 884 | </property> | ||
| 885 | <property name="title"> | ||
| 886 | <string>D-Pad</string> | ||
| 887 | </property> | ||
| 888 | <property name="flat"> | ||
| 889 | <bool>false</bool> | ||
| 890 | </property> | ||
| 891 | <property name="checkable"> | ||
| 892 | <bool>false</bool> | ||
| 893 | </property> | ||
| 894 | <layout class="QVBoxLayout" name="verticalLayout_5"> | ||
| 895 | <property name="spacing"> | ||
| 896 | <number>0</number> | ||
| 655 | </property> | 897 | </property> |
| 656 | </widget> | 898 | <property name="leftMargin"> |
| 657 | </item> | 899 | <number>3</number> |
| 658 | </layout> | ||
| 659 | </item> | ||
| 660 | <item> | ||
| 661 | <widget class="QPushButton" name="buttonLStickUp"> | ||
| 662 | <property name="text"> | ||
| 663 | <string/> | ||
| 664 | </property> | ||
| 665 | </widget> | ||
| 666 | </item> | ||
| 667 | </layout> | ||
| 668 | </item> | ||
| 669 | <item row="0" column="2"> | ||
| 670 | <layout class="QVBoxLayout" name="buttonLStickRightVerticalLayout"> | ||
| 671 | <item> | ||
| 672 | <layout class="QHBoxLayout" name="buttonLStickRightHorizontalLayout"> | ||
| 673 | <item> | ||
| 674 | <widget class="QLabel" name="labelLStickRight"> | ||
| 675 | <property name="text"> | ||
| 676 | <string>Right:</string> | ||
| 677 | </property> | 900 | </property> |
| 678 | </widget> | 901 | <property name="topMargin"> |
| 679 | </item> | 902 | <number>0</number> |
| 680 | </layout> | ||
| 681 | </item> | ||
| 682 | <item> | ||
| 683 | <widget class="QPushButton" name="buttonLStickRight"> | ||
| 684 | <property name="text"> | ||
| 685 | <string/> | ||
| 686 | </property> | ||
| 687 | </widget> | ||
| 688 | </item> | ||
| 689 | </layout> | ||
| 690 | </item> | ||
| 691 | <item row="4" column="1" colspan="2"> | ||
| 692 | <widget class="QPushButton" name="buttonLStickAnalog"> | ||
| 693 | <property name="text"> | ||
| 694 | <string>Set Analog Stick</string> | ||
| 695 | </property> | ||
| 696 | </widget> | ||
| 697 | </item> | ||
| 698 | <item row="0" column="1"> | ||
| 699 | <layout class="QVBoxLayout" name="buttonLStickLeftVerticalLayout"> | ||
| 700 | <item> | ||
| 701 | <layout class="QHBoxLayout" name="buttonLStickLeftHorizontalLayout_2"> | ||
| 702 | <item> | ||
| 703 | <widget class="QLabel" name="labelLStickLeft"> | ||
| 704 | <property name="text"> | ||
| 705 | <string>Left:</string> | ||
| 706 | </property> | 903 | </property> |
| 707 | </widget> | 904 | <property name="rightMargin"> |
| 708 | </item> | 905 | <number>3</number> |
| 709 | </layout> | ||
| 710 | </item> | ||
| 711 | <item> | ||
| 712 | <widget class="QPushButton" name="buttonLStickLeft"> | ||
| 713 | <property name="text"> | ||
| 714 | <string/> | ||
| 715 | </property> | ||
| 716 | </widget> | ||
| 717 | </item> | ||
| 718 | </layout> | ||
| 719 | </item> | ||
| 720 | <item row="1" column="2"> | ||
| 721 | <layout class="QVBoxLayout" name="buttonLStickDownVerticalLayout"> | ||
| 722 | <item> | ||
| 723 | <layout class="QHBoxLayout" name="buttonLStickDownHorizontalLayout"> | ||
| 724 | <item> | ||
| 725 | <widget class="QLabel" name="labelLStickDown"> | ||
| 726 | <property name="text"> | ||
| 727 | <string>Down:</string> | ||
| 728 | </property> | 906 | </property> |
| 729 | </widget> | 907 | <property name="bottomMargin"> |
| 730 | </item> | 908 | <number>3</number> |
| 731 | </layout> | ||
| 732 | </item> | ||
| 733 | <item> | ||
| 734 | <widget class="QPushButton" name="buttonLStickDown"> | ||
| 735 | <property name="text"> | ||
| 736 | <string/> | ||
| 737 | </property> | ||
| 738 | </widget> | ||
| 739 | </item> | ||
| 740 | </layout> | ||
| 741 | </item> | ||
| 742 | <item row="3" column="2"> | ||
| 743 | <layout class="QVBoxLayout" name="buttonLStickModVerticalLayout"> | ||
| 744 | <item> | ||
| 745 | <layout class="QHBoxLayout" name="buttonLStickModHorizontalLayout"> | ||
| 746 | <item> | ||
| 747 | <widget class="QLabel" name="labelLStickMod"> | ||
| 748 | <property name="text"> | ||
| 749 | <string>Modifier:</string> | ||
| 750 | </property> | 909 | </property> |
| 751 | </widget> | 910 | <item> |
| 752 | </item> | 911 | <widget class="QWidget" name="buttonDpadUpWidget" native="true"> |
| 753 | </layout> | 912 | <layout class="QHBoxLayout" name="horizontalLayout_23"> |
| 754 | </item> | 913 | <property name="spacing"> |
| 755 | <item> | 914 | <number>0</number> |
| 756 | <widget class="QPushButton" name="buttonLStickMod"> | 915 | </property> |
| 757 | <property name="text"> | 916 | <property name="leftMargin"> |
| 758 | <string/> | 917 | <number>0</number> |
| 759 | </property> | 918 | </property> |
| 760 | </widget> | 919 | <property name="topMargin"> |
| 761 | </item> | 920 | <number>0</number> |
| 762 | </layout> | 921 | </property> |
| 922 | <property name="rightMargin"> | ||
| 923 | <number>0</number> | ||
| 924 | </property> | ||
| 925 | <property name="bottomMargin"> | ||
| 926 | <number>0</number> | ||
| 927 | </property> | ||
| 928 | <item> | ||
| 929 | <spacer name="horizontalSpacerDpadUpLeft"> | ||
| 930 | <property name="orientation"> | ||
| 931 | <enum>Qt::Horizontal</enum> | ||
| 932 | </property> | ||
| 933 | <property name="sizeHint" stdset="0"> | ||
| 934 | <size> | ||
| 935 | <width>20</width> | ||
| 936 | <height>20</height> | ||
| 937 | </size> | ||
| 938 | </property> | ||
| 939 | </spacer> | ||
| 940 | </item> | ||
| 941 | <item alignment="Qt::AlignHCenter"> | ||
| 942 | <widget class="QGroupBox" name="buttonDpadUpGroup"> | ||
| 943 | <property name="title"> | ||
| 944 | <string>Up</string> | ||
| 945 | </property> | ||
| 946 | <property name="alignment"> | ||
| 947 | <set>Qt::AlignCenter</set> | ||
| 948 | </property> | ||
| 949 | <layout class="QVBoxLayout" name="buttonDpadUpVerticalLayout"> | ||
| 950 | <property name="spacing"> | ||
| 951 | <number>3</number> | ||
| 952 | </property> | ||
| 953 | <property name="leftMargin"> | ||
| 954 | <number>3</number> | ||
| 955 | </property> | ||
| 956 | <property name="topMargin"> | ||
| 957 | <number>3</number> | ||
| 958 | </property> | ||
| 959 | <property name="rightMargin"> | ||
| 960 | <number>3</number> | ||
| 961 | </property> | ||
| 962 | <property name="bottomMargin"> | ||
| 963 | <number>3</number> | ||
| 964 | </property> | ||
| 965 | <item> | ||
| 966 | <widget class="QPushButton" name="buttonDpadUp"> | ||
| 967 | <property name="minimumSize"> | ||
| 968 | <size> | ||
| 969 | <width>57</width> | ||
| 970 | <height>0</height> | ||
| 971 | </size> | ||
| 972 | </property> | ||
| 973 | <property name="maximumSize"> | ||
| 974 | <size> | ||
| 975 | <width>55</width> | ||
| 976 | <height>16777215</height> | ||
| 977 | </size> | ||
| 978 | </property> | ||
| 979 | <property name="styleSheet"> | ||
| 980 | <string notr="true">min-width: 55px;</string> | ||
| 981 | </property> | ||
| 982 | <property name="text"> | ||
| 983 | <string>Up</string> | ||
| 984 | </property> | ||
| 985 | </widget> | ||
| 986 | </item> | ||
| 987 | </layout> | ||
| 988 | </widget> | ||
| 989 | </item> | ||
| 990 | <item> | ||
| 991 | <spacer name="horizontalSpacerDpadUpRight"> | ||
| 992 | <property name="orientation"> | ||
| 993 | <enum>Qt::Horizontal</enum> | ||
| 994 | </property> | ||
| 995 | <property name="sizeHint" stdset="0"> | ||
| 996 | <size> | ||
| 997 | <width>20</width> | ||
| 998 | <height>20</height> | ||
| 999 | </size> | ||
| 1000 | </property> | ||
| 1001 | </spacer> | ||
| 1002 | </item> | ||
| 1003 | </layout> | ||
| 1004 | </widget> | ||
| 1005 | </item> | ||
| 1006 | <item> | ||
| 1007 | <layout class="QHBoxLayout" name="buttonDpadLeftRightHorizontalLayout"> | ||
| 1008 | <property name="spacing"> | ||
| 1009 | <number>3</number> | ||
| 1010 | </property> | ||
| 1011 | <item alignment="Qt::AlignHCenter"> | ||
| 1012 | <widget class="QGroupBox" name="buttonDpadLeftGroup"> | ||
| 1013 | <property name="title"> | ||
| 1014 | <string>Left</string> | ||
| 1015 | </property> | ||
| 1016 | <property name="alignment"> | ||
| 1017 | <set>Qt::AlignCenter</set> | ||
| 1018 | </property> | ||
| 1019 | <layout class="QVBoxLayout" name="buttonDpadLeftVerticalLayout"> | ||
| 1020 | <property name="spacing"> | ||
| 1021 | <number>3</number> | ||
| 1022 | </property> | ||
| 1023 | <property name="leftMargin"> | ||
| 1024 | <number>3</number> | ||
| 1025 | </property> | ||
| 1026 | <property name="topMargin"> | ||
| 1027 | <number>3</number> | ||
| 1028 | </property> | ||
| 1029 | <property name="rightMargin"> | ||
| 1030 | <number>3</number> | ||
| 1031 | </property> | ||
| 1032 | <property name="bottomMargin"> | ||
| 1033 | <number>3</number> | ||
| 1034 | </property> | ||
| 1035 | <item> | ||
| 1036 | <widget class="QPushButton" name="buttonDpadLeft"> | ||
| 1037 | <property name="minimumSize"> | ||
| 1038 | <size> | ||
| 1039 | <width>57</width> | ||
| 1040 | <height>0</height> | ||
| 1041 | </size> | ||
| 1042 | </property> | ||
| 1043 | <property name="maximumSize"> | ||
| 1044 | <size> | ||
| 1045 | <width>55</width> | ||
| 1046 | <height>16777215</height> | ||
| 1047 | </size> | ||
| 1048 | </property> | ||
| 1049 | <property name="styleSheet"> | ||
| 1050 | <string notr="true">min-width: 55px;</string> | ||
| 1051 | </property> | ||
| 1052 | <property name="text"> | ||
| 1053 | <string>Left</string> | ||
| 1054 | </property> | ||
| 1055 | </widget> | ||
| 1056 | </item> | ||
| 1057 | </layout> | ||
| 1058 | </widget> | ||
| 1059 | </item> | ||
| 1060 | <item alignment="Qt::AlignHCenter"> | ||
| 1061 | <widget class="QGroupBox" name="buttonDpadRightGroup"> | ||
| 1062 | <property name="title"> | ||
| 1063 | <string>Right</string> | ||
| 1064 | </property> | ||
| 1065 | <property name="alignment"> | ||
| 1066 | <set>Qt::AlignCenter</set> | ||
| 1067 | </property> | ||
| 1068 | <layout class="QVBoxLayout" name="buttonDpadRightVerticalLayout"> | ||
| 1069 | <property name="spacing"> | ||
| 1070 | <number>3</number> | ||
| 1071 | </property> | ||
| 1072 | <property name="leftMargin"> | ||
| 1073 | <number>3</number> | ||
| 1074 | </property> | ||
| 1075 | <property name="topMargin"> | ||
| 1076 | <number>3</number> | ||
| 1077 | </property> | ||
| 1078 | <property name="rightMargin"> | ||
| 1079 | <number>3</number> | ||
| 1080 | </property> | ||
| 1081 | <property name="bottomMargin"> | ||
| 1082 | <number>3</number> | ||
| 1083 | </property> | ||
| 1084 | <item> | ||
| 1085 | <widget class="QPushButton" name="buttonDpadRight"> | ||
| 1086 | <property name="minimumSize"> | ||
| 1087 | <size> | ||
| 1088 | <width>57</width> | ||
| 1089 | <height>0</height> | ||
| 1090 | </size> | ||
| 1091 | </property> | ||
| 1092 | <property name="maximumSize"> | ||
| 1093 | <size> | ||
| 1094 | <width>55</width> | ||
| 1095 | <height>16777215</height> | ||
| 1096 | </size> | ||
| 1097 | </property> | ||
| 1098 | <property name="styleSheet"> | ||
| 1099 | <string notr="true">min-width: 55px;</string> | ||
| 1100 | </property> | ||
| 1101 | <property name="text"> | ||
| 1102 | <string>Right</string> | ||
| 1103 | </property> | ||
| 1104 | </widget> | ||
| 1105 | </item> | ||
| 1106 | </layout> | ||
| 1107 | </widget> | ||
| 1108 | </item> | ||
| 1109 | </layout> | ||
| 1110 | </item> | ||
| 1111 | <item> | ||
| 1112 | <widget class="QWidget" name="buttonDpadDownWidget" native="true"> | ||
| 1113 | <layout class="QHBoxLayout" name="horizontalLayout_24"> | ||
| 1114 | <property name="spacing"> | ||
| 1115 | <number>0</number> | ||
| 1116 | </property> | ||
| 1117 | <property name="leftMargin"> | ||
| 1118 | <number>0</number> | ||
| 1119 | </property> | ||
| 1120 | <property name="topMargin"> | ||
| 1121 | <number>0</number> | ||
| 1122 | </property> | ||
| 1123 | <property name="rightMargin"> | ||
| 1124 | <number>0</number> | ||
| 1125 | </property> | ||
| 1126 | <property name="bottomMargin"> | ||
| 1127 | <number>0</number> | ||
| 1128 | </property> | ||
| 1129 | <item> | ||
| 1130 | <spacer name="horizontalSpacerDpadDownLeft"> | ||
| 1131 | <property name="orientation"> | ||
| 1132 | <enum>Qt::Horizontal</enum> | ||
| 1133 | </property> | ||
| 1134 | <property name="sizeHint" stdset="0"> | ||
| 1135 | <size> | ||
| 1136 | <width>20</width> | ||
| 1137 | <height>20</height> | ||
| 1138 | </size> | ||
| 1139 | </property> | ||
| 1140 | </spacer> | ||
| 1141 | </item> | ||
| 1142 | <item alignment="Qt::AlignHCenter"> | ||
| 1143 | <widget class="QGroupBox" name="buttonDpadDownGroup"> | ||
| 1144 | <property name="title"> | ||
| 1145 | <string>Down</string> | ||
| 1146 | </property> | ||
| 1147 | <property name="alignment"> | ||
| 1148 | <set>Qt::AlignCenter</set> | ||
| 1149 | </property> | ||
| 1150 | <layout class="QVBoxLayout" name="buttonDpadDownVerticalLayout"> | ||
| 1151 | <property name="spacing"> | ||
| 1152 | <number>3</number> | ||
| 1153 | </property> | ||
| 1154 | <property name="leftMargin"> | ||
| 1155 | <number>3</number> | ||
| 1156 | </property> | ||
| 1157 | <property name="topMargin"> | ||
| 1158 | <number>3</number> | ||
| 1159 | </property> | ||
| 1160 | <property name="rightMargin"> | ||
| 1161 | <number>3</number> | ||
| 1162 | </property> | ||
| 1163 | <property name="bottomMargin"> | ||
| 1164 | <number>3</number> | ||
| 1165 | </property> | ||
| 1166 | <item> | ||
| 1167 | <widget class="QPushButton" name="buttonDpadDown"> | ||
| 1168 | <property name="minimumSize"> | ||
| 1169 | <size> | ||
| 1170 | <width>57</width> | ||
| 1171 | <height>0</height> | ||
| 1172 | </size> | ||
| 1173 | </property> | ||
| 1174 | <property name="maximumSize"> | ||
| 1175 | <size> | ||
| 1176 | <width>55</width> | ||
| 1177 | <height>16777215</height> | ||
| 1178 | </size> | ||
| 1179 | </property> | ||
| 1180 | <property name="styleSheet"> | ||
| 1181 | <string notr="true">min-width: 55px;</string> | ||
| 1182 | </property> | ||
| 1183 | <property name="text"> | ||
| 1184 | <string>Down</string> | ||
| 1185 | </property> | ||
| 1186 | </widget> | ||
| 1187 | </item> | ||
| 1188 | </layout> | ||
| 1189 | </widget> | ||
| 1190 | </item> | ||
| 1191 | <item> | ||
| 1192 | <spacer name="horizontalSpacerDpadDownRight"> | ||
| 1193 | <property name="orientation"> | ||
| 1194 | <enum>Qt::Horizontal</enum> | ||
| 1195 | </property> | ||
| 1196 | <property name="sizeHint" stdset="0"> | ||
| 1197 | <size> | ||
| 1198 | <width>20</width> | ||
| 1199 | <height>20</height> | ||
| 1200 | </size> | ||
| 1201 | </property> | ||
| 1202 | </spacer> | ||
| 1203 | </item> | ||
| 1204 | </layout> | ||
| 1205 | </widget> | ||
| 1206 | </item> | ||
| 1207 | </layout> | ||
| 1208 | </widget> | ||
| 1209 | </item> | ||
| 1210 | <item> | ||
| 1211 | <spacer name="verticalSpacerBottomLeft_2"> | ||
| 1212 | <property name="orientation"> | ||
| 1213 | <enum>Qt::Vertical</enum> | ||
| 1214 | </property> | ||
| 1215 | <property name="sizeHint" stdset="0"> | ||
| 1216 | <size> | ||
| 1217 | <width>20</width> | ||
| 1218 | <height>0</height> | ||
| 1219 | </size> | ||
| 1220 | </property> | ||
| 1221 | </spacer> | ||
| 1222 | </item> | ||
| 1223 | </layout> | ||
| 1224 | </widget> | ||
| 763 | </item> | 1225 | </item> |
| 764 | <item row="3" column="1"> | 1226 | <item> |
| 765 | <layout class="QVBoxLayout" name="buttonLStickPressedVerticalLayout" stretch="0,0"> | 1227 | <widget class="QWidget" name="bottomMiddle" native="true"> |
| 766 | <item> | 1228 | <layout class="QVBoxLayout" stretch="0,0,0"> |
| 767 | <layout class="QHBoxLayout" name="buttonLStickPressedHorizontalLayout"> | 1229 | <property name="spacing"> |
| 768 | <item> | 1230 | <number>6</number> |
| 769 | <widget class="QLabel" name="labelLStickPressed"> | 1231 | </property> |
| 770 | <property name="text"> | 1232 | <property name="leftMargin"> |
| 771 | <string>Pressed:</string> | 1233 | <number>0</number> |
| 1234 | </property> | ||
| 1235 | <property name="topMargin"> | ||
| 1236 | <number>0</number> | ||
| 1237 | </property> | ||
| 1238 | <property name="rightMargin"> | ||
| 1239 | <number>0</number> | ||
| 1240 | </property> | ||
| 1241 | <property name="bottomMargin"> | ||
| 1242 | <number>0</number> | ||
| 1243 | </property> | ||
| 1244 | <item> | ||
| 1245 | <layout class="QHBoxLayout" name="shoulderButtons"> | ||
| 1246 | <property name="spacing"> | ||
| 1247 | <number>3</number> | ||
| 1248 | </property> | ||
| 1249 | <item> | ||
| 1250 | <widget class="QWidget" name="buttonShoulderButtonsLeft" native="true"> | ||
| 1251 | <layout class="QVBoxLayout" name="buttonShoulderButtonsLeftVerticalLayout"> | ||
| 1252 | <property name="spacing"> | ||
| 1253 | <number>0</number> | ||
| 1254 | </property> | ||
| 1255 | <property name="leftMargin"> | ||
| 1256 | <number>0</number> | ||
| 1257 | </property> | ||
| 1258 | <property name="topMargin"> | ||
| 1259 | <number>0</number> | ||
| 1260 | </property> | ||
| 1261 | <property name="rightMargin"> | ||
| 1262 | <number>0</number> | ||
| 1263 | </property> | ||
| 1264 | <property name="bottomMargin"> | ||
| 1265 | <number>0</number> | ||
| 1266 | </property> | ||
| 1267 | <item> | ||
| 1268 | <widget class="QGroupBox" name="buttonShoulderButtonsButtonLGroup"> | ||
| 1269 | <property name="title"> | ||
| 1270 | <string>L</string> | ||
| 1271 | </property> | ||
| 1272 | <property name="alignment"> | ||
| 1273 | <set>Qt::AlignCenter</set> | ||
| 1274 | </property> | ||
| 1275 | <layout class="QVBoxLayout" name="buttonShoulderButtonsLVerticalLayout"> | ||
| 1276 | <property name="spacing"> | ||
| 1277 | <number>3</number> | ||
| 1278 | </property> | ||
| 1279 | <property name="leftMargin"> | ||
| 1280 | <number>3</number> | ||
| 1281 | </property> | ||
| 1282 | <property name="topMargin"> | ||
| 1283 | <number>3</number> | ||
| 1284 | </property> | ||
| 1285 | <property name="rightMargin"> | ||
| 1286 | <number>3</number> | ||
| 1287 | </property> | ||
| 1288 | <property name="bottomMargin"> | ||
| 1289 | <number>3</number> | ||
| 1290 | </property> | ||
| 1291 | <item> | ||
| 1292 | <widget class="QPushButton" name="buttonL"> | ||
| 1293 | <property name="minimumSize"> | ||
| 1294 | <size> | ||
| 1295 | <width>57</width> | ||
| 1296 | <height>0</height> | ||
| 1297 | </size> | ||
| 1298 | </property> | ||
| 1299 | <property name="maximumSize"> | ||
| 1300 | <size> | ||
| 1301 | <width>55</width> | ||
| 1302 | <height>16777215</height> | ||
| 1303 | </size> | ||
| 1304 | </property> | ||
| 1305 | <property name="styleSheet"> | ||
| 1306 | <string notr="true">min-width: 55px;</string> | ||
| 1307 | </property> | ||
| 1308 | <property name="text"> | ||
| 1309 | <string>L</string> | ||
| 1310 | </property> | ||
| 1311 | </widget> | ||
| 1312 | </item> | ||
| 1313 | </layout> | ||
| 1314 | </widget> | ||
| 1315 | </item> | ||
| 1316 | <item> | ||
| 1317 | <widget class="QGroupBox" name="buttonShoulderButtonsButtonZLGroup"> | ||
| 1318 | <property name="title"> | ||
| 1319 | <string>ZL</string> | ||
| 1320 | </property> | ||
| 1321 | <property name="alignment"> | ||
| 1322 | <set>Qt::AlignCenter</set> | ||
| 1323 | </property> | ||
| 1324 | <layout class="QVBoxLayout" name="buttonShoulderButtonsZLVerticalLayout"> | ||
| 1325 | <property name="spacing"> | ||
| 1326 | <number>3</number> | ||
| 1327 | </property> | ||
| 1328 | <property name="leftMargin"> | ||
| 1329 | <number>3</number> | ||
| 1330 | </property> | ||
| 1331 | <property name="topMargin"> | ||
| 1332 | <number>3</number> | ||
| 1333 | </property> | ||
| 1334 | <property name="rightMargin"> | ||
| 1335 | <number>3</number> | ||
| 1336 | </property> | ||
| 1337 | <property name="bottomMargin"> | ||
| 1338 | <number>3</number> | ||
| 1339 | </property> | ||
| 1340 | <item> | ||
| 1341 | <widget class="QPushButton" name="buttonZL"> | ||
| 1342 | <property name="minimumSize"> | ||
| 1343 | <size> | ||
| 1344 | <width>57</width> | ||
| 1345 | <height>0</height> | ||
| 1346 | </size> | ||
| 1347 | </property> | ||
| 1348 | <property name="maximumSize"> | ||
| 1349 | <size> | ||
| 1350 | <width>55</width> | ||
| 1351 | <height>16777215</height> | ||
| 1352 | </size> | ||
| 1353 | </property> | ||
| 1354 | <property name="styleSheet"> | ||
| 1355 | <string notr="true">min-width: 55px;</string> | ||
| 1356 | </property> | ||
| 1357 | <property name="text"> | ||
| 1358 | <string>ZL</string> | ||
| 1359 | </property> | ||
| 1360 | </widget> | ||
| 1361 | </item> | ||
| 1362 | </layout> | ||
| 1363 | </widget> | ||
| 1364 | </item> | ||
| 1365 | </layout> | ||
| 1366 | </widget> | ||
| 1367 | </item> | ||
| 1368 | <item> | ||
| 1369 | <widget class="QWidget" name="horizontalSpacerShoulderButtonsWidget" native="true"> | ||
| 1370 | <layout class="QHBoxLayout" name="horizontalSpacerShoulderButtonsWidgetLayout"> | ||
| 1371 | <property name="spacing"> | ||
| 1372 | <number>0</number> | ||
| 1373 | </property> | ||
| 1374 | <property name="leftMargin"> | ||
| 1375 | <number>0</number> | ||
| 1376 | </property> | ||
| 1377 | <property name="topMargin"> | ||
| 1378 | <number>0</number> | ||
| 1379 | </property> | ||
| 1380 | <property name="rightMargin"> | ||
| 1381 | <number>0</number> | ||
| 1382 | </property> | ||
| 1383 | <property name="bottomMargin"> | ||
| 1384 | <number>0</number> | ||
| 1385 | </property> | ||
| 1386 | <item> | ||
| 1387 | <spacer name="horizontalSpacerShoulderButtons1"> | ||
| 1388 | <property name="orientation"> | ||
| 1389 | <enum>Qt::Horizontal</enum> | ||
| 1390 | </property> | ||
| 1391 | <property name="sizeHint" stdset="0"> | ||
| 1392 | <size> | ||
| 1393 | <width>0</width> | ||
| 1394 | <height>20</height> | ||
| 1395 | </size> | ||
| 1396 | </property> | ||
| 1397 | </spacer> | ||
| 1398 | </item> | ||
| 1399 | </layout> | ||
| 1400 | </widget> | ||
| 1401 | </item> | ||
| 1402 | <item> | ||
| 1403 | <widget class="QWidget" name="buttonMiscButtonsMinusScreenshot" native="true"> | ||
| 1404 | <layout class="QVBoxLayout" name="buttonMiscButtonsMinusScreenshotVerticalLayout"> | ||
| 1405 | <property name="spacing"> | ||
| 1406 | <number>0</number> | ||
| 1407 | </property> | ||
| 1408 | <property name="leftMargin"> | ||
| 1409 | <number>0</number> | ||
| 1410 | </property> | ||
| 1411 | <property name="topMargin"> | ||
| 1412 | <number>0</number> | ||
| 1413 | </property> | ||
| 1414 | <property name="rightMargin"> | ||
| 1415 | <number>0</number> | ||
| 1416 | </property> | ||
| 1417 | <property name="bottomMargin"> | ||
| 1418 | <number>0</number> | ||
| 1419 | </property> | ||
| 1420 | <item alignment="Qt::AlignHCenter"> | ||
| 1421 | <widget class="QGroupBox" name="buttonMiscButtonsMinusGroup"> | ||
| 1422 | <property name="title"> | ||
| 1423 | <string>Minus</string> | ||
| 1424 | </property> | ||
| 1425 | <property name="alignment"> | ||
| 1426 | <set>Qt::AlignCenter</set> | ||
| 1427 | </property> | ||
| 1428 | <layout class="QVBoxLayout" name="buttonMiscMinusVerticalLayout"> | ||
| 1429 | <property name="spacing"> | ||
| 1430 | <number>3</number> | ||
| 1431 | </property> | ||
| 1432 | <property name="leftMargin"> | ||
| 1433 | <number>3</number> | ||
| 1434 | </property> | ||
| 1435 | <property name="topMargin"> | ||
| 1436 | <number>3</number> | ||
| 1437 | </property> | ||
| 1438 | <property name="rightMargin"> | ||
| 1439 | <number>3</number> | ||
| 1440 | </property> | ||
| 1441 | <property name="bottomMargin"> | ||
| 1442 | <number>3</number> | ||
| 1443 | </property> | ||
| 1444 | <item> | ||
| 1445 | <widget class="QPushButton" name="buttonMinus"> | ||
| 1446 | <property name="minimumSize"> | ||
| 1447 | <size> | ||
| 1448 | <width>57</width> | ||
| 1449 | <height>0</height> | ||
| 1450 | </size> | ||
| 1451 | </property> | ||
| 1452 | <property name="maximumSize"> | ||
| 1453 | <size> | ||
| 1454 | <width>55</width> | ||
| 1455 | <height>16777215</height> | ||
| 1456 | </size> | ||
| 1457 | </property> | ||
| 1458 | <property name="styleSheet"> | ||
| 1459 | <string notr="true">min-width: 55px;</string> | ||
| 1460 | </property> | ||
| 1461 | <property name="text"> | ||
| 1462 | <string>Minus</string> | ||
| 1463 | </property> | ||
| 1464 | </widget> | ||
| 1465 | </item> | ||
| 1466 | </layout> | ||
| 1467 | </widget> | ||
| 1468 | </item> | ||
| 1469 | <item alignment="Qt::AlignHCenter"> | ||
| 1470 | <widget class="QGroupBox" name="buttonMiscButtonsScreenshotGroup"> | ||
| 1471 | <property name="title"> | ||
| 1472 | <string>Capture</string> | ||
| 1473 | </property> | ||
| 1474 | <property name="alignment"> | ||
| 1475 | <set>Qt::AlignCenter</set> | ||
| 1476 | </property> | ||
| 1477 | <layout class="QVBoxLayout" name="buttonMiscScrCapVerticalLayout"> | ||
| 1478 | <property name="spacing"> | ||
| 1479 | <number>3</number> | ||
| 1480 | </property> | ||
| 1481 | <property name="leftMargin"> | ||
| 1482 | <number>3</number> | ||
| 1483 | </property> | ||
| 1484 | <property name="topMargin"> | ||
| 1485 | <number>3</number> | ||
| 1486 | </property> | ||
| 1487 | <property name="rightMargin"> | ||
| 1488 | <number>3</number> | ||
| 1489 | </property> | ||
| 1490 | <property name="bottomMargin"> | ||
| 1491 | <number>3</number> | ||
| 1492 | </property> | ||
| 1493 | <item> | ||
| 1494 | <widget class="QPushButton" name="buttonScreenshot"> | ||
| 1495 | <property name="minimumSize"> | ||
| 1496 | <size> | ||
| 1497 | <width>57</width> | ||
| 1498 | <height>0</height> | ||
| 1499 | </size> | ||
| 1500 | </property> | ||
| 1501 | <property name="maximumSize"> | ||
| 1502 | <size> | ||
| 1503 | <width>55</width> | ||
| 1504 | <height>16777215</height> | ||
| 1505 | </size> | ||
| 1506 | </property> | ||
| 1507 | <property name="styleSheet"> | ||
| 1508 | <string notr="true">min-width: 55px;</string> | ||
| 1509 | </property> | ||
| 1510 | <property name="text"> | ||
| 1511 | <string>Capture</string> | ||
| 1512 | </property> | ||
| 1513 | </widget> | ||
| 1514 | </item> | ||
| 1515 | </layout> | ||
| 1516 | </widget> | ||
| 1517 | </item> | ||
| 1518 | </layout> | ||
| 1519 | </widget> | ||
| 1520 | </item> | ||
| 1521 | <item> | ||
| 1522 | <widget class="QWidget" name="buttonMiscButtonsPlusHome" native="true"> | ||
| 1523 | <layout class="QVBoxLayout" name="buttonMiscButtonsPlusHomeVerticalLayout"> | ||
| 1524 | <property name="spacing"> | ||
| 1525 | <number>0</number> | ||
| 1526 | </property> | ||
| 1527 | <property name="leftMargin"> | ||
| 1528 | <number>0</number> | ||
| 1529 | </property> | ||
| 1530 | <property name="topMargin"> | ||
| 1531 | <number>0</number> | ||
| 1532 | </property> | ||
| 1533 | <property name="rightMargin"> | ||
| 1534 | <number>0</number> | ||
| 1535 | </property> | ||
| 1536 | <property name="bottomMargin"> | ||
| 1537 | <number>0</number> | ||
| 1538 | </property> | ||
| 1539 | <item alignment="Qt::AlignHCenter"> | ||
| 1540 | <widget class="QGroupBox" name="buttonMiscButtonsPlusGroup"> | ||
| 1541 | <property name="title"> | ||
| 1542 | <string>Plus</string> | ||
| 1543 | </property> | ||
| 1544 | <property name="alignment"> | ||
| 1545 | <set>Qt::AlignCenter</set> | ||
| 1546 | </property> | ||
| 1547 | <layout class="QVBoxLayout" name="buttonMiscPlusVerticalLayout"> | ||
| 1548 | <property name="spacing"> | ||
| 1549 | <number>3</number> | ||
| 1550 | </property> | ||
| 1551 | <property name="leftMargin"> | ||
| 1552 | <number>3</number> | ||
| 1553 | </property> | ||
| 1554 | <property name="topMargin"> | ||
| 1555 | <number>3</number> | ||
| 1556 | </property> | ||
| 1557 | <property name="rightMargin"> | ||
| 1558 | <number>3</number> | ||
| 1559 | </property> | ||
| 1560 | <property name="bottomMargin"> | ||
| 1561 | <number>3</number> | ||
| 1562 | </property> | ||
| 1563 | <item> | ||
| 1564 | <widget class="QPushButton" name="buttonPlus"> | ||
| 1565 | <property name="minimumSize"> | ||
| 1566 | <size> | ||
| 1567 | <width>57</width> | ||
| 1568 | <height>0</height> | ||
| 1569 | </size> | ||
| 1570 | </property> | ||
| 1571 | <property name="maximumSize"> | ||
| 1572 | <size> | ||
| 1573 | <width>55</width> | ||
| 1574 | <height>16777215</height> | ||
| 1575 | </size> | ||
| 1576 | </property> | ||
| 1577 | <property name="styleSheet"> | ||
| 1578 | <string notr="true">min-width: 55px;</string> | ||
| 1579 | </property> | ||
| 1580 | <property name="text"> | ||
| 1581 | <string>Plus</string> | ||
| 1582 | </property> | ||
| 1583 | </widget> | ||
| 1584 | </item> | ||
| 1585 | </layout> | ||
| 1586 | </widget> | ||
| 1587 | </item> | ||
| 1588 | <item alignment="Qt::AlignHCenter"> | ||
| 1589 | <widget class="QGroupBox" name="buttonMiscButtonsHomeGroup"> | ||
| 1590 | <property name="title"> | ||
| 1591 | <string>Home</string> | ||
| 1592 | </property> | ||
| 1593 | <property name="alignment"> | ||
| 1594 | <set>Qt::AlignCenter</set> | ||
| 1595 | </property> | ||
| 1596 | <layout class="QVBoxLayout" name="buttonMiscHomeVerticalLayout"> | ||
| 1597 | <property name="spacing"> | ||
| 1598 | <number>3</number> | ||
| 1599 | </property> | ||
| 1600 | <property name="leftMargin"> | ||
| 1601 | <number>3</number> | ||
| 1602 | </property> | ||
| 1603 | <property name="topMargin"> | ||
| 1604 | <number>3</number> | ||
| 1605 | </property> | ||
| 1606 | <property name="rightMargin"> | ||
| 1607 | <number>3</number> | ||
| 1608 | </property> | ||
| 1609 | <property name="bottomMargin"> | ||
| 1610 | <number>3</number> | ||
| 1611 | </property> | ||
| 1612 | <item> | ||
| 1613 | <widget class="QPushButton" name="buttonHome"> | ||
| 1614 | <property name="minimumSize"> | ||
| 1615 | <size> | ||
| 1616 | <width>57</width> | ||
| 1617 | <height>0</height> | ||
| 1618 | </size> | ||
| 1619 | </property> | ||
| 1620 | <property name="maximumSize"> | ||
| 1621 | <size> | ||
| 1622 | <width>55</width> | ||
| 1623 | <height>16777215</height> | ||
| 1624 | </size> | ||
| 1625 | </property> | ||
| 1626 | <property name="styleSheet"> | ||
| 1627 | <string notr="true">min-width: 55px;</string> | ||
| 1628 | </property> | ||
| 1629 | <property name="text"> | ||
| 1630 | <string>Home</string> | ||
| 1631 | </property> | ||
| 1632 | </widget> | ||
| 1633 | </item> | ||
| 1634 | </layout> | ||
| 1635 | </widget> | ||
| 1636 | </item> | ||
| 1637 | </layout> | ||
| 1638 | </widget> | ||
| 1639 | </item> | ||
| 1640 | <item> | ||
| 1641 | <widget class="QWidget" name="horizontalSpacerShoulderButtonsWidget3" native="true"> | ||
| 1642 | <layout class="QHBoxLayout" name="horizontalSpacerShoulderButtonsWidget3Layout"> | ||
| 1643 | <property name="spacing"> | ||
| 1644 | <number>0</number> | ||
| 1645 | </property> | ||
| 1646 | <property name="leftMargin"> | ||
| 1647 | <number>0</number> | ||
| 1648 | </property> | ||
| 1649 | <property name="topMargin"> | ||
| 1650 | <number>0</number> | ||
| 1651 | </property> | ||
| 1652 | <property name="rightMargin"> | ||
| 1653 | <number>0</number> | ||
| 1654 | </property> | ||
| 1655 | <property name="bottomMargin"> | ||
| 1656 | <number>0</number> | ||
| 1657 | </property> | ||
| 1658 | <item> | ||
| 1659 | <spacer name="horizontalSpacerShoulderButtons2"> | ||
| 1660 | <property name="orientation"> | ||
| 1661 | <enum>Qt::Horizontal</enum> | ||
| 1662 | </property> | ||
| 1663 | <property name="sizeHint" stdset="0"> | ||
| 1664 | <size> | ||
| 1665 | <width>0</width> | ||
| 1666 | <height>20</height> | ||
| 1667 | </size> | ||
| 1668 | </property> | ||
| 1669 | </spacer> | ||
| 1670 | </item> | ||
| 1671 | </layout> | ||
| 1672 | </widget> | ||
| 1673 | </item> | ||
| 1674 | <item> | ||
| 1675 | <widget class="QWidget" name="buttonShoulderButtonsRight" native="true"> | ||
| 1676 | <layout class="QVBoxLayout" name="buttonShoulderButtonsRightVerticalLayout"> | ||
| 1677 | <property name="spacing"> | ||
| 1678 | <number>0</number> | ||
| 1679 | </property> | ||
| 1680 | <property name="leftMargin"> | ||
| 1681 | <number>0</number> | ||
| 1682 | </property> | ||
| 1683 | <property name="topMargin"> | ||
| 1684 | <number>0</number> | ||
| 1685 | </property> | ||
| 1686 | <property name="rightMargin"> | ||
| 1687 | <number>0</number> | ||
| 1688 | </property> | ||
| 1689 | <property name="bottomMargin"> | ||
| 1690 | <number>0</number> | ||
| 1691 | </property> | ||
| 1692 | <item> | ||
| 1693 | <widget class="QGroupBox" name="buttonShoulderButtonsRGroup"> | ||
| 1694 | <property name="title"> | ||
| 1695 | <string>R</string> | ||
| 1696 | </property> | ||
| 1697 | <property name="alignment"> | ||
| 1698 | <set>Qt::AlignCenter</set> | ||
| 1699 | </property> | ||
| 1700 | <layout class="QVBoxLayout" name="buttonShoulderButtonsRVerticalLayout"> | ||
| 1701 | <property name="spacing"> | ||
| 1702 | <number>3</number> | ||
| 1703 | </property> | ||
| 1704 | <property name="leftMargin"> | ||
| 1705 | <number>3</number> | ||
| 1706 | </property> | ||
| 1707 | <property name="topMargin"> | ||
| 1708 | <number>3</number> | ||
| 1709 | </property> | ||
| 1710 | <property name="rightMargin"> | ||
| 1711 | <number>3</number> | ||
| 1712 | </property> | ||
| 1713 | <property name="bottomMargin"> | ||
| 1714 | <number>3</number> | ||
| 1715 | </property> | ||
| 1716 | <item> | ||
| 1717 | <widget class="QPushButton" name="buttonR"> | ||
| 1718 | <property name="minimumSize"> | ||
| 1719 | <size> | ||
| 1720 | <width>57</width> | ||
| 1721 | <height>0</height> | ||
| 1722 | </size> | ||
| 1723 | </property> | ||
| 1724 | <property name="maximumSize"> | ||
| 1725 | <size> | ||
| 1726 | <width>55</width> | ||
| 1727 | <height>16777215</height> | ||
| 1728 | </size> | ||
| 1729 | </property> | ||
| 1730 | <property name="styleSheet"> | ||
| 1731 | <string notr="true">min-width: 55px;</string> | ||
| 1732 | </property> | ||
| 1733 | <property name="text"> | ||
| 1734 | <string>R</string> | ||
| 1735 | </property> | ||
| 1736 | </widget> | ||
| 1737 | </item> | ||
| 1738 | </layout> | ||
| 1739 | </widget> | ||
| 1740 | </item> | ||
| 1741 | <item> | ||
| 1742 | <widget class="QGroupBox" name="buttonShoulderButtonsZRGroup"> | ||
| 1743 | <property name="title"> | ||
| 1744 | <string>ZR</string> | ||
| 1745 | </property> | ||
| 1746 | <property name="alignment"> | ||
| 1747 | <set>Qt::AlignCenter</set> | ||
| 1748 | </property> | ||
| 1749 | <layout class="QVBoxLayout" name="buttonShoulderButtonsZRVerticalLayout"> | ||
| 1750 | <property name="spacing"> | ||
| 1751 | <number>3</number> | ||
| 1752 | </property> | ||
| 1753 | <property name="leftMargin"> | ||
| 1754 | <number>3</number> | ||
| 1755 | </property> | ||
| 1756 | <property name="topMargin"> | ||
| 1757 | <number>3</number> | ||
| 1758 | </property> | ||
| 1759 | <property name="rightMargin"> | ||
| 1760 | <number>3</number> | ||
| 1761 | </property> | ||
| 1762 | <property name="bottomMargin"> | ||
| 1763 | <number>3</number> | ||
| 1764 | </property> | ||
| 1765 | <item> | ||
| 1766 | <widget class="QPushButton" name="buttonZR"> | ||
| 1767 | <property name="minimumSize"> | ||
| 1768 | <size> | ||
| 1769 | <width>57</width> | ||
| 1770 | <height>0</height> | ||
| 1771 | </size> | ||
| 1772 | </property> | ||
| 1773 | <property name="maximumSize"> | ||
| 1774 | <size> | ||
| 1775 | <width>55</width> | ||
| 1776 | <height>16777215</height> | ||
| 1777 | </size> | ||
| 1778 | </property> | ||
| 1779 | <property name="styleSheet"> | ||
| 1780 | <string notr="true">min-width: 55px;</string> | ||
| 1781 | </property> | ||
| 1782 | <property name="text"> | ||
| 1783 | <string>ZR</string> | ||
| 1784 | </property> | ||
| 1785 | </widget> | ||
| 1786 | </item> | ||
| 1787 | </layout> | ||
| 1788 | </widget> | ||
| 1789 | </item> | ||
| 1790 | </layout> | ||
| 1791 | </widget> | ||
| 1792 | </item> | ||
| 1793 | <item> | ||
| 1794 | <widget class="QWidget" name="horizontalSpacerShoulderButtonsWidget2" native="true"> | ||
| 1795 | <layout class="QHBoxLayout" name="horizontalSpacerShoulderButtonsWidget2Layout"> | ||
| 1796 | <property name="spacing"> | ||
| 1797 | <number>0</number> | ||
| 1798 | </property> | ||
| 1799 | <property name="leftMargin"> | ||
| 1800 | <number>0</number> | ||
| 1801 | </property> | ||
| 1802 | <property name="topMargin"> | ||
| 1803 | <number>0</number> | ||
| 1804 | </property> | ||
| 1805 | <property name="rightMargin"> | ||
| 1806 | <number>0</number> | ||
| 1807 | </property> | ||
| 1808 | <property name="bottomMargin"> | ||
| 1809 | <number>0</number> | ||
| 1810 | </property> | ||
| 1811 | <item> | ||
| 1812 | <spacer name="horizontalSpacerShoulderButtons3"> | ||
| 1813 | <property name="orientation"> | ||
| 1814 | <enum>Qt::Horizontal</enum> | ||
| 1815 | </property> | ||
| 1816 | <property name="sizeHint" stdset="0"> | ||
| 1817 | <size> | ||
| 1818 | <width>0</width> | ||
| 1819 | <height>20</height> | ||
| 1820 | </size> | ||
| 1821 | </property> | ||
| 1822 | </spacer> | ||
| 1823 | </item> | ||
| 1824 | </layout> | ||
| 1825 | </widget> | ||
| 1826 | </item> | ||
| 1827 | <item> | ||
| 1828 | <widget class="QWidget" name="buttonShoulderButtonsSLSR" native="true"> | ||
| 1829 | <layout class="QVBoxLayout" name="buttonShoulderButtonsSLSRVerticalLayout"> | ||
| 1830 | <property name="spacing"> | ||
| 1831 | <number>0</number> | ||
| 1832 | </property> | ||
| 1833 | <property name="leftMargin"> | ||
| 1834 | <number>0</number> | ||
| 1835 | </property> | ||
| 1836 | <property name="topMargin"> | ||
| 1837 | <number>0</number> | ||
| 1838 | </property> | ||
| 1839 | <property name="rightMargin"> | ||
| 1840 | <number>0</number> | ||
| 1841 | </property> | ||
| 1842 | <property name="bottomMargin"> | ||
| 1843 | <number>0</number> | ||
| 1844 | </property> | ||
| 1845 | <item alignment="Qt::AlignHCenter"> | ||
| 1846 | <widget class="QGroupBox" name="buttonShoulderButtonsSLGroup"> | ||
| 1847 | <property name="title"> | ||
| 1848 | <string>SL</string> | ||
| 1849 | </property> | ||
| 1850 | <property name="alignment"> | ||
| 1851 | <set>Qt::AlignCenter</set> | ||
| 1852 | </property> | ||
| 1853 | <layout class="QVBoxLayout" name="buttonShoulderButtonsSLVerticalLayout"> | ||
| 1854 | <property name="spacing"> | ||
| 1855 | <number>3</number> | ||
| 1856 | </property> | ||
| 1857 | <property name="leftMargin"> | ||
| 1858 | <number>3</number> | ||
| 1859 | </property> | ||
| 1860 | <property name="topMargin"> | ||
| 1861 | <number>3</number> | ||
| 1862 | </property> | ||
| 1863 | <property name="rightMargin"> | ||
| 1864 | <number>3</number> | ||
| 1865 | </property> | ||
| 1866 | <property name="bottomMargin"> | ||
| 1867 | <number>3</number> | ||
| 1868 | </property> | ||
| 1869 | <item> | ||
| 1870 | <widget class="QPushButton" name="buttonSL"> | ||
| 1871 | <property name="minimumSize"> | ||
| 1872 | <size> | ||
| 1873 | <width>57</width> | ||
| 1874 | <height>0</height> | ||
| 1875 | </size> | ||
| 1876 | </property> | ||
| 1877 | <property name="maximumSize"> | ||
| 1878 | <size> | ||
| 1879 | <width>55</width> | ||
| 1880 | <height>16777215</height> | ||
| 1881 | </size> | ||
| 1882 | </property> | ||
| 1883 | <property name="styleSheet"> | ||
| 1884 | <string notr="true">min-width: 55px;</string> | ||
| 1885 | </property> | ||
| 1886 | <property name="text"> | ||
| 1887 | <string>SL</string> | ||
| 1888 | </property> | ||
| 1889 | </widget> | ||
| 1890 | </item> | ||
| 1891 | </layout> | ||
| 1892 | </widget> | ||
| 1893 | </item> | ||
| 1894 | <item alignment="Qt::AlignHCenter"> | ||
| 1895 | <widget class="QGroupBox" name="buttonShoulderButtonsSRGroup"> | ||
| 1896 | <property name="title"> | ||
| 1897 | <string>SR</string> | ||
| 1898 | </property> | ||
| 1899 | <property name="alignment"> | ||
| 1900 | <set>Qt::AlignCenter</set> | ||
| 1901 | </property> | ||
| 1902 | <layout class="QVBoxLayout" name="buttonShoulderButtonsSRVerticalLayout"> | ||
| 1903 | <property name="spacing"> | ||
| 1904 | <number>3</number> | ||
| 1905 | </property> | ||
| 1906 | <property name="leftMargin"> | ||
| 1907 | <number>3</number> | ||
| 1908 | </property> | ||
| 1909 | <property name="topMargin"> | ||
| 1910 | <number>3</number> | ||
| 1911 | </property> | ||
| 1912 | <property name="rightMargin"> | ||
| 1913 | <number>3</number> | ||
| 1914 | </property> | ||
| 1915 | <property name="bottomMargin"> | ||
| 1916 | <number>3</number> | ||
| 1917 | </property> | ||
| 1918 | <item> | ||
| 1919 | <widget class="QPushButton" name="buttonSR"> | ||
| 1920 | <property name="minimumSize"> | ||
| 1921 | <size> | ||
| 1922 | <width>57</width> | ||
| 1923 | <height>0</height> | ||
| 1924 | </size> | ||
| 1925 | </property> | ||
| 1926 | <property name="maximumSize"> | ||
| 1927 | <size> | ||
| 1928 | <width>55</width> | ||
| 1929 | <height>16777215</height> | ||
| 1930 | </size> | ||
| 1931 | </property> | ||
| 1932 | <property name="styleSheet"> | ||
| 1933 | <string notr="true">min-width: 55px;</string> | ||
| 1934 | </property> | ||
| 1935 | <property name="text"> | ||
| 1936 | <string>SR</string> | ||
| 1937 | </property> | ||
| 1938 | </widget> | ||
| 1939 | </item> | ||
| 1940 | </layout> | ||
| 1941 | </widget> | ||
| 1942 | </item> | ||
| 1943 | </layout> | ||
| 1944 | </widget> | ||
| 1945 | </item> | ||
| 1946 | </layout> | ||
| 1947 | </item> | ||
| 1948 | <item> | ||
| 1949 | <widget class="QFrame" name="controllerFrame"> | ||
| 1950 | <property name="sizePolicy"> | ||
| 1951 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 1952 | <horstretch>0</horstretch> | ||
| 1953 | <verstretch>0</verstretch> | ||
| 1954 | </sizepolicy> | ||
| 1955 | </property> | ||
| 1956 | <property name="font"> | ||
| 1957 | <font> | ||
| 1958 | <weight>75</weight> | ||
| 1959 | <bold>true</bold> | ||
| 1960 | </font> | ||
| 1961 | </property> | ||
| 1962 | <property name="styleSheet"> | ||
| 1963 | <string notr="true">image: url(:/controller/pro);</string> | ||
| 1964 | </property> | ||
| 1965 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 1966 | <property name="leftMargin"> | ||
| 1967 | <number>0</number> | ||
| 772 | </property> | 1968 | </property> |
| 773 | </widget> | 1969 | <property name="topMargin"> |
| 774 | </item> | 1970 | <number>0</number> |
| 775 | </layout> | ||
| 776 | </item> | ||
| 777 | <item> | ||
| 778 | <widget class="QPushButton" name="buttonLStick"> | ||
| 779 | <property name="text"> | ||
| 780 | <string/> | ||
| 781 | </property> | ||
| 782 | </widget> | ||
| 783 | </item> | ||
| 784 | </layout> | ||
| 785 | </item> | ||
| 786 | <item row="5" column="1" colspan="2"> | ||
| 787 | <layout class="QVBoxLayout" name="sliderLStickDeadzoneAndModifierVerticalLayout"> | ||
| 788 | <property name="sizeConstraint"> | ||
| 789 | <enum>QLayout::SetDefaultConstraint</enum> | ||
| 790 | </property> | ||
| 791 | <item> | ||
| 792 | <layout class="QHBoxLayout" name="sliderLStickDeadzoneAndModifierHorizontalLayout"> | ||
| 793 | <item> | ||
| 794 | <widget class="QLabel" name="labelLStickDeadzoneAndModifier"> | ||
| 795 | <property name="text"> | ||
| 796 | <string>Deadzone: 0</string> | ||
| 797 | </property> | 1971 | </property> |
| 798 | <property name="alignment"> | 1972 | <property name="rightMargin"> |
| 799 | <enum>Qt::AlignHCenter</enum> | 1973 | <number>0</number> |
| 800 | </property> | 1974 | </property> |
| 801 | </widget> | 1975 | <property name="bottomMargin"> |
| 802 | </item> | 1976 | <number>0</number> |
| 803 | </layout> | ||
| 804 | </item> | ||
| 805 | <item> | ||
| 806 | <widget class="QSlider" name="sliderLStickDeadzoneAndModifier"> | ||
| 807 | <property name="orientation"> | ||
| 808 | <enum>Qt::Horizontal</enum> | ||
| 809 | </property> | ||
| 810 | </widget> | ||
| 811 | </item> | ||
| 812 | </layout> | ||
| 813 | </item> | ||
| 814 | <item row="6" column="1"> | ||
| 815 | <spacer name="LStick_verticalSpacer"> | ||
| 816 | <property name="orientation"> | ||
| 817 | <enum>Qt::Vertical</enum> | ||
| 818 | </property> | ||
| 819 | <property name="sizeHint" stdset="0"> | ||
| 820 | <size> | ||
| 821 | <width>0</width> | ||
| 822 | <height>0</height> | ||
| 823 | </size> | ||
| 824 | </property> | ||
| 825 | </spacer> | ||
| 826 | </item> | ||
| 827 | </layout> | ||
| 828 | </widget> | ||
| 829 | </item> | ||
| 830 | <item row="3" column="0"> | ||
| 831 | <widget class="QGroupBox" name="shoulderButtons"> | ||
| 832 | <property name="title"> | ||
| 833 | <string>Shoulder Buttons</string> | ||
| 834 | </property> | ||
| 835 | <property name="flat"> | ||
| 836 | <bool>false</bool> | ||
| 837 | </property> | ||
| 838 | <property name="checkable"> | ||
| 839 | <bool>false</bool> | ||
| 840 | </property> | ||
| 841 | <layout class="QGridLayout" name="gridLayout_3"> | ||
| 842 | <item row="0" column="0"> | ||
| 843 | <layout class="QVBoxLayout" name="buttonShoulderButtonsLVerticalLayout"> | ||
| 844 | <item> | ||
| 845 | <layout class="QHBoxLayout" name="buttonShoulderButtonsLHorizontalLayout"> | ||
| 846 | <item> | ||
| 847 | <widget class="QLabel" name="labelL"> | ||
| 848 | <property name="text"> | ||
| 849 | <string>L:</string> | ||
| 850 | </property> | 1977 | </property> |
| 851 | </widget> | 1978 | </layout> |
| 852 | </item> | 1979 | </widget> |
| 853 | </layout> | 1980 | </item> |
| 854 | </item> | 1981 | <item> |
| 855 | <item> | 1982 | <layout class="QHBoxLayout" name="miscButtons"> |
| 856 | <widget class="QPushButton" name="buttonL"> | 1983 | <property name="spacing"> |
| 857 | <property name="text"> | 1984 | <number>3</number> |
| 858 | <string/> | 1985 | </property> |
| 859 | </property> | 1986 | <item> |
| 860 | </widget> | 1987 | <spacer name="horizontalSpacerMiscButtons1"> |
| 861 | </item> | 1988 | <property name="orientation"> |
| 862 | </layout> | 1989 | <enum>Qt::Horizontal</enum> |
| 1990 | </property> | ||
| 1991 | <property name="sizeHint" stdset="0"> | ||
| 1992 | <size> | ||
| 1993 | <width>40</width> | ||
| 1994 | <height>0</height> | ||
| 1995 | </size> | ||
| 1996 | </property> | ||
| 1997 | </spacer> | ||
| 1998 | </item> | ||
| 1999 | <item> | ||
| 2000 | <spacer name="horizontalSpacerMiscButtons4"> | ||
| 2001 | <property name="orientation"> | ||
| 2002 | <enum>Qt::Horizontal</enum> | ||
| 2003 | </property> | ||
| 2004 | <property name="sizeHint" stdset="0"> | ||
| 2005 | <size> | ||
| 2006 | <width>40</width> | ||
| 2007 | <height>0</height> | ||
| 2008 | </size> | ||
| 2009 | </property> | ||
| 2010 | </spacer> | ||
| 2011 | </item> | ||
| 2012 | </layout> | ||
| 2013 | </item> | ||
| 2014 | </layout> | ||
| 2015 | </widget> | ||
| 863 | </item> | 2016 | </item> |
| 864 | <item row="0" column="1"> | 2017 | <item> |
| 865 | <layout class="QVBoxLayout" name="buttonShoulderButtonsRVerticalLayout"> | 2018 | <widget class="QWidget" name="bottomRight" native="true"> |
| 866 | <item> | 2019 | <layout class="QVBoxLayout" name="bottomRightLayout"> |
| 867 | <layout class="QHBoxLayout" name="buttonShoulderButtonsRHorizontalLayout"> | 2020 | <property name="spacing"> |
| 868 | <item> | 2021 | <number>0</number> |
| 869 | <widget class="QLabel" name="labelR"> | 2022 | </property> |
| 870 | <property name="text"> | 2023 | <property name="leftMargin"> |
| 871 | <string>R:</string> | 2024 | <number>0</number> |
| 2025 | </property> | ||
| 2026 | <property name="topMargin"> | ||
| 2027 | <number>0</number> | ||
| 2028 | </property> | ||
| 2029 | <property name="rightMargin"> | ||
| 2030 | <number>0</number> | ||
| 2031 | </property> | ||
| 2032 | <property name="bottomMargin"> | ||
| 2033 | <number>0</number> | ||
| 2034 | </property> | ||
| 2035 | <item> | ||
| 2036 | <widget class="QGroupBox" name="faceButtons"> | ||
| 2037 | <property name="sizePolicy"> | ||
| 2038 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2039 | <horstretch>0</horstretch> | ||
| 2040 | <verstretch>0</verstretch> | ||
| 2041 | </sizepolicy> | ||
| 2042 | </property> | ||
| 2043 | <property name="title"> | ||
| 2044 | <string>Face Buttons</string> | ||
| 2045 | </property> | ||
| 2046 | <property name="flat"> | ||
| 2047 | <bool>false</bool> | ||
| 2048 | </property> | ||
| 2049 | <property name="checkable"> | ||
| 2050 | <bool>false</bool> | ||
| 2051 | </property> | ||
| 2052 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 2053 | <property name="spacing"> | ||
| 2054 | <number>0</number> | ||
| 872 | </property> | 2055 | </property> |
| 873 | </widget> | 2056 | <property name="leftMargin"> |
| 874 | </item> | 2057 | <number>3</number> |
| 875 | </layout> | ||
| 876 | </item> | ||
| 877 | <item> | ||
| 878 | <widget class="QPushButton" name="buttonR"> | ||
| 879 | <property name="text"> | ||
| 880 | <string/> | ||
| 881 | </property> | ||
| 882 | </widget> | ||
| 883 | </item> | ||
| 884 | </layout> | ||
| 885 | </item> | ||
| 886 | <item row="1" column="0"> | ||
| 887 | <layout class="QVBoxLayout" name="buttonShoulderButtonsZLVerticalLayout"> | ||
| 888 | <item> | ||
| 889 | <layout class="QHBoxLayout" name="buttonShoulderButtonsZLHorizontalLayout"> | ||
| 890 | <item> | ||
| 891 | <widget class="QLabel" name="labelZL"> | ||
| 892 | <property name="text"> | ||
| 893 | <string>ZL:</string> | ||
| 894 | </property> | 2058 | </property> |
| 895 | </widget> | 2059 | <property name="topMargin"> |
| 896 | </item> | 2060 | <number>0</number> |
| 897 | </layout> | ||
| 898 | </item> | ||
| 899 | <item> | ||
| 900 | <widget class="QPushButton" name="buttonZL"> | ||
| 901 | <property name="text"> | ||
| 902 | <string/> | ||
| 903 | </property> | ||
| 904 | </widget> | ||
| 905 | </item> | ||
| 906 | </layout> | ||
| 907 | </item> | ||
| 908 | <item row="1" column="1"> | ||
| 909 | <layout class="QVBoxLayout" name="buttonShoulderButtonsZRVerticalLayout"> | ||
| 910 | <item> | ||
| 911 | <layout class="QHBoxLayout" name="buttonShoulderButtonsZRHorizontalLayout"> | ||
| 912 | <item> | ||
| 913 | <widget class="QLabel" name="labelZR"> | ||
| 914 | <property name="text"> | ||
| 915 | <string>ZR:</string> | ||
| 916 | </property> | 2061 | </property> |
| 917 | </widget> | 2062 | <property name="rightMargin"> |
| 918 | </item> | 2063 | <number>3</number> |
| 919 | </layout> | ||
| 920 | </item> | ||
| 921 | <item> | ||
| 922 | <widget class="QPushButton" name="buttonZR"> | ||
| 923 | <property name="text"> | ||
| 924 | <string/> | ||
| 925 | </property> | ||
| 926 | </widget> | ||
| 927 | </item> | ||
| 928 | </layout> | ||
| 929 | </item> | ||
| 930 | <item row="0" column="2"> | ||
| 931 | <layout class="QVBoxLayout" name="buttonShoulderButtonsSLVerticalLayout"> | ||
| 932 | <item> | ||
| 933 | <layout class="QHBoxLayout" name="buttonShoulderButtonsSLHorizontalLayout"> | ||
| 934 | <item> | ||
| 935 | <widget class="QLabel" name="labelSL"> | ||
| 936 | <property name="text"> | ||
| 937 | <string>SL:</string> | ||
| 938 | </property> | 2064 | </property> |
| 939 | </widget> | 2065 | <property name="bottomMargin"> |
| 940 | </item> | 2066 | <number>3</number> |
| 941 | </layout> | ||
| 942 | </item> | ||
| 943 | <item> | ||
| 944 | <widget class="QPushButton" name="buttonSL"> | ||
| 945 | <property name="text"> | ||
| 946 | <string/> | ||
| 947 | </property> | ||
| 948 | </widget> | ||
| 949 | </item> | ||
| 950 | </layout> | ||
| 951 | </item> | ||
| 952 | <item row="1" column="2"> | ||
| 953 | <layout class="QVBoxLayout" name="buttonShoulderButtonsSRVerticalLayout"> | ||
| 954 | <item> | ||
| 955 | <layout class="QHBoxLayout" name="buttonShoulderButtonsSRHorizontalLayout"> | ||
| 956 | <item> | ||
| 957 | <widget class="QLabel" name="labelSR"> | ||
| 958 | <property name="text"> | ||
| 959 | <string>SR:</string> | ||
| 960 | </property> | 2067 | </property> |
| 961 | </widget> | 2068 | <item> |
| 962 | </item> | 2069 | <widget class="QWidget" name="buttonFaceButtonsBWidget" native="true"> |
| 963 | </layout> | 2070 | <layout class="QHBoxLayout" name="horizontalLayout_6"> |
| 964 | </item> | 2071 | <property name="spacing"> |
| 965 | <item> | 2072 | <number>0</number> |
| 966 | <widget class="QPushButton" name="buttonSR"> | 2073 | </property> |
| 967 | <property name="text"> | 2074 | <property name="leftMargin"> |
| 968 | <string/> | 2075 | <number>0</number> |
| 969 | </property> | 2076 | </property> |
| 970 | </widget> | 2077 | <property name="topMargin"> |
| 971 | </item> | 2078 | <number>0</number> |
| 972 | </layout> | 2079 | </property> |
| 973 | </item> | 2080 | <property name="rightMargin"> |
| 974 | </layout> | 2081 | <number>0</number> |
| 975 | </widget> | 2082 | </property> |
| 976 | </item> | 2083 | <property name="bottomMargin"> |
| 977 | <item row="3" column="1"> | 2084 | <number>0</number> |
| 978 | <widget class="QGroupBox" name="misc"> | 2085 | </property> |
| 979 | <property name="title"> | 2086 | <item> |
| 980 | <string>Misc.</string> | 2087 | <spacer name="horizontalSpacerBLeft"> |
| 981 | </property> | 2088 | <property name="orientation"> |
| 982 | <property name="flat"> | 2089 | <enum>Qt::Horizontal</enum> |
| 983 | <bool>false</bool> | 2090 | </property> |
| 984 | </property> | 2091 | <property name="sizeHint" stdset="0"> |
| 985 | <property name="checkable"> | 2092 | <size> |
| 986 | <bool>false</bool> | 2093 | <width>20</width> |
| 987 | </property> | 2094 | <height>20</height> |
| 988 | <layout class="QGridLayout" name="gridLayout_6"> | 2095 | </size> |
| 989 | <item row="1" column="0"> | 2096 | </property> |
| 990 | <layout class="QVBoxLayout" name="buttonMiscMinusVerticalLayout"> | 2097 | </spacer> |
| 991 | <item> | 2098 | </item> |
| 992 | <layout class="QHBoxLayout" name="buttonMiscMinusHorizontalLayout"> | 2099 | <item alignment="Qt::AlignHCenter"> |
| 993 | <item> | 2100 | <widget class="QGroupBox" name="buttonFaceButtonsXGroup"> |
| 994 | <widget class="QLabel" name="labelMinus"> | 2101 | <property name="title"> |
| 995 | <property name="text"> | 2102 | <string>X</string> |
| 996 | <string>Minus:</string> | 2103 | </property> |
| 2104 | <property name="alignment"> | ||
| 2105 | <set>Qt::AlignCenter</set> | ||
| 2106 | </property> | ||
| 2107 | <layout class="QVBoxLayout" name="buttonFaceButtonsXVerticalLayout"> | ||
| 2108 | <property name="spacing"> | ||
| 2109 | <number>3</number> | ||
| 2110 | </property> | ||
| 2111 | <property name="leftMargin"> | ||
| 2112 | <number>3</number> | ||
| 2113 | </property> | ||
| 2114 | <property name="topMargin"> | ||
| 2115 | <number>3</number> | ||
| 2116 | </property> | ||
| 2117 | <property name="rightMargin"> | ||
| 2118 | <number>3</number> | ||
| 2119 | </property> | ||
| 2120 | <property name="bottomMargin"> | ||
| 2121 | <number>3</number> | ||
| 2122 | </property> | ||
| 2123 | <item> | ||
| 2124 | <widget class="QPushButton" name="buttonX"> | ||
| 2125 | <property name="minimumSize"> | ||
| 2126 | <size> | ||
| 2127 | <width>57</width> | ||
| 2128 | <height>0</height> | ||
| 2129 | </size> | ||
| 2130 | </property> | ||
| 2131 | <property name="maximumSize"> | ||
| 2132 | <size> | ||
| 2133 | <width>55</width> | ||
| 2134 | <height>16777215</height> | ||
| 2135 | </size> | ||
| 2136 | </property> | ||
| 2137 | <property name="styleSheet"> | ||
| 2138 | <string notr="true">min-width: 55px;</string> | ||
| 2139 | </property> | ||
| 2140 | <property name="text"> | ||
| 2141 | <string>X</string> | ||
| 2142 | </property> | ||
| 2143 | </widget> | ||
| 2144 | </item> | ||
| 2145 | </layout> | ||
| 2146 | </widget> | ||
| 2147 | </item> | ||
| 2148 | <item> | ||
| 2149 | <spacer name="horizontalSpacerBRight"> | ||
| 2150 | <property name="orientation"> | ||
| 2151 | <enum>Qt::Horizontal</enum> | ||
| 2152 | </property> | ||
| 2153 | <property name="sizeHint" stdset="0"> | ||
| 2154 | <size> | ||
| 2155 | <width>20</width> | ||
| 2156 | <height>20</height> | ||
| 2157 | </size> | ||
| 2158 | </property> | ||
| 2159 | </spacer> | ||
| 2160 | </item> | ||
| 2161 | </layout> | ||
| 2162 | </widget> | ||
| 2163 | </item> | ||
| 2164 | <item> | ||
| 2165 | <layout class="QHBoxLayout" name="buttonFaceButtonsYAHorizontalLayout"> | ||
| 2166 | <property name="spacing"> | ||
| 2167 | <number>3</number> | ||
| 2168 | </property> | ||
| 2169 | <item alignment="Qt::AlignHCenter"> | ||
| 2170 | <widget class="QGroupBox" name="buttonFaceButtonsYGroup"> | ||
| 2171 | <property name="title"> | ||
| 2172 | <string>Y</string> | ||
| 2173 | </property> | ||
| 2174 | <property name="alignment"> | ||
| 2175 | <set>Qt::AlignCenter</set> | ||
| 2176 | </property> | ||
| 2177 | <layout class="QVBoxLayout" name="buttonFaceButtonsYVerticalLayout"> | ||
| 2178 | <property name="spacing"> | ||
| 2179 | <number>3</number> | ||
| 2180 | </property> | ||
| 2181 | <property name="leftMargin"> | ||
| 2182 | <number>3</number> | ||
| 2183 | </property> | ||
| 2184 | <property name="topMargin"> | ||
| 2185 | <number>3</number> | ||
| 2186 | </property> | ||
| 2187 | <property name="rightMargin"> | ||
| 2188 | <number>3</number> | ||
| 2189 | </property> | ||
| 2190 | <property name="bottomMargin"> | ||
| 2191 | <number>3</number> | ||
| 2192 | </property> | ||
| 2193 | <item> | ||
| 2194 | <widget class="QPushButton" name="buttonY"> | ||
| 2195 | <property name="minimumSize"> | ||
| 2196 | <size> | ||
| 2197 | <width>57</width> | ||
| 2198 | <height>0</height> | ||
| 2199 | </size> | ||
| 2200 | </property> | ||
| 2201 | <property name="maximumSize"> | ||
| 2202 | <size> | ||
| 2203 | <width>55</width> | ||
| 2204 | <height>16777215</height> | ||
| 2205 | </size> | ||
| 2206 | </property> | ||
| 2207 | <property name="styleSheet"> | ||
| 2208 | <string notr="true">min-width: 55px;</string> | ||
| 2209 | </property> | ||
| 2210 | <property name="text"> | ||
| 2211 | <string>Y</string> | ||
| 2212 | </property> | ||
| 2213 | </widget> | ||
| 2214 | </item> | ||
| 2215 | </layout> | ||
| 2216 | </widget> | ||
| 2217 | </item> | ||
| 2218 | <item alignment="Qt::AlignHCenter"> | ||
| 2219 | <widget class="QGroupBox" name="buttonFaceButtonsAGroup"> | ||
| 2220 | <property name="title"> | ||
| 2221 | <string>A</string> | ||
| 2222 | </property> | ||
| 2223 | <property name="alignment"> | ||
| 2224 | <set>Qt::AlignCenter</set> | ||
| 2225 | </property> | ||
| 2226 | <layout class="QVBoxLayout" name="buttonFaceButtonsAVerticalLayout"> | ||
| 2227 | <property name="spacing"> | ||
| 2228 | <number>3</number> | ||
| 2229 | </property> | ||
| 2230 | <property name="leftMargin"> | ||
| 2231 | <number>3</number> | ||
| 2232 | </property> | ||
| 2233 | <property name="topMargin"> | ||
| 2234 | <number>3</number> | ||
| 2235 | </property> | ||
| 2236 | <property name="rightMargin"> | ||
| 2237 | <number>3</number> | ||
| 2238 | </property> | ||
| 2239 | <property name="bottomMargin"> | ||
| 2240 | <number>3</number> | ||
| 2241 | </property> | ||
| 2242 | <item> | ||
| 2243 | <widget class="QPushButton" name="buttonA"> | ||
| 2244 | <property name="minimumSize"> | ||
| 2245 | <size> | ||
| 2246 | <width>57</width> | ||
| 2247 | <height>0</height> | ||
| 2248 | </size> | ||
| 2249 | </property> | ||
| 2250 | <property name="maximumSize"> | ||
| 2251 | <size> | ||
| 2252 | <width>55</width> | ||
| 2253 | <height>16777215</height> | ||
| 2254 | </size> | ||
| 2255 | </property> | ||
| 2256 | <property name="styleSheet"> | ||
| 2257 | <string notr="true">min-width: 55px;</string> | ||
| 2258 | </property> | ||
| 2259 | <property name="text"> | ||
| 2260 | <string>A</string> | ||
| 2261 | </property> | ||
| 2262 | </widget> | ||
| 2263 | </item> | ||
| 2264 | </layout> | ||
| 2265 | </widget> | ||
| 2266 | </item> | ||
| 2267 | </layout> | ||
| 2268 | </item> | ||
| 2269 | <item> | ||
| 2270 | <widget class="QWidget" name="buttonFaceButtonsXWidget" native="true"> | ||
| 2271 | <layout class="QHBoxLayout" name="horizontalLayout_10"> | ||
| 2272 | <property name="spacing"> | ||
| 2273 | <number>0</number> | ||
| 2274 | </property> | ||
| 2275 | <property name="leftMargin"> | ||
| 2276 | <number>0</number> | ||
| 2277 | </property> | ||
| 2278 | <property name="topMargin"> | ||
| 2279 | <number>0</number> | ||
| 2280 | </property> | ||
| 2281 | <property name="rightMargin"> | ||
| 2282 | <number>0</number> | ||
| 2283 | </property> | ||
| 2284 | <property name="bottomMargin"> | ||
| 2285 | <number>0</number> | ||
| 2286 | </property> | ||
| 2287 | <item> | ||
| 2288 | <spacer name="horizontalSpacerXLeft"> | ||
| 2289 | <property name="orientation"> | ||
| 2290 | <enum>Qt::Horizontal</enum> | ||
| 2291 | </property> | ||
| 2292 | <property name="sizeHint" stdset="0"> | ||
| 2293 | <size> | ||
| 2294 | <width>20</width> | ||
| 2295 | <height>20</height> | ||
| 2296 | </size> | ||
| 2297 | </property> | ||
| 2298 | </spacer> | ||
| 2299 | </item> | ||
| 2300 | <item alignment="Qt::AlignHCenter"> | ||
| 2301 | <widget class="QGroupBox" name="buttonFaceButtonsBWidget_2"> | ||
| 2302 | <property name="title"> | ||
| 2303 | <string>B</string> | ||
| 2304 | </property> | ||
| 2305 | <property name="alignment"> | ||
| 2306 | <set>Qt::AlignCenter</set> | ||
| 2307 | </property> | ||
| 2308 | <layout class="QVBoxLayout" name="buttonFaceButtonsBVerticalLayout"> | ||
| 2309 | <property name="spacing"> | ||
| 2310 | <number>3</number> | ||
| 2311 | </property> | ||
| 2312 | <property name="leftMargin"> | ||
| 2313 | <number>3</number> | ||
| 2314 | </property> | ||
| 2315 | <property name="topMargin"> | ||
| 2316 | <number>3</number> | ||
| 2317 | </property> | ||
| 2318 | <property name="rightMargin"> | ||
| 2319 | <number>3</number> | ||
| 2320 | </property> | ||
| 2321 | <property name="bottomMargin"> | ||
| 2322 | <number>3</number> | ||
| 2323 | </property> | ||
| 2324 | <item> | ||
| 2325 | <widget class="QPushButton" name="buttonB"> | ||
| 2326 | <property name="minimumSize"> | ||
| 2327 | <size> | ||
| 2328 | <width>57</width> | ||
| 2329 | <height>0</height> | ||
| 2330 | </size> | ||
| 2331 | </property> | ||
| 2332 | <property name="maximumSize"> | ||
| 2333 | <size> | ||
| 2334 | <width>55</width> | ||
| 2335 | <height>16777215</height> | ||
| 2336 | </size> | ||
| 2337 | </property> | ||
| 2338 | <property name="styleSheet"> | ||
| 2339 | <string notr="true">min-width: 55px;</string> | ||
| 2340 | </property> | ||
| 2341 | <property name="text"> | ||
| 2342 | <string>B</string> | ||
| 2343 | </property> | ||
| 2344 | </widget> | ||
| 2345 | </item> | ||
| 2346 | </layout> | ||
| 2347 | </widget> | ||
| 2348 | </item> | ||
| 2349 | <item> | ||
| 2350 | <spacer name="horizontalSpacerXRight"> | ||
| 2351 | <property name="orientation"> | ||
| 2352 | <enum>Qt::Horizontal</enum> | ||
| 2353 | </property> | ||
| 2354 | <property name="sizeHint" stdset="0"> | ||
| 2355 | <size> | ||
| 2356 | <width>20</width> | ||
| 2357 | <height>20</height> | ||
| 2358 | </size> | ||
| 2359 | </property> | ||
| 2360 | </spacer> | ||
| 2361 | </item> | ||
| 2362 | </layout> | ||
| 2363 | </widget> | ||
| 2364 | </item> | ||
| 2365 | </layout> | ||
| 2366 | </widget> | ||
| 2367 | </item> | ||
| 2368 | <item> | ||
| 2369 | <spacer name="verticalSpacerBottomRight"> | ||
| 2370 | <property name="orientation"> | ||
| 2371 | <enum>Qt::Vertical</enum> | ||
| 2372 | </property> | ||
| 2373 | <property name="sizeHint" stdset="0"> | ||
| 2374 | <size> | ||
| 2375 | <width>20</width> | ||
| 2376 | <height>0</height> | ||
| 2377 | </size> | ||
| 2378 | </property> | ||
| 2379 | </spacer> | ||
| 2380 | </item> | ||
| 2381 | <item> | ||
| 2382 | <widget class="QGroupBox" name="RStick"> | ||
| 2383 | <property name="sizePolicy"> | ||
| 2384 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 2385 | <horstretch>0</horstretch> | ||
| 2386 | <verstretch>0</verstretch> | ||
| 2387 | </sizepolicy> | ||
| 2388 | </property> | ||
| 2389 | <property name="title"> | ||
| 2390 | <string>Right Stick</string> | ||
| 2391 | </property> | ||
| 2392 | <property name="alignment"> | ||
| 2393 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> | ||
| 2394 | </property> | ||
| 2395 | <property name="flat"> | ||
| 2396 | <bool>false</bool> | ||
| 2397 | </property> | ||
| 2398 | <property name="checkable"> | ||
| 2399 | <bool>false</bool> | ||
| 2400 | </property> | ||
| 2401 | <layout class="QVBoxLayout" name="verticalLayout_2"> | ||
| 2402 | <property name="spacing"> | ||
| 2403 | <number>0</number> | ||
| 997 | </property> | 2404 | </property> |
| 998 | </widget> | 2405 | <property name="leftMargin"> |
| 999 | </item> | 2406 | <number>3</number> |
| 1000 | </layout> | ||
| 1001 | </item> | ||
| 1002 | <item> | ||
| 1003 | <widget class="QPushButton" name="buttonMinus"> | ||
| 1004 | <property name="text"> | ||
| 1005 | <string/> | ||
| 1006 | </property> | ||
| 1007 | </widget> | ||
| 1008 | </item> | ||
| 1009 | </layout> | ||
| 1010 | </item> | ||
| 1011 | <item row="3" column="1"> | ||
| 1012 | <spacer name="verticalSpacer_2"> | ||
| 1013 | <property name="orientation"> | ||
| 1014 | <enum>Qt::Vertical</enum> | ||
| 1015 | </property> | ||
| 1016 | <property name="sizeHint" stdset="0"> | ||
| 1017 | <size> | ||
| 1018 | <width>20</width> | ||
| 1019 | <height>40</height> | ||
| 1020 | </size> | ||
| 1021 | </property> | ||
| 1022 | </spacer> | ||
| 1023 | </item> | ||
| 1024 | <item row="0" column="0"> | ||
| 1025 | <layout class="QVBoxLayout" name="buttonMiscPlusVerticalLayout"> | ||
| 1026 | <item> | ||
| 1027 | <layout class="QHBoxLayout" name="buttonMiscPlusHorizontalLayout"> | ||
| 1028 | <item> | ||
| 1029 | <widget class="QLabel" name="labelPlus"> | ||
| 1030 | <property name="text"> | ||
| 1031 | <string>Plus:</string> | ||
| 1032 | </property> | 2407 | </property> |
| 1033 | </widget> | 2408 | <property name="topMargin"> |
| 1034 | </item> | 2409 | <number>0</number> |
| 1035 | </layout> | ||
| 1036 | </item> | ||
| 1037 | <item> | ||
| 1038 | <widget class="QPushButton" name="buttonPlus"> | ||
| 1039 | <property name="text"> | ||
| 1040 | <string/> | ||
| 1041 | </property> | ||
| 1042 | </widget> | ||
| 1043 | </item> | ||
| 1044 | </layout> | ||
| 1045 | </item> | ||
| 1046 | <item row="0" column="1"> | ||
| 1047 | <layout class="QVBoxLayout" name="buttonMiscHomeVerticalLayout"> | ||
| 1048 | <item> | ||
| 1049 | <layout class="QHBoxLayout" name="buttonMiscHomeHorizontalLayout"> | ||
| 1050 | <item> | ||
| 1051 | <widget class="QLabel" name="labelHome"> | ||
| 1052 | <property name="text"> | ||
| 1053 | <string>Home:</string> | ||
| 1054 | </property> | 2410 | </property> |
| 1055 | </widget> | 2411 | <property name="rightMargin"> |
| 1056 | </item> | 2412 | <number>3</number> |
| 1057 | </layout> | ||
| 1058 | </item> | ||
| 1059 | <item> | ||
| 1060 | <widget class="QPushButton" name="buttonHome"> | ||
| 1061 | <property name="text"> | ||
| 1062 | <string/> | ||
| 1063 | </property> | ||
| 1064 | </widget> | ||
| 1065 | </item> | ||
| 1066 | </layout> | ||
| 1067 | </item> | ||
| 1068 | <item row="1" column="1"> | ||
| 1069 | <layout class="QVBoxLayout" name="buttonMiscScrCapVerticalLayout"> | ||
| 1070 | <item> | ||
| 1071 | <layout class="QHBoxLayout" name="buttonMiscScrCapHorizontalLayout"> | ||
| 1072 | <item> | ||
| 1073 | <widget class="QLabel" name="labelScreenshot"> | ||
| 1074 | <property name="text"> | ||
| 1075 | <string>Screen Capture:</string> | ||
| 1076 | </property> | 2413 | </property> |
| 1077 | <property name="wordWrap"> | 2414 | <property name="bottomMargin"> |
| 1078 | <bool>false</bool> | 2415 | <number>0</number> |
| 1079 | </property> | 2416 | </property> |
| 1080 | </widget> | 2417 | <item> |
| 1081 | </item> | 2418 | <widget class="QWidget" name="buttonRStickUpWidget" native="true"> |
| 1082 | </layout> | 2419 | <property name="minimumSize"> |
| 1083 | </item> | 2420 | <size> |
| 1084 | <item> | 2421 | <width>0</width> |
| 1085 | <widget class="QPushButton" name="buttonScreenshot"> | 2422 | <height>0</height> |
| 1086 | <property name="sizePolicy"> | 2423 | </size> |
| 1087 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 2424 | </property> |
| 1088 | <horstretch>0</horstretch> | 2425 | <layout class="QHBoxLayout" name="horizontalLayout_9"> |
| 1089 | <verstretch>0</verstretch> | 2426 | <property name="spacing"> |
| 1090 | </sizepolicy> | 2427 | <number>0</number> |
| 1091 | </property> | 2428 | </property> |
| 1092 | <property name="maximumSize"> | 2429 | <property name="leftMargin"> |
| 1093 | <size> | 2430 | <number>0</number> |
| 1094 | <width>80</width> | 2431 | </property> |
| 1095 | <height>16777215</height> | 2432 | <property name="topMargin"> |
| 1096 | </size> | 2433 | <number>0</number> |
| 1097 | </property> | 2434 | </property> |
| 1098 | <property name="text"> | 2435 | <property name="rightMargin"> |
| 1099 | <string/> | 2436 | <number>0</number> |
| 1100 | </property> | 2437 | </property> |
| 1101 | </widget> | 2438 | <property name="bottomMargin"> |
| 1102 | </item> | 2439 | <number>0</number> |
| 1103 | </layout> | 2440 | </property> |
| 2441 | <item> | ||
| 2442 | <spacer name="horizontalSpacerRStickUpLeft"> | ||
| 2443 | <property name="orientation"> | ||
| 2444 | <enum>Qt::Horizontal</enum> | ||
| 2445 | </property> | ||
| 2446 | <property name="sizeHint" stdset="0"> | ||
| 2447 | <size> | ||
| 2448 | <width>20</width> | ||
| 2449 | <height>20</height> | ||
| 2450 | </size> | ||
| 2451 | </property> | ||
| 2452 | </spacer> | ||
| 2453 | </item> | ||
| 2454 | <item alignment="Qt::AlignHCenter"> | ||
| 2455 | <widget class="QGroupBox" name="buttonRStickUpGroup"> | ||
| 2456 | <property name="title"> | ||
| 2457 | <string>Up</string> | ||
| 2458 | </property> | ||
| 2459 | <property name="alignment"> | ||
| 2460 | <set>Qt::AlignCenter</set> | ||
| 2461 | </property> | ||
| 2462 | <layout class="QVBoxLayout" name="buttonRStickUpVerticalLayout"> | ||
| 2463 | <property name="spacing"> | ||
| 2464 | <number>3</number> | ||
| 2465 | </property> | ||
| 2466 | <property name="leftMargin"> | ||
| 2467 | <number>3</number> | ||
| 2468 | </property> | ||
| 2469 | <property name="topMargin"> | ||
| 2470 | <number>3</number> | ||
| 2471 | </property> | ||
| 2472 | <property name="rightMargin"> | ||
| 2473 | <number>3</number> | ||
| 2474 | </property> | ||
| 2475 | <property name="bottomMargin"> | ||
| 2476 | <number>3</number> | ||
| 2477 | </property> | ||
| 2478 | <item> | ||
| 2479 | <widget class="QPushButton" name="buttonRStickUp"> | ||
| 2480 | <property name="minimumSize"> | ||
| 2481 | <size> | ||
| 2482 | <width>57</width> | ||
| 2483 | <height>0</height> | ||
| 2484 | </size> | ||
| 2485 | </property> | ||
| 2486 | <property name="maximumSize"> | ||
| 2487 | <size> | ||
| 2488 | <width>55</width> | ||
| 2489 | <height>16777215</height> | ||
| 2490 | </size> | ||
| 2491 | </property> | ||
| 2492 | <property name="styleSheet"> | ||
| 2493 | <string notr="true">min-width: 55px;</string> | ||
| 2494 | </property> | ||
| 2495 | <property name="text"> | ||
| 2496 | <string>Up</string> | ||
| 2497 | </property> | ||
| 2498 | </widget> | ||
| 2499 | </item> | ||
| 2500 | </layout> | ||
| 2501 | </widget> | ||
| 2502 | </item> | ||
| 2503 | <item> | ||
| 2504 | <spacer name="horizontalSpacerRStickUpRight"> | ||
| 2505 | <property name="orientation"> | ||
| 2506 | <enum>Qt::Horizontal</enum> | ||
| 2507 | </property> | ||
| 2508 | <property name="sizeHint" stdset="0"> | ||
| 2509 | <size> | ||
| 2510 | <width>20</width> | ||
| 2511 | <height>20</height> | ||
| 2512 | </size> | ||
| 2513 | </property> | ||
| 2514 | </spacer> | ||
| 2515 | </item> | ||
| 2516 | </layout> | ||
| 2517 | </widget> | ||
| 2518 | </item> | ||
| 2519 | <item> | ||
| 2520 | <layout class="QHBoxLayout" name="buttonRStickLeftRightHorizontalLayout"> | ||
| 2521 | <property name="spacing"> | ||
| 2522 | <number>3</number> | ||
| 2523 | </property> | ||
| 2524 | <item alignment="Qt::AlignHCenter"> | ||
| 2525 | <widget class="QGroupBox" name="buttonRStickLeftGroup"> | ||
| 2526 | <property name="title"> | ||
| 2527 | <string>Left</string> | ||
| 2528 | </property> | ||
| 2529 | <property name="alignment"> | ||
| 2530 | <set>Qt::AlignCenter</set> | ||
| 2531 | </property> | ||
| 2532 | <layout class="QVBoxLayout" name="buttonRStickLeftVerticalLayout"> | ||
| 2533 | <property name="spacing"> | ||
| 2534 | <number>3</number> | ||
| 2535 | </property> | ||
| 2536 | <property name="leftMargin"> | ||
| 2537 | <number>3</number> | ||
| 2538 | </property> | ||
| 2539 | <property name="topMargin"> | ||
| 2540 | <number>3</number> | ||
| 2541 | </property> | ||
| 2542 | <property name="rightMargin"> | ||
| 2543 | <number>3</number> | ||
| 2544 | </property> | ||
| 2545 | <property name="bottomMargin"> | ||
| 2546 | <number>3</number> | ||
| 2547 | </property> | ||
| 2548 | <item> | ||
| 2549 | <widget class="QPushButton" name="buttonRStickLeft"> | ||
| 2550 | <property name="minimumSize"> | ||
| 2551 | <size> | ||
| 2552 | <width>57</width> | ||
| 2553 | <height>0</height> | ||
| 2554 | </size> | ||
| 2555 | </property> | ||
| 2556 | <property name="maximumSize"> | ||
| 2557 | <size> | ||
| 2558 | <width>55</width> | ||
| 2559 | <height>16777215</height> | ||
| 2560 | </size> | ||
| 2561 | </property> | ||
| 2562 | <property name="styleSheet"> | ||
| 2563 | <string notr="true">min-width: 55px;</string> | ||
| 2564 | </property> | ||
| 2565 | <property name="text"> | ||
| 2566 | <string>Left</string> | ||
| 2567 | </property> | ||
| 2568 | </widget> | ||
| 2569 | </item> | ||
| 2570 | </layout> | ||
| 2571 | </widget> | ||
| 2572 | </item> | ||
| 2573 | <item alignment="Qt::AlignHCenter"> | ||
| 2574 | <widget class="QGroupBox" name="buttonRStickRightGroup"> | ||
| 2575 | <property name="title"> | ||
| 2576 | <string>Right</string> | ||
| 2577 | </property> | ||
| 2578 | <property name="alignment"> | ||
| 2579 | <set>Qt::AlignCenter</set> | ||
| 2580 | </property> | ||
| 2581 | <layout class="QVBoxLayout" name="buttonRStickRightVerticalLayout"> | ||
| 2582 | <property name="spacing"> | ||
| 2583 | <number>3</number> | ||
| 2584 | </property> | ||
| 2585 | <property name="leftMargin"> | ||
| 2586 | <number>3</number> | ||
| 2587 | </property> | ||
| 2588 | <property name="topMargin"> | ||
| 2589 | <number>3</number> | ||
| 2590 | </property> | ||
| 2591 | <property name="rightMargin"> | ||
| 2592 | <number>3</number> | ||
| 2593 | </property> | ||
| 2594 | <property name="bottomMargin"> | ||
| 2595 | <number>3</number> | ||
| 2596 | </property> | ||
| 2597 | <item> | ||
| 2598 | <widget class="QPushButton" name="buttonRStickRight"> | ||
| 2599 | <property name="minimumSize"> | ||
| 2600 | <size> | ||
| 2601 | <width>57</width> | ||
| 2602 | <height>0</height> | ||
| 2603 | </size> | ||
| 2604 | </property> | ||
| 2605 | <property name="maximumSize"> | ||
| 2606 | <size> | ||
| 2607 | <width>55</width> | ||
| 2608 | <height>16777215</height> | ||
| 2609 | </size> | ||
| 2610 | </property> | ||
| 2611 | <property name="styleSheet"> | ||
| 2612 | <string notr="true">min-width: 55px;</string> | ||
| 2613 | </property> | ||
| 2614 | <property name="text"> | ||
| 2615 | <string>Right</string> | ||
| 2616 | </property> | ||
| 2617 | </widget> | ||
| 2618 | </item> | ||
| 2619 | </layout> | ||
| 2620 | </widget> | ||
| 2621 | </item> | ||
| 2622 | </layout> | ||
| 2623 | </item> | ||
| 2624 | <item> | ||
| 2625 | <widget class="QWidget" name="buttonRStickDownWidget" native="true"> | ||
| 2626 | <layout class="QHBoxLayout" name="horizontalLayout_11"> | ||
| 2627 | <property name="spacing"> | ||
| 2628 | <number>0</number> | ||
| 2629 | </property> | ||
| 2630 | <property name="leftMargin"> | ||
| 2631 | <number>0</number> | ||
| 2632 | </property> | ||
| 2633 | <property name="topMargin"> | ||
| 2634 | <number>0</number> | ||
| 2635 | </property> | ||
| 2636 | <property name="rightMargin"> | ||
| 2637 | <number>0</number> | ||
| 2638 | </property> | ||
| 2639 | <property name="bottomMargin"> | ||
| 2640 | <number>0</number> | ||
| 2641 | </property> | ||
| 2642 | <item> | ||
| 2643 | <spacer name="horizontalSpacerRStickDownLeft"> | ||
| 2644 | <property name="orientation"> | ||
| 2645 | <enum>Qt::Horizontal</enum> | ||
| 2646 | </property> | ||
| 2647 | <property name="sizeHint" stdset="0"> | ||
| 2648 | <size> | ||
| 2649 | <width>20</width> | ||
| 2650 | <height>20</height> | ||
| 2651 | </size> | ||
| 2652 | </property> | ||
| 2653 | </spacer> | ||
| 2654 | </item> | ||
| 2655 | <item> | ||
| 2656 | <widget class="QGroupBox" name="buttonRStickDownGroup"> | ||
| 2657 | <property name="title"> | ||
| 2658 | <string>Down</string> | ||
| 2659 | </property> | ||
| 2660 | <property name="alignment"> | ||
| 2661 | <set>Qt::AlignCenter</set> | ||
| 2662 | </property> | ||
| 2663 | <layout class="QVBoxLayout" name="buttonRStickDownVerticalLayout"> | ||
| 2664 | <property name="spacing"> | ||
| 2665 | <number>3</number> | ||
| 2666 | </property> | ||
| 2667 | <property name="leftMargin"> | ||
| 2668 | <number>3</number> | ||
| 2669 | </property> | ||
| 2670 | <property name="topMargin"> | ||
| 2671 | <number>3</number> | ||
| 2672 | </property> | ||
| 2673 | <property name="rightMargin"> | ||
| 2674 | <number>3</number> | ||
| 2675 | </property> | ||
| 2676 | <property name="bottomMargin"> | ||
| 2677 | <number>3</number> | ||
| 2678 | </property> | ||
| 2679 | <item> | ||
| 2680 | <widget class="QPushButton" name="buttonRStickDown"> | ||
| 2681 | <property name="minimumSize"> | ||
| 2682 | <size> | ||
| 2683 | <width>57</width> | ||
| 2684 | <height>0</height> | ||
| 2685 | </size> | ||
| 2686 | </property> | ||
| 2687 | <property name="maximumSize"> | ||
| 2688 | <size> | ||
| 2689 | <width>55</width> | ||
| 2690 | <height>16777215</height> | ||
| 2691 | </size> | ||
| 2692 | </property> | ||
| 2693 | <property name="styleSheet"> | ||
| 2694 | <string notr="true">min-width: 55px;</string> | ||
| 2695 | </property> | ||
| 2696 | <property name="text"> | ||
| 2697 | <string>Down</string> | ||
| 2698 | </property> | ||
| 2699 | </widget> | ||
| 2700 | </item> | ||
| 2701 | </layout> | ||
| 2702 | </widget> | ||
| 2703 | </item> | ||
| 2704 | <item> | ||
| 2705 | <spacer name="horizontalSpacerRStickDownRight"> | ||
| 2706 | <property name="orientation"> | ||
| 2707 | <enum>Qt::Horizontal</enum> | ||
| 2708 | </property> | ||
| 2709 | <property name="sizeHint" stdset="0"> | ||
| 2710 | <size> | ||
| 2711 | <width>20</width> | ||
| 2712 | <height>20</height> | ||
| 2713 | </size> | ||
| 2714 | </property> | ||
| 2715 | </spacer> | ||
| 2716 | </item> | ||
| 2717 | </layout> | ||
| 2718 | </widget> | ||
| 2719 | </item> | ||
| 2720 | <item> | ||
| 2721 | <layout class="QHBoxLayout" name="buttonRStickPressedModifierHorizontalLayout"> | ||
| 2722 | <property name="spacing"> | ||
| 2723 | <number>3</number> | ||
| 2724 | </property> | ||
| 2725 | <item alignment="Qt::AlignHCenter"> | ||
| 2726 | <widget class="QGroupBox" name="groupRStickPressed"> | ||
| 2727 | <property name="title"> | ||
| 2728 | <string>Pressed</string> | ||
| 2729 | </property> | ||
| 2730 | <property name="alignment"> | ||
| 2731 | <set>Qt::AlignCenter</set> | ||
| 2732 | </property> | ||
| 2733 | <layout class="QVBoxLayout" name="buttonRStickPressedVerticalLayout"> | ||
| 2734 | <property name="spacing"> | ||
| 2735 | <number>3</number> | ||
| 2736 | </property> | ||
| 2737 | <property name="leftMargin"> | ||
| 2738 | <number>3</number> | ||
| 2739 | </property> | ||
| 2740 | <property name="topMargin"> | ||
| 2741 | <number>3</number> | ||
| 2742 | </property> | ||
| 2743 | <property name="rightMargin"> | ||
| 2744 | <number>3</number> | ||
| 2745 | </property> | ||
| 2746 | <property name="bottomMargin"> | ||
| 2747 | <number>3</number> | ||
| 2748 | </property> | ||
| 2749 | <item> | ||
| 2750 | <widget class="QPushButton" name="buttonRStick"> | ||
| 2751 | <property name="minimumSize"> | ||
| 2752 | <size> | ||
| 2753 | <width>57</width> | ||
| 2754 | <height>0</height> | ||
| 2755 | </size> | ||
| 2756 | </property> | ||
| 2757 | <property name="maximumSize"> | ||
| 2758 | <size> | ||
| 2759 | <width>55</width> | ||
| 2760 | <height>16777215</height> | ||
| 2761 | </size> | ||
| 2762 | </property> | ||
| 2763 | <property name="styleSheet"> | ||
| 2764 | <string notr="true">min-width: 55px;</string> | ||
| 2765 | </property> | ||
| 2766 | <property name="text"> | ||
| 2767 | <string>Pressed</string> | ||
| 2768 | </property> | ||
| 2769 | </widget> | ||
| 2770 | </item> | ||
| 2771 | </layout> | ||
| 2772 | </widget> | ||
| 2773 | </item> | ||
| 2774 | <item alignment="Qt::AlignHCenter"> | ||
| 2775 | <widget class="QGroupBox" name="buttonRStickModGroup"> | ||
| 2776 | <property name="title"> | ||
| 2777 | <string>Modifier</string> | ||
| 2778 | </property> | ||
| 2779 | <property name="alignment"> | ||
| 2780 | <set>Qt::AlignCenter</set> | ||
| 2781 | </property> | ||
| 2782 | <layout class="QVBoxLayout" name="buttonRStickModVerticalLayout"> | ||
| 2783 | <property name="spacing"> | ||
| 2784 | <number>3</number> | ||
| 2785 | </property> | ||
| 2786 | <property name="leftMargin"> | ||
| 2787 | <number>3</number> | ||
| 2788 | </property> | ||
| 2789 | <property name="topMargin"> | ||
| 2790 | <number>3</number> | ||
| 2791 | </property> | ||
| 2792 | <property name="rightMargin"> | ||
| 2793 | <number>3</number> | ||
| 2794 | </property> | ||
| 2795 | <property name="bottomMargin"> | ||
| 2796 | <number>3</number> | ||
| 2797 | </property> | ||
| 2798 | <item> | ||
| 2799 | <widget class="QPushButton" name="buttonRStickMod"> | ||
| 2800 | <property name="minimumSize"> | ||
| 2801 | <size> | ||
| 2802 | <width>57</width> | ||
| 2803 | <height>0</height> | ||
| 2804 | </size> | ||
| 2805 | </property> | ||
| 2806 | <property name="maximumSize"> | ||
| 2807 | <size> | ||
| 2808 | <width>55</width> | ||
| 2809 | <height>16777215</height> | ||
| 2810 | </size> | ||
| 2811 | </property> | ||
| 2812 | <property name="styleSheet"> | ||
| 2813 | <string notr="true">min-width: 55px;</string> | ||
| 2814 | </property> | ||
| 2815 | <property name="text"> | ||
| 2816 | <string>Modifier</string> | ||
| 2817 | </property> | ||
| 2818 | </widget> | ||
| 2819 | </item> | ||
| 2820 | </layout> | ||
| 2821 | </widget> | ||
| 2822 | </item> | ||
| 2823 | <item> | ||
| 2824 | <widget class="QGroupBox" name="buttonRStickRangeGroup"> | ||
| 2825 | <property name="title"> | ||
| 2826 | <string>Range</string> | ||
| 2827 | </property> | ||
| 2828 | <layout class="QHBoxLayout" name="buttonRStickRangeGroupHorizontalLayout"> | ||
| 2829 | <property name="spacing"> | ||
| 2830 | <number>3</number> | ||
| 2831 | </property> | ||
| 2832 | <property name="leftMargin"> | ||
| 2833 | <number>3</number> | ||
| 2834 | </property> | ||
| 2835 | <property name="topMargin"> | ||
| 2836 | <number>3</number> | ||
| 2837 | </property> | ||
| 2838 | <property name="rightMargin"> | ||
| 2839 | <number>3</number> | ||
| 2840 | </property> | ||
| 2841 | <property name="bottomMargin"> | ||
| 2842 | <number>3</number> | ||
| 2843 | </property> | ||
| 2844 | <item> | ||
| 2845 | <widget class="QSpinBox" name="spinboxRStickRange"> | ||
| 2846 | <property name="minimumSize"> | ||
| 2847 | <size> | ||
| 2848 | <width>55</width> | ||
| 2849 | <height>21</height> | ||
| 2850 | </size> | ||
| 2851 | </property> | ||
| 2852 | <property name="maximumSize"> | ||
| 2853 | <size> | ||
| 2854 | <width>55</width> | ||
| 2855 | <height>16777215</height> | ||
| 2856 | </size> | ||
| 2857 | </property> | ||
| 2858 | <property name="suffix"> | ||
| 2859 | <string>%</string> | ||
| 2860 | </property> | ||
| 2861 | <property name="minimum"> | ||
| 2862 | <number>50</number> | ||
| 2863 | </property> | ||
| 2864 | <property name="maximum"> | ||
| 2865 | <number>150</number> | ||
| 2866 | </property> | ||
| 2867 | <property name="value"> | ||
| 2868 | <number>100</number> | ||
| 2869 | </property> | ||
| 2870 | </widget> | ||
| 2871 | </item> | ||
| 2872 | </layout> | ||
| 2873 | </widget> | ||
| 2874 | </item> | ||
| 2875 | </layout> | ||
| 2876 | </item> | ||
| 2877 | <item> | ||
| 2878 | <layout class="QVBoxLayout" name="sliderRStickDeadzoneModifierRangeVerticalLayout"> | ||
| 2879 | <property name="spacing"> | ||
| 2880 | <number>3</number> | ||
| 2881 | </property> | ||
| 2882 | <property name="leftMargin"> | ||
| 2883 | <number>0</number> | ||
| 2884 | </property> | ||
| 2885 | <property name="topMargin"> | ||
| 2886 | <number>2</number> | ||
| 2887 | </property> | ||
| 2888 | <property name="rightMargin"> | ||
| 2889 | <number>0</number> | ||
| 2890 | </property> | ||
| 2891 | <property name="bottomMargin"> | ||
| 2892 | <number>3</number> | ||
| 2893 | </property> | ||
| 2894 | <item> | ||
| 2895 | <layout class="QHBoxLayout" name="sliderRStickDeadzoneHorizontalLayout"> | ||
| 2896 | <item> | ||
| 2897 | <widget class="QLabel" name="labelRStickDeadzone"> | ||
| 2898 | <property name="text"> | ||
| 2899 | <string>Deadzone: 0%</string> | ||
| 2900 | </property> | ||
| 2901 | <property name="alignment"> | ||
| 2902 | <set>Qt::AlignHCenter</set> | ||
| 2903 | </property> | ||
| 2904 | </widget> | ||
| 2905 | </item> | ||
| 2906 | </layout> | ||
| 2907 | </item> | ||
| 2908 | <item> | ||
| 2909 | <widget class="QSlider" name="sliderRStickDeadzone"> | ||
| 2910 | <property name="maximum"> | ||
| 2911 | <number>100</number> | ||
| 2912 | </property> | ||
| 2913 | <property name="orientation"> | ||
| 2914 | <enum>Qt::Horizontal</enum> | ||
| 2915 | </property> | ||
| 2916 | </widget> | ||
| 2917 | </item> | ||
| 2918 | <item> | ||
| 2919 | <layout class="QHBoxLayout" name="sliderRStickModifierRangeHorizontalLayout"> | ||
| 2920 | <item> | ||
| 2921 | <widget class="QLabel" name="labelRStickModifierRange"> | ||
| 2922 | <property name="text"> | ||
| 2923 | <string>Modifier Range: 0%</string> | ||
| 2924 | </property> | ||
| 2925 | <property name="alignment"> | ||
| 2926 | <set>Qt::AlignHCenter</set> | ||
| 2927 | </property> | ||
| 2928 | </widget> | ||
| 2929 | </item> | ||
| 2930 | </layout> | ||
| 2931 | </item> | ||
| 2932 | <item> | ||
| 2933 | <widget class="QSlider" name="sliderRStickModifierRange"> | ||
| 2934 | <property name="maximum"> | ||
| 2935 | <number>100</number> | ||
| 2936 | </property> | ||
| 2937 | <property name="orientation"> | ||
| 2938 | <enum>Qt::Horizontal</enum> | ||
| 2939 | </property> | ||
| 2940 | </widget> | ||
| 2941 | </item> | ||
| 2942 | </layout> | ||
| 2943 | </item> | ||
| 2944 | </layout> | ||
| 2945 | </widget> | ||
| 2946 | </item> | ||
| 2947 | <item> | ||
| 2948 | <spacer name="verticalSpacerBottomRight_2"> | ||
| 2949 | <property name="orientation"> | ||
| 2950 | <enum>Qt::Vertical</enum> | ||
| 2951 | </property> | ||
| 2952 | <property name="sizeHint" stdset="0"> | ||
| 2953 | <size> | ||
| 2954 | <width>20</width> | ||
| 2955 | <height>0</height> | ||
| 2956 | </size> | ||
| 2957 | </property> | ||
| 2958 | </spacer> | ||
| 2959 | </item> | ||
| 2960 | </layout> | ||
| 2961 | </widget> | ||
| 1104 | </item> | 2962 | </item> |
| 1105 | </layout> | 2963 | </layout> |
| 1106 | </widget> | 2964 | </widget> |
| 1107 | </item> | 2965 | </item> |
| 1108 | </layout> | 2966 | </layout> |
| 1109 | </item> | 2967 | </item> |
| 1110 | <item> | ||
| 1111 | <spacer name="verticalSpacer"> | ||
| 1112 | <property name="orientation"> | ||
| 1113 | <enum>Qt::Vertical</enum> | ||
| 1114 | </property> | ||
| 1115 | <property name="sizeHint" stdset="0"> | ||
| 1116 | <size> | ||
| 1117 | <width>20</width> | ||
| 1118 | <height>40</height> | ||
| 1119 | </size> | ||
| 1120 | </property> | ||
| 1121 | </spacer> | ||
| 1122 | </item> | ||
| 1123 | <item> | ||
| 1124 | <layout class="QHBoxLayout" name="horizontalLayout"/> | ||
| 1125 | </item> | ||
| 1126 | <item> | ||
| 1127 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 1128 | <item> | ||
| 1129 | <widget class="QPushButton" name="buttonClearAll"> | ||
| 1130 | <property name="sizePolicy"> | ||
| 1131 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 1132 | <horstretch>0</horstretch> | ||
| 1133 | <verstretch>0</verstretch> | ||
| 1134 | </sizepolicy> | ||
| 1135 | </property> | ||
| 1136 | <property name="sizeIncrement"> | ||
| 1137 | <size> | ||
| 1138 | <width>0</width> | ||
| 1139 | <height>0</height> | ||
| 1140 | </size> | ||
| 1141 | </property> | ||
| 1142 | <property name="baseSize"> | ||
| 1143 | <size> | ||
| 1144 | <width>0</width> | ||
| 1145 | <height>0</height> | ||
| 1146 | </size> | ||
| 1147 | </property> | ||
| 1148 | <property name="layoutDirection"> | ||
| 1149 | <enum>Qt::LeftToRight</enum> | ||
| 1150 | </property> | ||
| 1151 | <property name="text"> | ||
| 1152 | <string>Clear All</string> | ||
| 1153 | </property> | ||
| 1154 | </widget> | ||
| 1155 | </item> | ||
| 1156 | <item> | ||
| 1157 | <widget class="QPushButton" name="buttonRestoreDefaults"> | ||
| 1158 | <property name="sizePolicy"> | ||
| 1159 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 1160 | <horstretch>0</horstretch> | ||
| 1161 | <verstretch>0</verstretch> | ||
| 1162 | </sizepolicy> | ||
| 1163 | </property> | ||
| 1164 | <property name="sizeIncrement"> | ||
| 1165 | <size> | ||
| 1166 | <width>0</width> | ||
| 1167 | <height>0</height> | ||
| 1168 | </size> | ||
| 1169 | </property> | ||
| 1170 | <property name="baseSize"> | ||
| 1171 | <size> | ||
| 1172 | <width>0</width> | ||
| 1173 | <height>0</height> | ||
| 1174 | </size> | ||
| 1175 | </property> | ||
| 1176 | <property name="layoutDirection"> | ||
| 1177 | <enum>Qt::LeftToRight</enum> | ||
| 1178 | </property> | ||
| 1179 | <property name="text"> | ||
| 1180 | <string>Restore Defaults</string> | ||
| 1181 | </property> | ||
| 1182 | </widget> | ||
| 1183 | </item> | ||
| 1184 | <item> | ||
| 1185 | <spacer name="horizontalSpacer"> | ||
| 1186 | <property name="orientation"> | ||
| 1187 | <enum>Qt::Horizontal</enum> | ||
| 1188 | </property> | ||
| 1189 | <property name="sizeHint" stdset="0"> | ||
| 1190 | <size> | ||
| 1191 | <width>40</width> | ||
| 1192 | <height>20</height> | ||
| 1193 | </size> | ||
| 1194 | </property> | ||
| 1195 | </spacer> | ||
| 1196 | </item> | ||
| 1197 | <item> | ||
| 1198 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 1199 | <property name="standardButtons"> | ||
| 1200 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 1201 | </property> | ||
| 1202 | </widget> | ||
| 1203 | </item> | ||
| 1204 | </layout> | ||
| 1205 | </item> | ||
| 1206 | </layout> | 2968 | </layout> |
| 1207 | </widget> | 2969 | </widget> |
| 1208 | <resources/> | 2970 | <resources> |
| 1209 | <connections> | 2971 | <include location="../../../dist/icons/controller/controller.qrc"/> |
| 1210 | <connection> | 2972 | </resources> |
| 1211 | <sender>buttonBox</sender> | 2973 | <connections/> |
| 1212 | <signal>accepted()</signal> | ||
| 1213 | <receiver>ConfigureInputPlayer</receiver> | ||
| 1214 | <slot>accept()</slot> | ||
| 1215 | <hints> | ||
| 1216 | <hint type="sourcelabel"> | ||
| 1217 | <x>371</x> | ||
| 1218 | <y>730</y> | ||
| 1219 | </hint> | ||
| 1220 | <hint type="destinationlabel"> | ||
| 1221 | <x>229</x> | ||
| 1222 | <y>375</y> | ||
| 1223 | </hint> | ||
| 1224 | </hints> | ||
| 1225 | </connection> | ||
| 1226 | <connection> | ||
| 1227 | <sender>buttonBox</sender> | ||
| 1228 | <signal>rejected()</signal> | ||
| 1229 | <receiver>ConfigureInputPlayer</receiver> | ||
| 1230 | <slot>reject()</slot> | ||
| 1231 | <hints> | ||
| 1232 | <hint type="sourcelabel"> | ||
| 1233 | <x>371</x> | ||
| 1234 | <y>730</y> | ||
| 1235 | </hint> | ||
| 1236 | <hint type="destinationlabel"> | ||
| 1237 | <x>229</x> | ||
| 1238 | <y>375</y> | ||
| 1239 | </hint> | ||
| 1240 | </hints> | ||
| 1241 | </connection> | ||
| 1242 | </connections> | ||
| 1243 | </ui> | 2974 | </ui> |
diff --git a/src/yuzu/configuration/configure_input_simple.cpp b/src/yuzu/configuration/configure_input_simple.cpp deleted file mode 100644 index 0e0e8f113..000000000 --- a/src/yuzu/configuration/configure_input_simple.cpp +++ /dev/null | |||
| @@ -1,152 +0,0 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <tuple> | ||
| 7 | |||
| 8 | #include "ui_configure_input_simple.h" | ||
| 9 | #include "yuzu/configuration/configure_input.h" | ||
| 10 | #include "yuzu/configuration/configure_input_player.h" | ||
| 11 | #include "yuzu/configuration/configure_input_simple.h" | ||
| 12 | #include "yuzu/uisettings.h" | ||
| 13 | |||
| 14 | namespace { | ||
| 15 | |||
| 16 | template <typename Dialog, typename... Args> | ||
| 17 | void CallConfigureDialog(ConfigureInputSimple* caller, Args&&... args) { | ||
| 18 | caller->ApplyConfiguration(); | ||
| 19 | Dialog dialog(caller, std::forward<Args>(args)...); | ||
| 20 | |||
| 21 | const auto res = dialog.exec(); | ||
| 22 | if (res == QDialog::Accepted) { | ||
| 23 | dialog.ApplyConfiguration(); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | // OnProfileSelect functions should (when applicable): | ||
| 28 | // - Set controller types | ||
| 29 | // - Set controller enabled | ||
| 30 | // - Set docked mode | ||
| 31 | // - Set advanced controller config/enabled (i.e. debug, kbd, mouse, touch) | ||
| 32 | // | ||
| 33 | // OnProfileSelect function should NOT however: | ||
| 34 | // - Reset any button mappings | ||
| 35 | // - Open any dialogs | ||
| 36 | // - Block in any way | ||
| 37 | |||
| 38 | constexpr std::size_t PLAYER_0_INDEX = 0; | ||
| 39 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 40 | |||
| 41 | void HandheldOnProfileSelect() { | ||
| 42 | Settings::values.players[HANDHELD_INDEX].connected = true; | ||
| 43 | Settings::values.players[HANDHELD_INDEX].type = Settings::ControllerType::DualJoycon; | ||
| 44 | |||
| 45 | for (std::size_t player = 0; player < HANDHELD_INDEX; ++player) { | ||
| 46 | Settings::values.players[player].connected = false; | ||
| 47 | } | ||
| 48 | |||
| 49 | Settings::values.use_docked_mode = false; | ||
| 50 | Settings::values.keyboard_enabled = false; | ||
| 51 | Settings::values.mouse_enabled = false; | ||
| 52 | Settings::values.debug_pad_enabled = false; | ||
| 53 | Settings::values.touchscreen.enabled = true; | ||
| 54 | } | ||
| 55 | |||
| 56 | void DualJoyconsDockedOnProfileSelect() { | ||
| 57 | Settings::values.players[PLAYER_0_INDEX].connected = true; | ||
| 58 | Settings::values.players[PLAYER_0_INDEX].type = Settings::ControllerType::DualJoycon; | ||
| 59 | |||
| 60 | for (std::size_t player = 1; player <= HANDHELD_INDEX; ++player) { | ||
| 61 | Settings::values.players[player].connected = false; | ||
| 62 | } | ||
| 63 | |||
| 64 | Settings::values.use_docked_mode = true; | ||
| 65 | Settings::values.keyboard_enabled = false; | ||
| 66 | Settings::values.mouse_enabled = false; | ||
| 67 | Settings::values.debug_pad_enabled = false; | ||
| 68 | Settings::values.touchscreen.enabled = true; | ||
| 69 | } | ||
| 70 | |||
| 71 | // Name, OnProfileSelect (called when selected in drop down), OnConfigure (called when configure | ||
| 72 | // is clicked) | ||
| 73 | using InputProfile = std::tuple<const char*, void (*)(), void (*)(ConfigureInputSimple*)>; | ||
| 74 | |||
| 75 | constexpr std::array<InputProfile, 3> INPUT_PROFILES{{ | ||
| 76 | {QT_TR_NOOP("Single Player - Handheld - Undocked"), HandheldOnProfileSelect, | ||
| 77 | [](ConfigureInputSimple* caller) { | ||
| 78 | CallConfigureDialog<ConfigureInputPlayer>(caller, HANDHELD_INDEX, false); | ||
| 79 | }}, | ||
| 80 | {QT_TR_NOOP("Single Player - Dual Joycons - Docked"), DualJoyconsDockedOnProfileSelect, | ||
| 81 | [](ConfigureInputSimple* caller) { | ||
| 82 | CallConfigureDialog<ConfigureInputPlayer>(caller, PLAYER_0_INDEX, false); | ||
| 83 | }}, | ||
| 84 | {QT_TR_NOOP("Custom"), [] {}, CallConfigureDialog<ConfigureInput>}, | ||
| 85 | }}; | ||
| 86 | |||
| 87 | } // namespace | ||
| 88 | |||
| 89 | void ApplyInputProfileConfiguration(int profile_index) { | ||
| 90 | std::get<1>( | ||
| 91 | INPUT_PROFILES.at(std::min(profile_index, static_cast<int>(INPUT_PROFILES.size() - 1))))(); | ||
| 92 | } | ||
| 93 | |||
| 94 | ConfigureInputSimple::ConfigureInputSimple(QWidget* parent) | ||
| 95 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputSimple>()) { | ||
| 96 | ui->setupUi(this); | ||
| 97 | |||
| 98 | for (const auto& profile : INPUT_PROFILES) { | ||
| 99 | const QString label = tr(std::get<0>(profile)); | ||
| 100 | ui->profile_combobox->addItem(label, label); | ||
| 101 | } | ||
| 102 | |||
| 103 | connect(ui->profile_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | ||
| 104 | &ConfigureInputSimple::OnSelectProfile); | ||
| 105 | connect(ui->profile_configure, &QPushButton::clicked, this, &ConfigureInputSimple::OnConfigure); | ||
| 106 | |||
| 107 | LoadConfiguration(); | ||
| 108 | } | ||
| 109 | |||
| 110 | ConfigureInputSimple::~ConfigureInputSimple() = default; | ||
| 111 | |||
| 112 | void ConfigureInputSimple::ApplyConfiguration() { | ||
| 113 | auto index = ui->profile_combobox->currentIndex(); | ||
| 114 | // Make the stored index for "Custom" very large so that if new profiles are added it | ||
| 115 | // doesn't change. | ||
| 116 | if (index >= static_cast<int>(INPUT_PROFILES.size() - 1)) { | ||
| 117 | index = std::numeric_limits<int>::max(); | ||
| 118 | } | ||
| 119 | |||
| 120 | UISettings::values.profile_index = index; | ||
| 121 | } | ||
| 122 | |||
| 123 | void ConfigureInputSimple::changeEvent(QEvent* event) { | ||
| 124 | if (event->type() == QEvent::LanguageChange) { | ||
| 125 | RetranslateUI(); | ||
| 126 | } | ||
| 127 | |||
| 128 | QWidget::changeEvent(event); | ||
| 129 | } | ||
| 130 | |||
| 131 | void ConfigureInputSimple::RetranslateUI() { | ||
| 132 | ui->retranslateUi(this); | ||
| 133 | } | ||
| 134 | |||
| 135 | void ConfigureInputSimple::LoadConfiguration() { | ||
| 136 | const auto index = UISettings::values.profile_index; | ||
| 137 | if (index >= static_cast<int>(INPUT_PROFILES.size()) || index < 0) { | ||
| 138 | ui->profile_combobox->setCurrentIndex(static_cast<int>(INPUT_PROFILES.size() - 1)); | ||
| 139 | } else { | ||
| 140 | ui->profile_combobox->setCurrentIndex(index); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | void ConfigureInputSimple::OnSelectProfile(int index) { | ||
| 145 | const auto old_docked = Settings::values.use_docked_mode; | ||
| 146 | ApplyInputProfileConfiguration(index); | ||
| 147 | OnDockedModeChanged(old_docked, Settings::values.use_docked_mode); | ||
| 148 | } | ||
| 149 | |||
| 150 | void ConfigureInputSimple::OnConfigure() { | ||
| 151 | std::get<2>(INPUT_PROFILES.at(ui->profile_combobox->currentIndex()))(this); | ||
| 152 | } | ||
diff --git a/src/yuzu/configuration/configure_input_simple.h b/src/yuzu/configuration/configure_input_simple.h deleted file mode 100644 index bb5050224..000000000 --- a/src/yuzu/configuration/configure_input_simple.h +++ /dev/null | |||
| @@ -1,43 +0,0 @@ | |||
| 1 | // Copyright 2016 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 <memory> | ||
| 8 | |||
| 9 | #include <QWidget> | ||
| 10 | |||
| 11 | class QPushButton; | ||
| 12 | class QString; | ||
| 13 | class QTimer; | ||
| 14 | |||
| 15 | namespace Ui { | ||
| 16 | class ConfigureInputSimple; | ||
| 17 | } | ||
| 18 | |||
| 19 | // Used by configuration loader to apply a profile if the input is invalid. | ||
| 20 | void ApplyInputProfileConfiguration(int profile_index); | ||
| 21 | |||
| 22 | class ConfigureInputSimple : public QWidget { | ||
| 23 | Q_OBJECT | ||
| 24 | |||
| 25 | public: | ||
| 26 | explicit ConfigureInputSimple(QWidget* parent = nullptr); | ||
| 27 | ~ConfigureInputSimple() override; | ||
| 28 | |||
| 29 | /// Save all button configurations to settings file | ||
| 30 | void ApplyConfiguration(); | ||
| 31 | |||
| 32 | private: | ||
| 33 | void changeEvent(QEvent* event) override; | ||
| 34 | void RetranslateUI(); | ||
| 35 | |||
| 36 | /// Load configuration settings. | ||
| 37 | void LoadConfiguration(); | ||
| 38 | |||
| 39 | void OnSelectProfile(int index); | ||
| 40 | void OnConfigure(); | ||
| 41 | |||
| 42 | std::unique_ptr<Ui::ConfigureInputSimple> ui; | ||
| 43 | }; | ||
diff --git a/src/yuzu/configuration/configure_input_simple.ui b/src/yuzu/configuration/configure_input_simple.ui deleted file mode 100644 index c4889caa9..000000000 --- a/src/yuzu/configuration/configure_input_simple.ui +++ /dev/null | |||
| @@ -1,97 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureInputSimple</class> | ||
| 4 | <widget class="QWidget" name="ConfigureInputSimple"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>473</width> | ||
| 10 | <height>685</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>ConfigureInputSimple</string> | ||
| 15 | </property> | ||
| 16 | <layout class="QVBoxLayout" name="verticalLayout_5"> | ||
| 17 | <item> | ||
| 18 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 19 | <item> | ||
| 20 | <widget class="QGroupBox" name="gridGroupBox"> | ||
| 21 | <property name="title"> | ||
| 22 | <string>Profile</string> | ||
| 23 | </property> | ||
| 24 | <layout class="QGridLayout" name="gridLayout"> | ||
| 25 | <item row="1" column="2"> | ||
| 26 | <widget class="QPushButton" name="profile_configure"> | ||
| 27 | <property name="text"> | ||
| 28 | <string>Configure</string> | ||
| 29 | </property> | ||
| 30 | </widget> | ||
| 31 | </item> | ||
| 32 | <item row="1" column="0"> | ||
| 33 | <spacer name="horizontalSpacer"> | ||
| 34 | <property name="orientation"> | ||
| 35 | <enum>Qt::Horizontal</enum> | ||
| 36 | </property> | ||
| 37 | <property name="sizeHint" stdset="0"> | ||
| 38 | <size> | ||
| 39 | <width>40</width> | ||
| 40 | <height>20</height> | ||
| 41 | </size> | ||
| 42 | </property> | ||
| 43 | </spacer> | ||
| 44 | </item> | ||
| 45 | <item row="1" column="3"> | ||
| 46 | <spacer name="horizontalSpacer_2"> | ||
| 47 | <property name="orientation"> | ||
| 48 | <enum>Qt::Horizontal</enum> | ||
| 49 | </property> | ||
| 50 | <property name="sizeHint" stdset="0"> | ||
| 51 | <size> | ||
| 52 | <width>40</width> | ||
| 53 | <height>20</height> | ||
| 54 | </size> | ||
| 55 | </property> | ||
| 56 | </spacer> | ||
| 57 | </item> | ||
| 58 | <item row="1" column="1"> | ||
| 59 | <widget class="QComboBox" name="profile_combobox"> | ||
| 60 | <property name="minimumSize"> | ||
| 61 | <size> | ||
| 62 | <width>250</width> | ||
| 63 | <height>0</height> | ||
| 64 | </size> | ||
| 65 | </property> | ||
| 66 | </widget> | ||
| 67 | </item> | ||
| 68 | <item row="0" column="1" colspan="2"> | ||
| 69 | <widget class="QLabel" name="label"> | ||
| 70 | <property name="text"> | ||
| 71 | <string>Choose a controller configuration:</string> | ||
| 72 | </property> | ||
| 73 | </widget> | ||
| 74 | </item> | ||
| 75 | </layout> | ||
| 76 | </widget> | ||
| 77 | </item> | ||
| 78 | </layout> | ||
| 79 | </item> | ||
| 80 | <item> | ||
| 81 | <spacer name="verticalSpacer"> | ||
| 82 | <property name="orientation"> | ||
| 83 | <enum>Qt::Vertical</enum> | ||
| 84 | </property> | ||
| 85 | <property name="sizeHint" stdset="0"> | ||
| 86 | <size> | ||
| 87 | <width>20</width> | ||
| 88 | <height>40</height> | ||
| 89 | </size> | ||
| 90 | </property> | ||
| 91 | </spacer> | ||
| 92 | </item> | ||
| 93 | </layout> | ||
| 94 | </widget> | ||
| 95 | <resources/> | ||
| 96 | <connections/> | ||
| 97 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp new file mode 100644 index 000000000..c7d085151 --- /dev/null +++ b/src/yuzu/configuration/configure_motion_touch.cpp | |||
| @@ -0,0 +1,314 @@ | |||
| 1 | // Copyright 2018 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <QCloseEvent> | ||
| 7 | #include <QLabel> | ||
| 8 | #include <QMessageBox> | ||
| 9 | #include <QPushButton> | ||
| 10 | #include <QVBoxLayout> | ||
| 11 | #include "common/logging/log.h" | ||
| 12 | #include "core/settings.h" | ||
| 13 | #include "input_common/main.h" | ||
| 14 | #include "input_common/udp/client.h" | ||
| 15 | #include "input_common/udp/udp.h" | ||
| 16 | #include "ui_configure_motion_touch.h" | ||
| 17 | #include "yuzu/configuration/configure_motion_touch.h" | ||
| 18 | #include "yuzu/configuration/configure_touch_from_button.h" | ||
| 19 | |||
| 20 | CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent, | ||
| 21 | const std::string& host, u16 port, | ||
| 22 | u8 pad_index, u16 client_id) | ||
| 23 | : QDialog(parent) { | ||
| 24 | layout = new QVBoxLayout; | ||
| 25 | status_label = new QLabel(tr("Communicating with the server...")); | ||
| 26 | cancel_button = new QPushButton(tr("Cancel")); | ||
| 27 | connect(cancel_button, &QPushButton::clicked, this, [this] { | ||
| 28 | if (!completed) { | ||
| 29 | job->Stop(); | ||
| 30 | } | ||
| 31 | accept(); | ||
| 32 | }); | ||
| 33 | layout->addWidget(status_label); | ||
| 34 | layout->addWidget(cancel_button); | ||
| 35 | setLayout(layout); | ||
| 36 | |||
| 37 | using namespace InputCommon::CemuhookUDP; | ||
| 38 | job = std::make_unique<CalibrationConfigurationJob>( | ||
| 39 | host, port, pad_index, client_id, | ||
| 40 | [this](CalibrationConfigurationJob::Status status) { | ||
| 41 | QString text; | ||
| 42 | switch (status) { | ||
| 43 | case CalibrationConfigurationJob::Status::Ready: | ||
| 44 | text = tr("Touch the top left corner <br>of your touchpad."); | ||
| 45 | break; | ||
| 46 | case CalibrationConfigurationJob::Status::Stage1Completed: | ||
| 47 | text = tr("Now touch the bottom right corner <br>of your touchpad."); | ||
| 48 | break; | ||
| 49 | case CalibrationConfigurationJob::Status::Completed: | ||
| 50 | text = tr("Configuration completed!"); | ||
| 51 | break; | ||
| 52 | } | ||
| 53 | QMetaObject::invokeMethod(this, "UpdateLabelText", Q_ARG(QString, text)); | ||
| 54 | if (status == CalibrationConfigurationJob::Status::Completed) { | ||
| 55 | QMetaObject::invokeMethod(this, "UpdateButtonText", Q_ARG(QString, tr("OK"))); | ||
| 56 | } | ||
| 57 | }, | ||
| 58 | [this](u16 min_x_, u16 min_y_, u16 max_x_, u16 max_y_) { | ||
| 59 | completed = true; | ||
| 60 | min_x = min_x_; | ||
| 61 | min_y = min_y_; | ||
| 62 | max_x = max_x_; | ||
| 63 | max_y = max_y_; | ||
| 64 | }); | ||
| 65 | } | ||
| 66 | |||
| 67 | CalibrationConfigurationDialog::~CalibrationConfigurationDialog() = default; | ||
| 68 | |||
| 69 | void CalibrationConfigurationDialog::UpdateLabelText(const QString& text) { | ||
| 70 | status_label->setText(text); | ||
| 71 | } | ||
| 72 | |||
| 73 | void CalibrationConfigurationDialog::UpdateButtonText(const QString& text) { | ||
| 74 | cancel_button->setText(text); | ||
| 75 | } | ||
| 76 | |||
| 77 | constexpr std::array<std::pair<const char*, const char*>, 2> MotionProviders = {{ | ||
| 78 | {"motion_emu", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "Mouse (Right Click)")}, | ||
| 79 | {"cemuhookudp", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "CemuhookUDP")}, | ||
| 80 | }}; | ||
| 81 | |||
| 82 | constexpr std::array<std::pair<const char*, const char*>, 2> TouchProviders = {{ | ||
| 83 | {"emu_window", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "Emulator Window")}, | ||
| 84 | {"cemuhookudp", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "CemuhookUDP")}, | ||
| 85 | }}; | ||
| 86 | |||
| 87 | ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent, | ||
| 88 | InputCommon::InputSubsystem* input_subsystem_) | ||
| 89 | : QDialog(parent), input_subsystem{input_subsystem_}, | ||
| 90 | ui(std::make_unique<Ui::ConfigureMotionTouch>()) { | ||
| 91 | ui->setupUi(this); | ||
| 92 | for (const auto& [provider, name] : MotionProviders) { | ||
| 93 | ui->motion_provider->addItem(tr(name), QString::fromUtf8(provider)); | ||
| 94 | } | ||
| 95 | for (const auto& [provider, name] : TouchProviders) { | ||
| 96 | ui->touch_provider->addItem(tr(name), QString::fromUtf8(provider)); | ||
| 97 | } | ||
| 98 | |||
| 99 | ui->udp_learn_more->setOpenExternalLinks(true); | ||
| 100 | ui->udp_learn_more->setText( | ||
| 101 | tr("<a " | ||
| 102 | "href='https://yuzu-emu.org/wiki/" | ||
| 103 | "using-a-controller-or-android-phone-for-motion-or-touch-input'><span " | ||
| 104 | "style=\"text-decoration: underline; color:#039be5;\">Learn More</span></a>")); | ||
| 105 | |||
| 106 | SetConfiguration(); | ||
| 107 | UpdateUiDisplay(); | ||
| 108 | ConnectEvents(); | ||
| 109 | } | ||
| 110 | |||
| 111 | ConfigureMotionTouch::~ConfigureMotionTouch() = default; | ||
| 112 | |||
| 113 | void ConfigureMotionTouch::SetConfiguration() { | ||
| 114 | const Common::ParamPackage motion_param(Settings::values.motion_device); | ||
| 115 | const Common::ParamPackage touch_param(Settings::values.touch_device); | ||
| 116 | const std::string motion_engine = motion_param.Get("engine", "motion_emu"); | ||
| 117 | const std::string touch_engine = touch_param.Get("engine", "emu_window"); | ||
| 118 | |||
| 119 | ui->motion_provider->setCurrentIndex( | ||
| 120 | ui->motion_provider->findData(QString::fromStdString(motion_engine))); | ||
| 121 | ui->touch_provider->setCurrentIndex( | ||
| 122 | ui->touch_provider->findData(QString::fromStdString(touch_engine))); | ||
| 123 | ui->touch_from_button_checkbox->setChecked(Settings::values.use_touch_from_button); | ||
| 124 | touch_from_button_maps = Settings::values.touch_from_button_maps; | ||
| 125 | for (const auto& touch_map : touch_from_button_maps) { | ||
| 126 | ui->touch_from_button_map->addItem(QString::fromStdString(touch_map.name)); | ||
| 127 | } | ||
| 128 | ui->touch_from_button_map->setCurrentIndex(Settings::values.touch_from_button_map_index); | ||
| 129 | ui->motion_sensitivity->setValue(motion_param.Get("sensitivity", 0.01f)); | ||
| 130 | |||
| 131 | min_x = touch_param.Get("min_x", 100); | ||
| 132 | min_y = touch_param.Get("min_y", 50); | ||
| 133 | max_x = touch_param.Get("max_x", 1800); | ||
| 134 | max_y = touch_param.Get("max_y", 850); | ||
| 135 | |||
| 136 | ui->udp_server->setText(QString::fromStdString(Settings::values.udp_input_address)); | ||
| 137 | ui->udp_port->setText(QString::number(Settings::values.udp_input_port)); | ||
| 138 | ui->udp_pad_index->setCurrentIndex(Settings::values.udp_pad_index); | ||
| 139 | } | ||
| 140 | |||
| 141 | void ConfigureMotionTouch::UpdateUiDisplay() { | ||
| 142 | const QString motion_engine = ui->motion_provider->currentData().toString(); | ||
| 143 | const QString touch_engine = ui->touch_provider->currentData().toString(); | ||
| 144 | const QString cemuhook_udp = QStringLiteral("cemuhookudp"); | ||
| 145 | |||
| 146 | if (motion_engine == QStringLiteral("motion_emu")) { | ||
| 147 | ui->motion_sensitivity_label->setVisible(true); | ||
| 148 | ui->motion_sensitivity->setVisible(true); | ||
| 149 | } else { | ||
| 150 | ui->motion_sensitivity_label->setVisible(false); | ||
| 151 | ui->motion_sensitivity->setVisible(false); | ||
| 152 | } | ||
| 153 | |||
| 154 | if (touch_engine == cemuhook_udp) { | ||
| 155 | ui->touch_calibration->setVisible(true); | ||
| 156 | ui->touch_calibration_config->setVisible(true); | ||
| 157 | ui->touch_calibration_label->setVisible(true); | ||
| 158 | ui->touch_calibration->setText( | ||
| 159 | QStringLiteral("(%1, %2) - (%3, %4)").arg(min_x).arg(min_y).arg(max_x).arg(max_y)); | ||
| 160 | } else { | ||
| 161 | ui->touch_calibration->setVisible(false); | ||
| 162 | ui->touch_calibration_config->setVisible(false); | ||
| 163 | ui->touch_calibration_label->setVisible(false); | ||
| 164 | } | ||
| 165 | |||
| 166 | if (motion_engine == cemuhook_udp || touch_engine == cemuhook_udp) { | ||
| 167 | ui->udp_config_group_box->setVisible(true); | ||
| 168 | } else { | ||
| 169 | ui->udp_config_group_box->setVisible(false); | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | void ConfigureMotionTouch::ConnectEvents() { | ||
| 174 | connect(ui->motion_provider, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||
| 175 | [this](int index) { UpdateUiDisplay(); }); | ||
| 176 | connect(ui->touch_provider, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||
| 177 | [this](int index) { UpdateUiDisplay(); }); | ||
| 178 | connect(ui->udp_test, &QPushButton::clicked, this, &ConfigureMotionTouch::OnCemuhookUDPTest); | ||
| 179 | connect(ui->touch_calibration_config, &QPushButton::clicked, this, | ||
| 180 | &ConfigureMotionTouch::OnConfigureTouchCalibration); | ||
| 181 | connect(ui->touch_from_button_config_btn, &QPushButton::clicked, this, | ||
| 182 | &ConfigureMotionTouch::OnConfigureTouchFromButton); | ||
| 183 | connect(ui->buttonBox, &QDialogButtonBox::rejected, this, [this] { | ||
| 184 | if (CanCloseDialog()) { | ||
| 185 | reject(); | ||
| 186 | } | ||
| 187 | }); | ||
| 188 | } | ||
| 189 | |||
| 190 | void ConfigureMotionTouch::OnCemuhookUDPTest() { | ||
| 191 | ui->udp_test->setEnabled(false); | ||
| 192 | ui->udp_test->setText(tr("Testing")); | ||
| 193 | udp_test_in_progress = true; | ||
| 194 | InputCommon::CemuhookUDP::TestCommunication( | ||
| 195 | ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), | ||
| 196 | static_cast<u8>(ui->udp_pad_index->currentIndex()), 24872, | ||
| 197 | [this] { | ||
| 198 | LOG_INFO(Frontend, "UDP input test success"); | ||
| 199 | QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); | ||
| 200 | }, | ||
| 201 | [this] { | ||
| 202 | LOG_ERROR(Frontend, "UDP input test failed"); | ||
| 203 | QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, false)); | ||
| 204 | }); | ||
| 205 | } | ||
| 206 | |||
| 207 | void ConfigureMotionTouch::OnConfigureTouchCalibration() { | ||
| 208 | ui->touch_calibration_config->setEnabled(false); | ||
| 209 | ui->touch_calibration_config->setText(tr("Configuring")); | ||
| 210 | CalibrationConfigurationDialog dialog( | ||
| 211 | this, ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toUInt()), | ||
| 212 | static_cast<u8>(ui->udp_pad_index->currentIndex()), 24872); | ||
| 213 | dialog.exec(); | ||
| 214 | if (dialog.completed) { | ||
| 215 | min_x = dialog.min_x; | ||
| 216 | min_y = dialog.min_y; | ||
| 217 | max_x = dialog.max_x; | ||
| 218 | max_y = dialog.max_y; | ||
| 219 | LOG_INFO(Frontend, | ||
| 220 | "UDP touchpad calibration config success: min_x={}, min_y={}, max_x={}, max_y={}", | ||
| 221 | min_x, min_y, max_x, max_y); | ||
| 222 | UpdateUiDisplay(); | ||
| 223 | } else { | ||
| 224 | LOG_ERROR(Frontend, "UDP touchpad calibration config failed"); | ||
| 225 | } | ||
| 226 | ui->touch_calibration_config->setEnabled(true); | ||
| 227 | ui->touch_calibration_config->setText(tr("Configure")); | ||
| 228 | } | ||
| 229 | |||
| 230 | void ConfigureMotionTouch::closeEvent(QCloseEvent* event) { | ||
| 231 | if (CanCloseDialog()) { | ||
| 232 | event->accept(); | ||
| 233 | } else { | ||
| 234 | event->ignore(); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | void ConfigureMotionTouch::ShowUDPTestResult(bool result) { | ||
| 239 | udp_test_in_progress = false; | ||
| 240 | if (result) { | ||
| 241 | QMessageBox::information(this, tr("Test Successful"), | ||
| 242 | tr("Successfully received data from the server.")); | ||
| 243 | } else { | ||
| 244 | QMessageBox::warning(this, tr("Test Failed"), | ||
| 245 | tr("Could not receive valid data from the server.<br>Please verify " | ||
| 246 | "that the server is set up correctly and " | ||
| 247 | "the address and port are correct.")); | ||
| 248 | } | ||
| 249 | ui->udp_test->setEnabled(true); | ||
| 250 | ui->udp_test->setText(tr("Test")); | ||
| 251 | } | ||
| 252 | |||
| 253 | void ConfigureMotionTouch::OnConfigureTouchFromButton() { | ||
| 254 | ConfigureTouchFromButton dialog{this, touch_from_button_maps, input_subsystem, | ||
| 255 | ui->touch_from_button_map->currentIndex()}; | ||
| 256 | if (dialog.exec() != QDialog::Accepted) { | ||
| 257 | return; | ||
| 258 | } | ||
| 259 | touch_from_button_maps = dialog.GetMaps(); | ||
| 260 | |||
| 261 | while (ui->touch_from_button_map->count() > 0) { | ||
| 262 | ui->touch_from_button_map->removeItem(0); | ||
| 263 | } | ||
| 264 | for (const auto& touch_map : touch_from_button_maps) { | ||
| 265 | ui->touch_from_button_map->addItem(QString::fromStdString(touch_map.name)); | ||
| 266 | } | ||
| 267 | ui->touch_from_button_map->setCurrentIndex(dialog.GetSelectedIndex()); | ||
| 268 | } | ||
| 269 | |||
| 270 | bool ConfigureMotionTouch::CanCloseDialog() { | ||
| 271 | if (udp_test_in_progress) { | ||
| 272 | QMessageBox::warning(this, tr("Citra"), | ||
| 273 | tr("UDP Test or calibration configuration is in progress.<br>Please " | ||
| 274 | "wait for them to finish.")); | ||
| 275 | return false; | ||
| 276 | } | ||
| 277 | return true; | ||
| 278 | } | ||
| 279 | |||
| 280 | void ConfigureMotionTouch::ApplyConfiguration() { | ||
| 281 | if (!CanCloseDialog()) { | ||
| 282 | return; | ||
| 283 | } | ||
| 284 | |||
| 285 | std::string motion_engine = ui->motion_provider->currentData().toString().toStdString(); | ||
| 286 | std::string touch_engine = ui->touch_provider->currentData().toString().toStdString(); | ||
| 287 | |||
| 288 | Common::ParamPackage motion_param{}, touch_param{}; | ||
| 289 | motion_param.Set("engine", std::move(motion_engine)); | ||
| 290 | touch_param.Set("engine", std::move(touch_engine)); | ||
| 291 | |||
| 292 | if (motion_engine == "motion_emu") { | ||
| 293 | motion_param.Set("sensitivity", static_cast<float>(ui->motion_sensitivity->value())); | ||
| 294 | } | ||
| 295 | |||
| 296 | if (touch_engine == "cemuhookudp") { | ||
| 297 | touch_param.Set("min_x", min_x); | ||
| 298 | touch_param.Set("min_y", min_y); | ||
| 299 | touch_param.Set("max_x", max_x); | ||
| 300 | touch_param.Set("max_y", max_y); | ||
| 301 | } | ||
| 302 | |||
| 303 | Settings::values.motion_device = motion_param.Serialize(); | ||
| 304 | Settings::values.touch_device = touch_param.Serialize(); | ||
| 305 | Settings::values.use_touch_from_button = ui->touch_from_button_checkbox->isChecked(); | ||
| 306 | Settings::values.touch_from_button_map_index = ui->touch_from_button_map->currentIndex(); | ||
| 307 | Settings::values.touch_from_button_maps = touch_from_button_maps; | ||
| 308 | Settings::values.udp_input_address = ui->udp_server->text().toStdString(); | ||
| 309 | Settings::values.udp_input_port = static_cast<u16>(ui->udp_port->text().toInt()); | ||
| 310 | Settings::values.udp_pad_index = static_cast<u8>(ui->udp_pad_index->currentIndex()); | ||
| 311 | input_subsystem->ReloadInputDevices(); | ||
| 312 | |||
| 313 | accept(); | ||
| 314 | } | ||
diff --git a/src/yuzu/configuration/configure_motion_touch.h b/src/yuzu/configuration/configure_motion_touch.h new file mode 100644 index 000000000..3d4b5d659 --- /dev/null +++ b/src/yuzu/configuration/configure_motion_touch.h | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | // Copyright 2018 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 <memory> | ||
| 8 | #include <QDialog> | ||
| 9 | #include "common/param_package.h" | ||
| 10 | |||
| 11 | class QLabel; | ||
| 12 | class QPushButton; | ||
| 13 | class QVBoxLayout; | ||
| 14 | |||
| 15 | namespace InputCommon { | ||
| 16 | class InputSubsystem; | ||
| 17 | } | ||
| 18 | |||
| 19 | namespace InputCommon::CemuhookUDP { | ||
| 20 | class CalibrationConfigurationJob; | ||
| 21 | } | ||
| 22 | |||
| 23 | namespace Ui { | ||
| 24 | class ConfigureMotionTouch; | ||
| 25 | } | ||
| 26 | |||
| 27 | /// A dialog for touchpad calibration configuration. | ||
| 28 | class CalibrationConfigurationDialog : public QDialog { | ||
| 29 | Q_OBJECT | ||
| 30 | public: | ||
| 31 | explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port, | ||
| 32 | u8 pad_index, u16 client_id); | ||
| 33 | ~CalibrationConfigurationDialog() override; | ||
| 34 | |||
| 35 | private: | ||
| 36 | Q_INVOKABLE void UpdateLabelText(const QString& text); | ||
| 37 | Q_INVOKABLE void UpdateButtonText(const QString& text); | ||
| 38 | |||
| 39 | QVBoxLayout* layout; | ||
| 40 | QLabel* status_label; | ||
| 41 | QPushButton* cancel_button; | ||
| 42 | std::unique_ptr<InputCommon::CemuhookUDP::CalibrationConfigurationJob> job; | ||
| 43 | |||
| 44 | // Configuration results | ||
| 45 | bool completed{}; | ||
| 46 | u16 min_x{}; | ||
| 47 | u16 min_y{}; | ||
| 48 | u16 max_x{}; | ||
| 49 | u16 max_y{}; | ||
| 50 | |||
| 51 | friend class ConfigureMotionTouch; | ||
| 52 | }; | ||
| 53 | |||
| 54 | class ConfigureMotionTouch : public QDialog { | ||
| 55 | Q_OBJECT | ||
| 56 | |||
| 57 | public: | ||
| 58 | explicit ConfigureMotionTouch(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_); | ||
| 59 | ~ConfigureMotionTouch() override; | ||
| 60 | |||
| 61 | public slots: | ||
| 62 | void ApplyConfiguration(); | ||
| 63 | |||
| 64 | private slots: | ||
| 65 | void OnCemuhookUDPTest(); | ||
| 66 | void OnConfigureTouchCalibration(); | ||
| 67 | void OnConfigureTouchFromButton(); | ||
| 68 | |||
| 69 | private: | ||
| 70 | void closeEvent(QCloseEvent* event) override; | ||
| 71 | Q_INVOKABLE void ShowUDPTestResult(bool result); | ||
| 72 | void SetConfiguration(); | ||
| 73 | void UpdateUiDisplay(); | ||
| 74 | void ConnectEvents(); | ||
| 75 | bool CanCloseDialog(); | ||
| 76 | |||
| 77 | InputCommon::InputSubsystem* input_subsystem; | ||
| 78 | |||
| 79 | std::unique_ptr<Ui::ConfigureMotionTouch> ui; | ||
| 80 | |||
| 81 | // Coordinate system of the CemuhookUDP touch provider | ||
| 82 | int min_x{}; | ||
| 83 | int min_y{}; | ||
| 84 | int max_x{}; | ||
| 85 | int max_y{}; | ||
| 86 | |||
| 87 | bool udp_test_in_progress{}; | ||
| 88 | |||
| 89 | std::vector<Settings::TouchFromButtonMap> touch_from_button_maps; | ||
| 90 | }; | ||
diff --git a/src/yuzu/configuration/configure_motion_touch.ui b/src/yuzu/configuration/configure_motion_touch.ui new file mode 100644 index 000000000..602cf8cd8 --- /dev/null +++ b/src/yuzu/configuration/configure_motion_touch.ui | |||
| @@ -0,0 +1,327 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureMotionTouch</class> | ||
| 4 | <widget class="QDialog" name="ConfigureMotionTouch"> | ||
| 5 | <property name="windowTitle"> | ||
| 6 | <string>Configure Motion / Touch</string> | ||
| 7 | </property> | ||
| 8 | <property name="geometry"> | ||
| 9 | <rect> | ||
| 10 | <x>0</x> | ||
| 11 | <y>0</y> | ||
| 12 | <width>500</width> | ||
| 13 | <height>450</height> | ||
| 14 | </rect> | ||
| 15 | </property> | ||
| 16 | <layout class="QVBoxLayout"> | ||
| 17 | <item> | ||
| 18 | <widget class="QGroupBox" name="motion_group_box"> | ||
| 19 | <property name="title"> | ||
| 20 | <string>Motion</string> | ||
| 21 | </property> | ||
| 22 | <layout class="QVBoxLayout"> | ||
| 23 | <item> | ||
| 24 | <layout class="QHBoxLayout"> | ||
| 25 | <item> | ||
| 26 | <widget class="QLabel" name="motion_provider_label"> | ||
| 27 | <property name="text"> | ||
| 28 | <string>Motion Provider:</string> | ||
| 29 | </property> | ||
| 30 | </widget> | ||
| 31 | </item> | ||
| 32 | <item> | ||
| 33 | <widget class="QComboBox" name="motion_provider"/> | ||
| 34 | </item> | ||
| 35 | </layout> | ||
| 36 | </item> | ||
| 37 | <item> | ||
| 38 | <layout class="QHBoxLayout"> | ||
| 39 | <item> | ||
| 40 | <widget class="QLabel" name="motion_sensitivity_label"> | ||
| 41 | <property name="text"> | ||
| 42 | <string>Sensitivity:</string> | ||
| 43 | </property> | ||
| 44 | </widget> | ||
| 45 | </item> | ||
| 46 | <item> | ||
| 47 | <widget class="QDoubleSpinBox" name="motion_sensitivity"> | ||
| 48 | <property name="alignment"> | ||
| 49 | <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||
| 50 | </property> | ||
| 51 | <property name="decimals"> | ||
| 52 | <number>4</number> | ||
| 53 | </property> | ||
| 54 | <property name="minimum"> | ||
| 55 | <double>0.010000000000000</double> | ||
| 56 | </property> | ||
| 57 | <property name="maximum"> | ||
| 58 | <double>10.000000000000000</double> | ||
| 59 | </property> | ||
| 60 | <property name="singleStep"> | ||
| 61 | <double>0.001000000000000</double> | ||
| 62 | </property> | ||
| 63 | <property name="value"> | ||
| 64 | <double>0.010000000000000</double> | ||
| 65 | </property> | ||
| 66 | </widget> | ||
| 67 | </item> | ||
| 68 | </layout> | ||
| 69 | </item> | ||
| 70 | </layout> | ||
| 71 | </widget> | ||
| 72 | </item> | ||
| 73 | <item> | ||
| 74 | <widget class="QGroupBox" name="touch_group_box"> | ||
| 75 | <property name="title"> | ||
| 76 | <string>Touch</string> | ||
| 77 | </property> | ||
| 78 | <layout class="QVBoxLayout"> | ||
| 79 | <item> | ||
| 80 | <layout class="QHBoxLayout"> | ||
| 81 | <item> | ||
| 82 | <widget class="QLabel" name="touch_provider_label"> | ||
| 83 | <property name="text"> | ||
| 84 | <string>Touch Provider:</string> | ||
| 85 | </property> | ||
| 86 | </widget> | ||
| 87 | </item> | ||
| 88 | <item> | ||
| 89 | <widget class="QComboBox" name="touch_provider"/> | ||
| 90 | </item> | ||
| 91 | </layout> | ||
| 92 | </item> | ||
| 93 | <item> | ||
| 94 | <layout class="QHBoxLayout"> | ||
| 95 | <item> | ||
| 96 | <widget class="QLabel" name="touch_calibration_label"> | ||
| 97 | <property name="text"> | ||
| 98 | <string>Calibration:</string> | ||
| 99 | </property> | ||
| 100 | </widget> | ||
| 101 | </item> | ||
| 102 | <item> | ||
| 103 | <widget class="QLabel" name="touch_calibration"> | ||
| 104 | <property name="text"> | ||
| 105 | <string>(100, 50) - (1800, 850)</string> | ||
| 106 | </property> | ||
| 107 | <property name="alignment"> | ||
| 108 | <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||
| 109 | </property> | ||
| 110 | </widget> | ||
| 111 | </item> | ||
| 112 | <item> | ||
| 113 | <widget class="QPushButton" name="touch_calibration_config"> | ||
| 114 | <property name="sizePolicy"> | ||
| 115 | <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||
| 116 | <horstretch>0</horstretch> | ||
| 117 | <verstretch>0</verstretch> | ||
| 118 | </sizepolicy> | ||
| 119 | </property> | ||
| 120 | <property name="text"> | ||
| 121 | <string>Configure</string> | ||
| 122 | </property> | ||
| 123 | </widget> | ||
| 124 | </item> | ||
| 125 | </layout> | ||
| 126 | </item> | ||
| 127 | <item> | ||
| 128 | <layout class="QHBoxLayout"> | ||
| 129 | <item> | ||
| 130 | <widget class="QCheckBox" name="touch_from_button_checkbox"> | ||
| 131 | <property name="sizePolicy"> | ||
| 132 | <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||
| 133 | <horstretch>0</horstretch> | ||
| 134 | <verstretch>0</verstretch> | ||
| 135 | </sizepolicy> | ||
| 136 | </property> | ||
| 137 | <property name="text"> | ||
| 138 | <string>Use button mapping:</string> | ||
| 139 | </property> | ||
| 140 | </widget> | ||
| 141 | </item> | ||
| 142 | <item> | ||
| 143 | <widget class="QComboBox" name="touch_from_button_map"/> | ||
| 144 | </item> | ||
| 145 | <item> | ||
| 146 | <widget class="QPushButton" name="touch_from_button_config_btn"> | ||
| 147 | <property name="sizePolicy"> | ||
| 148 | <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||
| 149 | <horstretch>0</horstretch> | ||
| 150 | <verstretch>0</verstretch> | ||
| 151 | </sizepolicy> | ||
| 152 | </property> | ||
| 153 | <property name="text"> | ||
| 154 | <string>Configure</string> | ||
| 155 | </property> | ||
| 156 | </widget> | ||
| 157 | </item> | ||
| 158 | </layout> | ||
| 159 | </item> | ||
| 160 | </layout> | ||
| 161 | </widget> | ||
| 162 | </item> | ||
| 163 | <item> | ||
| 164 | <widget class="QGroupBox" name="udp_config_group_box"> | ||
| 165 | <property name="title"> | ||
| 166 | <string>CemuhookUDP Config</string> | ||
| 167 | </property> | ||
| 168 | <layout class="QVBoxLayout"> | ||
| 169 | <item> | ||
| 170 | <widget class="QLabel" name="udp_help"> | ||
| 171 | <property name="text"> | ||
| 172 | <string>You may use any Cemuhook compatible UDP input source to provide motion and touch input.</string> | ||
| 173 | </property> | ||
| 174 | <property name="alignment"> | ||
| 175 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> | ||
| 176 | </property> | ||
| 177 | <property name="wordWrap"> | ||
| 178 | <bool>true</bool> | ||
| 179 | </property> | ||
| 180 | </widget> | ||
| 181 | </item> | ||
| 182 | <item> | ||
| 183 | <layout class="QHBoxLayout"> | ||
| 184 | <item> | ||
| 185 | <widget class="QLabel" name="udp_server_label"> | ||
| 186 | <property name="text"> | ||
| 187 | <string>Server:</string> | ||
| 188 | </property> | ||
| 189 | </widget> | ||
| 190 | </item> | ||
| 191 | <item> | ||
| 192 | <widget class="QLineEdit" name="udp_server"> | ||
| 193 | <property name="sizePolicy"> | ||
| 194 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 195 | <horstretch>0</horstretch> | ||
| 196 | <verstretch>0</verstretch> | ||
| 197 | </sizepolicy> | ||
| 198 | </property> | ||
| 199 | </widget> | ||
| 200 | </item> | ||
| 201 | </layout> | ||
| 202 | </item> | ||
| 203 | <item> | ||
| 204 | <layout class="QHBoxLayout"> | ||
| 205 | <item> | ||
| 206 | <widget class="QLabel" name="udp_port_label"> | ||
| 207 | <property name="text"> | ||
| 208 | <string>Port:</string> | ||
| 209 | </property> | ||
| 210 | </widget> | ||
| 211 | </item> | ||
| 212 | <item> | ||
| 213 | <widget class="QLineEdit" name="udp_port"> | ||
| 214 | <property name="sizePolicy"> | ||
| 215 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 216 | <horstretch>0</horstretch> | ||
| 217 | <verstretch>0</verstretch> | ||
| 218 | </sizepolicy> | ||
| 219 | </property> | ||
| 220 | </widget> | ||
| 221 | </item> | ||
| 222 | </layout> | ||
| 223 | </item> | ||
| 224 | <item> | ||
| 225 | <layout class="QHBoxLayout"> | ||
| 226 | <item> | ||
| 227 | <widget class="QLabel" name="udp_pad_index_label"> | ||
| 228 | <property name="text"> | ||
| 229 | <string>Pad:</string> | ||
| 230 | </property> | ||
| 231 | </widget> | ||
| 232 | </item> | ||
| 233 | <item> | ||
| 234 | <widget class="QComboBox" name="udp_pad_index"> | ||
| 235 | <item> | ||
| 236 | <property name="text"> | ||
| 237 | <string>Pad 1</string> | ||
| 238 | </property> | ||
| 239 | </item> | ||
| 240 | <item> | ||
| 241 | <property name="text"> | ||
| 242 | <string>Pad 2</string> | ||
| 243 | </property> | ||
| 244 | </item> | ||
| 245 | <item> | ||
| 246 | <property name="text"> | ||
| 247 | <string>Pad 3</string> | ||
| 248 | </property> | ||
| 249 | </item> | ||
| 250 | <item> | ||
| 251 | <property name="text"> | ||
| 252 | <string>Pad 4</string> | ||
| 253 | </property> | ||
| 254 | </item> | ||
| 255 | </widget> | ||
| 256 | </item> | ||
| 257 | </layout> | ||
| 258 | </item> | ||
| 259 | <item> | ||
| 260 | <layout class="QHBoxLayout"> | ||
| 261 | <item> | ||
| 262 | <widget class="QLabel" name="udp_learn_more"> | ||
| 263 | <property name="text"> | ||
| 264 | <string>Learn More</string> | ||
| 265 | </property> | ||
| 266 | </widget> | ||
| 267 | </item> | ||
| 268 | <item> | ||
| 269 | <widget class="QPushButton" name="udp_test"> | ||
| 270 | <property name="sizePolicy"> | ||
| 271 | <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||
| 272 | <horstretch>0</horstretch> | ||
| 273 | <verstretch>0</verstretch> | ||
| 274 | </sizepolicy> | ||
| 275 | </property> | ||
| 276 | <property name="text"> | ||
| 277 | <string>Test</string> | ||
| 278 | </property> | ||
| 279 | </widget> | ||
| 280 | </item> | ||
| 281 | </layout> | ||
| 282 | </item> | ||
| 283 | </layout> | ||
| 284 | </widget> | ||
| 285 | </item> | ||
| 286 | <item> | ||
| 287 | <spacer> | ||
| 288 | <property name="orientation"> | ||
| 289 | <enum>Qt::Vertical</enum> | ||
| 290 | </property> | ||
| 291 | <property name="sizeHint" stdset="0"> | ||
| 292 | <size> | ||
| 293 | <width>167</width> | ||
| 294 | <height>55</height> | ||
| 295 | </size> | ||
| 296 | </property> | ||
| 297 | </spacer> | ||
| 298 | </item> | ||
| 299 | <item> | ||
| 300 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 301 | <property name="standardButtons"> | ||
| 302 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 303 | </property> | ||
| 304 | </widget> | ||
| 305 | </item> | ||
| 306 | </layout> | ||
| 307 | </widget> | ||
| 308 | <resources/> | ||
| 309 | <connections> | ||
| 310 | <connection> | ||
| 311 | <sender>buttonBox</sender> | ||
| 312 | <signal>accepted()</signal> | ||
| 313 | <receiver>ConfigureMotionTouch</receiver> | ||
| 314 | <slot>ApplyConfiguration()</slot> | ||
| 315 | <hints> | ||
| 316 | <hint type="sourcelabel"> | ||
| 317 | <x>220</x> | ||
| 318 | <y>380</y> | ||
| 319 | </hint> | ||
| 320 | <hint type="destinationlabel"> | ||
| 321 | <x>220</x> | ||
| 322 | <y>200</y> | ||
| 323 | </hint> | ||
| 324 | </hints> | ||
| 325 | </connection> | ||
| 326 | </connections> | ||
| 327 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp index 5bcf5ffa8..2af3afda8 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.cpp +++ b/src/yuzu/configuration/configure_mouse_advanced.cpp | |||
| @@ -18,6 +18,16 @@ | |||
| 18 | 18 | ||
| 19 | static QString GetKeyName(int key_code) { | 19 | static QString GetKeyName(int key_code) { |
| 20 | switch (key_code) { | 20 | switch (key_code) { |
| 21 | case Qt::LeftButton: | ||
| 22 | return QObject::tr("Click 0"); | ||
| 23 | case Qt::RightButton: | ||
| 24 | return QObject::tr("Click 1"); | ||
| 25 | case Qt::MiddleButton: | ||
| 26 | return QObject::tr("Click 2"); | ||
| 27 | case Qt::BackButton: | ||
| 28 | return QObject::tr("Click 3"); | ||
| 29 | case Qt::ForwardButton: | ||
| 30 | return QObject::tr("Click 4"); | ||
| 21 | case Qt::Key_Shift: | 31 | case Qt::Key_Shift: |
| 22 | return QObject::tr("Shift"); | 32 | return QObject::tr("Shift"); |
| 23 | case Qt::Key_Control: | 33 | case Qt::Key_Control: |
| @@ -66,8 +76,10 @@ static QString ButtonToText(const Common::ParamPackage& param) { | |||
| 66 | return QObject::tr("[unknown]"); | 76 | return QObject::tr("[unknown]"); |
| 67 | } | 77 | } |
| 68 | 78 | ||
| 69 | ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) | 79 | ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent, |
| 70 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), | 80 | InputCommon::InputSubsystem* input_subsystem_) |
| 81 | : QDialog(parent), | ||
| 82 | ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), input_subsystem{input_subsystem_}, | ||
| 71 | timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { | 83 | timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { |
| 72 | ui->setupUi(this); | 84 | ui->setupUi(this); |
| 73 | setFocusPolicy(Qt::ClickFocus); | 85 | setFocusPolicy(Qt::ClickFocus); |
| @@ -188,9 +200,9 @@ void ConfigureMouseAdvanced::HandleClick( | |||
| 188 | button->setText(tr("[press key]")); | 200 | button->setText(tr("[press key]")); |
| 189 | button->setFocus(); | 201 | button->setFocus(); |
| 190 | 202 | ||
| 191 | // Keyboard keys can only be used as button devices | 203 | // Keyboard keys or mouse buttons can only be used as button devices |
| 192 | want_keyboard_keys = type == InputCommon::Polling::DeviceType::Button; | 204 | want_keyboard_mouse = type == InputCommon::Polling::DeviceType::Button; |
| 193 | if (want_keyboard_keys) { | 205 | if (want_keyboard_mouse) { |
| 194 | const auto iter = std::find(button_map.begin(), button_map.end(), button); | 206 | const auto iter = std::find(button_map.begin(), button_map.end(), button); |
| 195 | ASSERT(iter != button_map.end()); | 207 | ASSERT(iter != button_map.end()); |
| 196 | const auto index = std::distance(button_map.begin(), iter); | 208 | const auto index = std::distance(button_map.begin(), iter); |
| @@ -199,27 +211,29 @@ void ConfigureMouseAdvanced::HandleClick( | |||
| 199 | 211 | ||
| 200 | input_setter = new_input_setter; | 212 | input_setter = new_input_setter; |
| 201 | 213 | ||
| 202 | device_pollers = InputCommon::Polling::GetPollers(type); | 214 | device_pollers = input_subsystem->GetPollers(type); |
| 203 | 215 | ||
| 204 | for (auto& poller : device_pollers) { | 216 | for (auto& poller : device_pollers) { |
| 205 | poller->Start(); | 217 | poller->Start(); |
| 206 | } | 218 | } |
| 207 | 219 | ||
| 208 | grabKeyboard(); | 220 | QWidget::grabMouse(); |
| 209 | grabMouse(); | 221 | QWidget::grabKeyboard(); |
| 210 | timeout_timer->start(5000); // Cancel after 5 seconds | 222 | |
| 211 | poll_timer->start(200); // Check for new inputs every 200ms | 223 | timeout_timer->start(2500); // Cancel after 2.5 seconds |
| 224 | poll_timer->start(50); // Check for new inputs every 50ms | ||
| 212 | } | 225 | } |
| 213 | 226 | ||
| 214 | void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) { | 227 | void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) { |
| 215 | releaseKeyboard(); | ||
| 216 | releaseMouse(); | ||
| 217 | timeout_timer->stop(); | 228 | timeout_timer->stop(); |
| 218 | poll_timer->stop(); | 229 | poll_timer->stop(); |
| 219 | for (auto& poller : device_pollers) { | 230 | for (auto& poller : device_pollers) { |
| 220 | poller->Stop(); | 231 | poller->Stop(); |
| 221 | } | 232 | } |
| 222 | 233 | ||
| 234 | QWidget::releaseMouse(); | ||
| 235 | QWidget::releaseKeyboard(); | ||
| 236 | |||
| 223 | if (!abort) { | 237 | if (!abort) { |
| 224 | (*input_setter)(params); | 238 | (*input_setter)(params); |
| 225 | } | 239 | } |
| @@ -228,13 +242,29 @@ void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params | |||
| 228 | input_setter = std::nullopt; | 242 | input_setter = std::nullopt; |
| 229 | } | 243 | } |
| 230 | 244 | ||
| 245 | void ConfigureMouseAdvanced::mousePressEvent(QMouseEvent* event) { | ||
| 246 | if (!input_setter || !event) { | ||
| 247 | return; | ||
| 248 | } | ||
| 249 | |||
| 250 | if (want_keyboard_mouse) { | ||
| 251 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())}, | ||
| 252 | false); | ||
| 253 | } else { | ||
| 254 | // We don't want any mouse buttons, so don't stop polling | ||
| 255 | return; | ||
| 256 | } | ||
| 257 | |||
| 258 | SetPollingResult({}, true); | ||
| 259 | } | ||
| 260 | |||
| 231 | void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { | 261 | void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { |
| 232 | if (!input_setter || !event) { | 262 | if (!input_setter || !event) { |
| 233 | return; | 263 | return; |
| 234 | } | 264 | } |
| 235 | 265 | ||
| 236 | if (event->key() != Qt::Key_Escape) { | 266 | if (event->key() != Qt::Key_Escape) { |
| 237 | if (want_keyboard_keys) { | 267 | if (want_keyboard_mouse) { |
| 238 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, | 268 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, |
| 239 | false); | 269 | false); |
| 240 | } else { | 270 | } else { |
diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h index 342b82412..65b6fca9a 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.h +++ b/src/yuzu/configuration/configure_mouse_advanced.h | |||
| @@ -8,12 +8,14 @@ | |||
| 8 | #include <optional> | 8 | #include <optional> |
| 9 | #include <QDialog> | 9 | #include <QDialog> |
| 10 | 10 | ||
| 11 | #include "core/settings.h" | ||
| 12 | |||
| 13 | class QCheckBox; | 11 | class QCheckBox; |
| 14 | class QPushButton; | 12 | class QPushButton; |
| 15 | class QTimer; | 13 | class QTimer; |
| 16 | 14 | ||
| 15 | namespace InputCommon { | ||
| 16 | class InputSubsystem; | ||
| 17 | } | ||
| 18 | |||
| 17 | namespace Ui { | 19 | namespace Ui { |
| 18 | class ConfigureMouseAdvanced; | 20 | class ConfigureMouseAdvanced; |
| 19 | } | 21 | } |
| @@ -22,7 +24,7 @@ class ConfigureMouseAdvanced : public QDialog { | |||
| 22 | Q_OBJECT | 24 | Q_OBJECT |
| 23 | 25 | ||
| 24 | public: | 26 | public: |
| 25 | explicit ConfigureMouseAdvanced(QWidget* parent); | 27 | explicit ConfigureMouseAdvanced(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_); |
| 26 | ~ConfigureMouseAdvanced() override; | 28 | ~ConfigureMouseAdvanced() override; |
| 27 | 29 | ||
| 28 | void ApplyConfiguration(); | 30 | void ApplyConfiguration(); |
| @@ -49,11 +51,16 @@ private: | |||
| 49 | /// Finish polling and configure input using the input_setter | 51 | /// Finish polling and configure input using the input_setter |
| 50 | void SetPollingResult(const Common::ParamPackage& params, bool abort); | 52 | void SetPollingResult(const Common::ParamPackage& params, bool abort); |
| 51 | 53 | ||
| 54 | /// Handle mouse button press events. | ||
| 55 | void mousePressEvent(QMouseEvent* event) override; | ||
| 56 | |||
| 52 | /// Handle key press events. | 57 | /// Handle key press events. |
| 53 | void keyPressEvent(QKeyEvent* event) override; | 58 | void keyPressEvent(QKeyEvent* event) override; |
| 54 | 59 | ||
| 55 | std::unique_ptr<Ui::ConfigureMouseAdvanced> ui; | 60 | std::unique_ptr<Ui::ConfigureMouseAdvanced> ui; |
| 56 | 61 | ||
| 62 | InputCommon::InputSubsystem* input_subsystem; | ||
| 63 | |||
| 57 | /// This will be the the setting function when an input is awaiting configuration. | 64 | /// This will be the the setting function when an input is awaiting configuration. |
| 58 | std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; | 65 | std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; |
| 59 | 66 | ||
| @@ -67,5 +74,5 @@ private: | |||
| 67 | 74 | ||
| 68 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, | 75 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, |
| 69 | /// keyboard events are ignored. | 76 | /// keyboard events are ignored. |
| 70 | bool want_keyboard_keys = false; | 77 | bool want_keyboard_mouse = false; |
| 71 | }; | 78 | }; |
diff --git a/src/yuzu/configuration/configure_mouse_advanced.ui b/src/yuzu/configuration/configure_mouse_advanced.ui index 08245ecf0..74552fdbd 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.ui +++ b/src/yuzu/configuration/configure_mouse_advanced.ui | |||
| @@ -6,13 +6,18 @@ | |||
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>250</width> | 9 | <width>310</width> |
| 10 | <height>261</height> | 10 | <height>193</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Configure Mouse</string> | 14 | <string>Configure Mouse</string> |
| 15 | </property> | 15 | </property> |
| 16 | <property name="styleSheet"> | ||
| 17 | <string notr="true">QPushButton { | ||
| 18 | min-width: 55px; | ||
| 19 | }</string> | ||
| 20 | </property> | ||
| 16 | <layout class="QVBoxLayout" name="verticalLayout"> | 21 | <layout class="QVBoxLayout" name="verticalLayout"> |
| 17 | <item> | 22 | <item> |
| 18 | <widget class="QGroupBox" name="gridGroupBox"> | 23 | <widget class="QGroupBox" name="gridGroupBox"> |
| @@ -20,81 +25,33 @@ | |||
| 20 | <string>Mouse Buttons</string> | 25 | <string>Mouse Buttons</string> |
| 21 | </property> | 26 | </property> |
| 22 | <layout class="QGridLayout" name="gridLayout"> | 27 | <layout class="QGridLayout" name="gridLayout"> |
| 23 | <item row="0" column="4"> | 28 | <item row="3" column="5"> |
| 24 | <spacer name="horizontalSpacer_2"> | 29 | <layout class="QVBoxLayout" name="verticalLayout_6"> |
| 25 | <property name="orientation"> | ||
| 26 | <enum>Qt::Horizontal</enum> | ||
| 27 | </property> | ||
| 28 | <property name="sizeType"> | ||
| 29 | <enum>QSizePolicy::Fixed</enum> | ||
| 30 | </property> | ||
| 31 | <property name="sizeHint" stdset="0"> | ||
| 32 | <size> | ||
| 33 | <width>20</width> | ||
| 34 | <height>20</height> | ||
| 35 | </size> | ||
| 36 | </property> | ||
| 37 | </spacer> | ||
| 38 | </item> | ||
| 39 | <item row="0" column="3"> | ||
| 40 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 41 | <item> | 30 | <item> |
| 42 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | 31 | <layout class="QHBoxLayout" name="horizontalLayout_5"> |
| 43 | <item> | 32 | <item> |
| 44 | <widget class="QLabel" name="label_3"> | 33 | <widget class="QLabel" name="label_5"> |
| 45 | <property name="text"> | 34 | <property name="text"> |
| 46 | <string>Right:</string> | 35 | <string>Forward:</string> |
| 47 | </property> | 36 | </property> |
| 48 | </widget> | 37 | </widget> |
| 49 | </item> | 38 | </item> |
| 50 | </layout> | 39 | </layout> |
| 51 | </item> | 40 | </item> |
| 52 | <item> | 41 | <item> |
| 53 | <widget class="QPushButton" name="right_button"> | 42 | <widget class="QPushButton" name="forward_button"> |
| 54 | <property name="minimumSize"> | 43 | <property name="minimumSize"> |
| 55 | <size> | 44 | <size> |
| 56 | <width>75</width> | 45 | <width>57</width> |
| 57 | <height>0</height> | 46 | <height>0</height> |
| 58 | </size> | 47 | </size> |
| 59 | </property> | 48 | </property> |
| 60 | <property name="text"> | 49 | <property name="maximumSize"> |
| 61 | <string/> | 50 | <size> |
| 51 | <width>16777215</width> | ||
| 52 | <height>16777215</height> | ||
| 53 | </size> | ||
| 62 | </property> | 54 | </property> |
| 63 | </widget> | ||
| 64 | </item> | ||
| 65 | </layout> | ||
| 66 | </item> | ||
| 67 | <item row="0" column="0"> | ||
| 68 | <spacer name="horizontalSpacer"> | ||
| 69 | <property name="orientation"> | ||
| 70 | <enum>Qt::Horizontal</enum> | ||
| 71 | </property> | ||
| 72 | <property name="sizeType"> | ||
| 73 | <enum>QSizePolicy::Fixed</enum> | ||
| 74 | </property> | ||
| 75 | <property name="sizeHint" stdset="0"> | ||
| 76 | <size> | ||
| 77 | <width>20</width> | ||
| 78 | <height>20</height> | ||
| 79 | </size> | ||
| 80 | </property> | ||
| 81 | </spacer> | ||
| 82 | </item> | ||
| 83 | <item row="2" column="1"> | ||
| 84 | <layout class="QVBoxLayout" name="verticalLayout_3"> | ||
| 85 | <item> | ||
| 86 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 87 | <item> | ||
| 88 | <widget class="QLabel" name="label_2"> | ||
| 89 | <property name="text"> | ||
| 90 | <string>Middle:</string> | ||
| 91 | </property> | ||
| 92 | </widget> | ||
| 93 | </item> | ||
| 94 | </layout> | ||
| 95 | </item> | ||
| 96 | <item> | ||
| 97 | <widget class="QPushButton" name="middle_button"> | ||
| 98 | <property name="text"> | 55 | <property name="text"> |
| 99 | <string/> | 56 | <string/> |
| 100 | </property> | 57 | </property> |
| @@ -123,6 +80,12 @@ | |||
| 123 | </item> | 80 | </item> |
| 124 | <item> | 81 | <item> |
| 125 | <widget class="QPushButton" name="back_button"> | 82 | <widget class="QPushButton" name="back_button"> |
| 83 | <property name="minimumSize"> | ||
| 84 | <size> | ||
| 85 | <width>57</width> | ||
| 86 | <height>0</height> | ||
| 87 | </size> | ||
| 88 | </property> | ||
| 126 | <property name="text"> | 89 | <property name="text"> |
| 127 | <string/> | 90 | <string/> |
| 128 | </property> | 91 | </property> |
| @@ -147,7 +110,7 @@ | |||
| 147 | <widget class="QPushButton" name="left_button"> | 110 | <widget class="QPushButton" name="left_button"> |
| 148 | <property name="minimumSize"> | 111 | <property name="minimumSize"> |
| 149 | <size> | 112 | <size> |
| 150 | <width>75</width> | 113 | <width>57</width> |
| 151 | <height>0</height> | 114 | <height>0</height> |
| 152 | </size> | 115 | </size> |
| 153 | </property> | 116 | </property> |
| @@ -158,21 +121,99 @@ | |||
| 158 | </item> | 121 | </item> |
| 159 | </layout> | 122 | </layout> |
| 160 | </item> | 123 | </item> |
| 161 | <item row="3" column="3"> | 124 | <item row="0" column="3"> |
| 162 | <layout class="QVBoxLayout" name="verticalLayout_6"> | 125 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
| 163 | <item> | 126 | <item> |
| 164 | <layout class="QHBoxLayout" name="horizontalLayout_5"> | 127 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 165 | <item> | 128 | <item> |
| 166 | <widget class="QLabel" name="label_5"> | 129 | <widget class="QLabel" name="label_2"> |
| 167 | <property name="text"> | 130 | <property name="text"> |
| 168 | <string>Forward:</string> | 131 | <string>Middle:</string> |
| 169 | </property> | 132 | </property> |
| 170 | </widget> | 133 | </widget> |
| 171 | </item> | 134 | </item> |
| 172 | </layout> | 135 | </layout> |
| 173 | </item> | 136 | </item> |
| 174 | <item> | 137 | <item> |
| 175 | <widget class="QPushButton" name="forward_button"> | 138 | <widget class="QPushButton" name="middle_button"> |
| 139 | <property name="minimumSize"> | ||
| 140 | <size> | ||
| 141 | <width>57</width> | ||
| 142 | <height>0</height> | ||
| 143 | </size> | ||
| 144 | </property> | ||
| 145 | <property name="maximumSize"> | ||
| 146 | <size> | ||
| 147 | <width>16777215</width> | ||
| 148 | <height>16777215</height> | ||
| 149 | </size> | ||
| 150 | </property> | ||
| 151 | <property name="text"> | ||
| 152 | <string/> | ||
| 153 | </property> | ||
| 154 | </widget> | ||
| 155 | </item> | ||
| 156 | </layout> | ||
| 157 | </item> | ||
| 158 | <item row="0" column="6"> | ||
| 159 | <spacer name="horizontalSpacer_2"> | ||
| 160 | <property name="orientation"> | ||
| 161 | <enum>Qt::Horizontal</enum> | ||
| 162 | </property> | ||
| 163 | <property name="sizeType"> | ||
| 164 | <enum>QSizePolicy::Fixed</enum> | ||
| 165 | </property> | ||
| 166 | <property name="sizeHint" stdset="0"> | ||
| 167 | <size> | ||
| 168 | <width>0</width> | ||
| 169 | <height>20</height> | ||
| 170 | </size> | ||
| 171 | </property> | ||
| 172 | </spacer> | ||
| 173 | </item> | ||
| 174 | <item row="0" column="0"> | ||
| 175 | <spacer name="horizontalSpacer"> | ||
| 176 | <property name="orientation"> | ||
| 177 | <enum>Qt::Horizontal</enum> | ||
| 178 | </property> | ||
| 179 | <property name="sizeType"> | ||
| 180 | <enum>QSizePolicy::Fixed</enum> | ||
| 181 | </property> | ||
| 182 | <property name="sizeHint" stdset="0"> | ||
| 183 | <size> | ||
| 184 | <width>0</width> | ||
| 185 | <height>20</height> | ||
| 186 | </size> | ||
| 187 | </property> | ||
| 188 | </spacer> | ||
| 189 | </item> | ||
| 190 | <item row="0" column="5"> | ||
| 191 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 192 | <item> | ||
| 193 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||
| 194 | <item> | ||
| 195 | <widget class="QLabel" name="label_3"> | ||
| 196 | <property name="text"> | ||
| 197 | <string>Right:</string> | ||
| 198 | </property> | ||
| 199 | </widget> | ||
| 200 | </item> | ||
| 201 | </layout> | ||
| 202 | </item> | ||
| 203 | <item> | ||
| 204 | <widget class="QPushButton" name="right_button"> | ||
| 205 | <property name="minimumSize"> | ||
| 206 | <size> | ||
| 207 | <width>57</width> | ||
| 208 | <height>0</height> | ||
| 209 | </size> | ||
| 210 | </property> | ||
| 211 | <property name="maximumSize"> | ||
| 212 | <size> | ||
| 213 | <width>16777215</width> | ||
| 214 | <height>16777215</height> | ||
| 215 | </size> | ||
| 216 | </property> | ||
| 176 | <property name="text"> | 217 | <property name="text"> |
| 177 | <string/> | 218 | <string/> |
| 178 | </property> | 219 | </property> |
| @@ -180,6 +221,32 @@ | |||
| 180 | </item> | 221 | </item> |
| 181 | </layout> | 222 | </layout> |
| 182 | </item> | 223 | </item> |
| 224 | <item row="0" column="2"> | ||
| 225 | <spacer name="horizontalSpacer_4"> | ||
| 226 | <property name="orientation"> | ||
| 227 | <enum>Qt::Horizontal</enum> | ||
| 228 | </property> | ||
| 229 | <property name="sizeHint" stdset="0"> | ||
| 230 | <size> | ||
| 231 | <width>0</width> | ||
| 232 | <height>20</height> | ||
| 233 | </size> | ||
| 234 | </property> | ||
| 235 | </spacer> | ||
| 236 | </item> | ||
| 237 | <item row="0" column="4"> | ||
| 238 | <spacer name="horizontalSpacer_5"> | ||
| 239 | <property name="orientation"> | ||
| 240 | <enum>Qt::Horizontal</enum> | ||
| 241 | </property> | ||
| 242 | <property name="sizeHint" stdset="0"> | ||
| 243 | <size> | ||
| 244 | <width>0</width> | ||
| 245 | <height>20</height> | ||
| 246 | </size> | ||
| 247 | </property> | ||
| 248 | </spacer> | ||
| 249 | </item> | ||
| 183 | </layout> | 250 | </layout> |
| 184 | </widget> | 251 | </widget> |
| 185 | </item> | 252 | </item> |
| @@ -187,15 +254,39 @@ | |||
| 187 | <layout class="QHBoxLayout" name="horizontalLayout_6"> | 254 | <layout class="QHBoxLayout" name="horizontalLayout_6"> |
| 188 | <item> | 255 | <item> |
| 189 | <widget class="QPushButton" name="buttonClearAll"> | 256 | <widget class="QPushButton" name="buttonClearAll"> |
| 257 | <property name="minimumSize"> | ||
| 258 | <size> | ||
| 259 | <width>57</width> | ||
| 260 | <height>0</height> | ||
| 261 | </size> | ||
| 262 | </property> | ||
| 263 | <property name="maximumSize"> | ||
| 264 | <size> | ||
| 265 | <width>16777215</width> | ||
| 266 | <height>16777215</height> | ||
| 267 | </size> | ||
| 268 | </property> | ||
| 190 | <property name="text"> | 269 | <property name="text"> |
| 191 | <string>Clear All</string> | 270 | <string>Clear</string> |
| 192 | </property> | 271 | </property> |
| 193 | </widget> | 272 | </widget> |
| 194 | </item> | 273 | </item> |
| 195 | <item> | 274 | <item> |
| 196 | <widget class="QPushButton" name="buttonRestoreDefaults"> | 275 | <widget class="QPushButton" name="buttonRestoreDefaults"> |
| 276 | <property name="minimumSize"> | ||
| 277 | <size> | ||
| 278 | <width>57</width> | ||
| 279 | <height>0</height> | ||
| 280 | </size> | ||
| 281 | </property> | ||
| 282 | <property name="maximumSize"> | ||
| 283 | <size> | ||
| 284 | <width>16777215</width> | ||
| 285 | <height>16777215</height> | ||
| 286 | </size> | ||
| 287 | </property> | ||
| 197 | <property name="text"> | 288 | <property name="text"> |
| 198 | <string>Restore Defaults</string> | 289 | <string>Defaults</string> |
| 199 | </property> | 290 | </property> |
| 200 | </widget> | 291 | </widget> |
| 201 | </item> | 292 | </item> |
| @@ -206,21 +297,24 @@ | |||
| 206 | </property> | 297 | </property> |
| 207 | <property name="sizeHint" stdset="0"> | 298 | <property name="sizeHint" stdset="0"> |
| 208 | <size> | 299 | <size> |
| 209 | <width>40</width> | 300 | <width>0</width> |
| 210 | <height>20</height> | 301 | <height>20</height> |
| 211 | </size> | 302 | </size> |
| 212 | </property> | 303 | </property> |
| 213 | </spacer> | 304 | </spacer> |
| 214 | </item> | 305 | </item> |
| 306 | <item> | ||
| 307 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 308 | <property name="styleSheet"> | ||
| 309 | <string notr="true"/> | ||
| 310 | </property> | ||
| 311 | <property name="standardButtons"> | ||
| 312 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 313 | </property> | ||
| 314 | </widget> | ||
| 315 | </item> | ||
| 215 | </layout> | 316 | </layout> |
| 216 | </item> | 317 | </item> |
| 217 | <item> | ||
| 218 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 219 | <property name="standardButtons"> | ||
| 220 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 221 | </property> | ||
| 222 | </widget> | ||
| 223 | </item> | ||
| 224 | </layout> | 318 | </layout> |
| 225 | </widget> | 319 | </widget> |
| 226 | <resources/> | 320 | <resources/> |
diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp new file mode 100644 index 000000000..15557e4b8 --- /dev/null +++ b/src/yuzu/configuration/configure_touch_from_button.cpp | |||
| @@ -0,0 +1,623 @@ | |||
| 1 | // Copyright 2020 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <QInputDialog> | ||
| 6 | #include <QKeyEvent> | ||
| 7 | #include <QMessageBox> | ||
| 8 | #include <QMouseEvent> | ||
| 9 | #include <QResizeEvent> | ||
| 10 | #include <QStandardItemModel> | ||
| 11 | #include <QTimer> | ||
| 12 | #include "common/param_package.h" | ||
| 13 | #include "core/frontend/framebuffer_layout.h" | ||
| 14 | #include "core/settings.h" | ||
| 15 | #include "input_common/main.h" | ||
| 16 | #include "ui_configure_touch_from_button.h" | ||
| 17 | #include "yuzu/configuration/configure_touch_from_button.h" | ||
| 18 | #include "yuzu/configuration/configure_touch_widget.h" | ||
| 19 | |||
| 20 | static QString GetKeyName(int key_code) { | ||
| 21 | switch (key_code) { | ||
| 22 | case Qt::Key_Shift: | ||
| 23 | return QObject::tr("Shift"); | ||
| 24 | case Qt::Key_Control: | ||
| 25 | return QObject::tr("Ctrl"); | ||
| 26 | case Qt::Key_Alt: | ||
| 27 | return QObject::tr("Alt"); | ||
| 28 | case Qt::Key_Meta: | ||
| 29 | return QString{}; | ||
| 30 | default: | ||
| 31 | return QKeySequence(key_code).toString(); | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | static QString ButtonToText(const Common::ParamPackage& param) { | ||
| 36 | if (!param.Has("engine")) { | ||
| 37 | return QObject::tr("[not set]"); | ||
| 38 | } | ||
| 39 | |||
| 40 | if (param.Get("engine", "") == "keyboard") { | ||
| 41 | return GetKeyName(param.Get("code", 0)); | ||
| 42 | } | ||
| 43 | |||
| 44 | if (param.Get("engine", "") == "sdl") { | ||
| 45 | if (param.Has("hat")) { | ||
| 46 | const QString hat_str = QString::fromStdString(param.Get("hat", "")); | ||
| 47 | const QString direction_str = QString::fromStdString(param.Get("direction", "")); | ||
| 48 | |||
| 49 | return QObject::tr("Hat %1 %2").arg(hat_str, direction_str); | ||
| 50 | } | ||
| 51 | |||
| 52 | if (param.Has("axis")) { | ||
| 53 | const QString axis_str = QString::fromStdString(param.Get("axis", "")); | ||
| 54 | const QString direction_str = QString::fromStdString(param.Get("direction", "")); | ||
| 55 | |||
| 56 | return QObject::tr("Axis %1%2").arg(axis_str, direction_str); | ||
| 57 | } | ||
| 58 | |||
| 59 | if (param.Has("button")) { | ||
| 60 | const QString button_str = QString::fromStdString(param.Get("button", "")); | ||
| 61 | |||
| 62 | return QObject::tr("Button %1").arg(button_str); | ||
| 63 | } | ||
| 64 | |||
| 65 | return {}; | ||
| 66 | } | ||
| 67 | |||
| 68 | return QObject::tr("[unknown]"); | ||
| 69 | } | ||
| 70 | |||
| 71 | ConfigureTouchFromButton::ConfigureTouchFromButton( | ||
| 72 | QWidget* parent, const std::vector<Settings::TouchFromButtonMap>& touch_maps, | ||
| 73 | InputCommon::InputSubsystem* input_subsystem_, const int default_index) | ||
| 74 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureTouchFromButton>()), | ||
| 75 | touch_maps(touch_maps), input_subsystem{input_subsystem_}, selected_index(default_index), | ||
| 76 | timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { | ||
| 77 | ui->setupUi(this); | ||
| 78 | binding_list_model = new QStandardItemModel(0, 3, this); | ||
| 79 | binding_list_model->setHorizontalHeaderLabels( | ||
| 80 | {tr("Button"), tr("X", "X axis"), tr("Y", "Y axis")}); | ||
| 81 | ui->binding_list->setModel(binding_list_model); | ||
| 82 | ui->bottom_screen->SetCoordLabel(ui->coord_label); | ||
| 83 | |||
| 84 | SetConfiguration(); | ||
| 85 | UpdateUiDisplay(); | ||
| 86 | ConnectEvents(); | ||
| 87 | } | ||
| 88 | |||
| 89 | ConfigureTouchFromButton::~ConfigureTouchFromButton() = default; | ||
| 90 | |||
| 91 | void ConfigureTouchFromButton::showEvent(QShowEvent* ev) { | ||
| 92 | QWidget::showEvent(ev); | ||
| 93 | |||
| 94 | // width values are not valid in the constructor | ||
| 95 | const int w = | ||
| 96 | ui->binding_list->viewport()->contentsRect().width() / binding_list_model->columnCount(); | ||
| 97 | if (w <= 0) { | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | ui->binding_list->setColumnWidth(0, w); | ||
| 101 | ui->binding_list->setColumnWidth(1, w); | ||
| 102 | ui->binding_list->setColumnWidth(2, w); | ||
| 103 | } | ||
| 104 | |||
| 105 | void ConfigureTouchFromButton::SetConfiguration() { | ||
| 106 | for (const auto& touch_map : touch_maps) { | ||
| 107 | ui->mapping->addItem(QString::fromStdString(touch_map.name)); | ||
| 108 | } | ||
| 109 | |||
| 110 | ui->mapping->setCurrentIndex(selected_index); | ||
| 111 | } | ||
| 112 | |||
| 113 | void ConfigureTouchFromButton::UpdateUiDisplay() { | ||
| 114 | ui->button_delete->setEnabled(touch_maps.size() > 1); | ||
| 115 | ui->button_delete_bind->setEnabled(false); | ||
| 116 | |||
| 117 | binding_list_model->removeRows(0, binding_list_model->rowCount()); | ||
| 118 | |||
| 119 | for (const auto& button_str : touch_maps[selected_index].buttons) { | ||
| 120 | Common::ParamPackage package{button_str}; | ||
| 121 | QStandardItem* button = new QStandardItem(ButtonToText(package)); | ||
| 122 | button->setData(QString::fromStdString(button_str)); | ||
| 123 | button->setEditable(false); | ||
| 124 | QStandardItem* xcoord = new QStandardItem(QString::number(package.Get("x", 0))); | ||
| 125 | QStandardItem* ycoord = new QStandardItem(QString::number(package.Get("y", 0))); | ||
| 126 | binding_list_model->appendRow({button, xcoord, ycoord}); | ||
| 127 | |||
| 128 | const int dot = ui->bottom_screen->AddDot(package.Get("x", 0), package.Get("y", 0)); | ||
| 129 | button->setData(dot, DataRoleDot); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | void ConfigureTouchFromButton::ConnectEvents() { | ||
| 134 | connect(ui->mapping, qOverload<int>(&QComboBox::currentIndexChanged), this, [this](int index) { | ||
| 135 | SaveCurrentMapping(); | ||
| 136 | selected_index = index; | ||
| 137 | UpdateUiDisplay(); | ||
| 138 | }); | ||
| 139 | connect(ui->button_new, &QPushButton::clicked, this, &ConfigureTouchFromButton::NewMapping); | ||
| 140 | connect(ui->button_delete, &QPushButton::clicked, this, | ||
| 141 | &ConfigureTouchFromButton::DeleteMapping); | ||
| 142 | connect(ui->button_rename, &QPushButton::clicked, this, | ||
| 143 | &ConfigureTouchFromButton::RenameMapping); | ||
| 144 | connect(ui->button_delete_bind, &QPushButton::clicked, this, | ||
| 145 | &ConfigureTouchFromButton::DeleteBinding); | ||
| 146 | connect(ui->binding_list, &QTreeView::doubleClicked, this, | ||
| 147 | &ConfigureTouchFromButton::EditBinding); | ||
| 148 | connect(ui->binding_list->selectionModel(), &QItemSelectionModel::selectionChanged, this, | ||
| 149 | &ConfigureTouchFromButton::OnBindingSelection); | ||
| 150 | connect(binding_list_model, &QStandardItemModel::itemChanged, this, | ||
| 151 | &ConfigureTouchFromButton::OnBindingChanged); | ||
| 152 | connect(ui->binding_list->model(), &QStandardItemModel::rowsAboutToBeRemoved, this, | ||
| 153 | &ConfigureTouchFromButton::OnBindingDeleted); | ||
| 154 | connect(ui->bottom_screen, &TouchScreenPreview::DotAdded, this, | ||
| 155 | &ConfigureTouchFromButton::NewBinding); | ||
| 156 | connect(ui->bottom_screen, &TouchScreenPreview::DotSelected, this, | ||
| 157 | &ConfigureTouchFromButton::SetActiveBinding); | ||
| 158 | connect(ui->bottom_screen, &TouchScreenPreview::DotMoved, this, | ||
| 159 | &ConfigureTouchFromButton::SetCoordinates); | ||
| 160 | connect(ui->buttonBox, &QDialogButtonBox::accepted, this, | ||
| 161 | &ConfigureTouchFromButton::ApplyConfiguration); | ||
| 162 | |||
| 163 | connect(timeout_timer.get(), &QTimer::timeout, [this]() { SetPollingResult({}, true); }); | ||
| 164 | |||
| 165 | connect(poll_timer.get(), &QTimer::timeout, [this]() { | ||
| 166 | Common::ParamPackage params; | ||
| 167 | for (auto& poller : device_pollers) { | ||
| 168 | params = poller->GetNextInput(); | ||
| 169 | if (params.Has("engine")) { | ||
| 170 | SetPollingResult(params, false); | ||
| 171 | return; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | }); | ||
| 175 | } | ||
| 176 | |||
| 177 | void ConfigureTouchFromButton::SaveCurrentMapping() { | ||
| 178 | auto& map = touch_maps[selected_index]; | ||
| 179 | map.buttons.clear(); | ||
| 180 | for (int i = 0, rc = binding_list_model->rowCount(); i < rc; ++i) { | ||
| 181 | const auto bind_str = binding_list_model->index(i, 0) | ||
| 182 | .data(Qt::ItemDataRole::UserRole + 1) | ||
| 183 | .toString() | ||
| 184 | .toStdString(); | ||
| 185 | if (bind_str.empty()) { | ||
| 186 | continue; | ||
| 187 | } | ||
| 188 | Common::ParamPackage params{bind_str}; | ||
| 189 | if (!params.Has("engine")) { | ||
| 190 | continue; | ||
| 191 | } | ||
| 192 | params.Set("x", binding_list_model->index(i, 1).data().toInt()); | ||
| 193 | params.Set("y", binding_list_model->index(i, 2).data().toInt()); | ||
| 194 | map.buttons.emplace_back(params.Serialize()); | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | void ConfigureTouchFromButton::NewMapping() { | ||
| 199 | const QString name = | ||
| 200 | QInputDialog::getText(this, tr("New Profile"), tr("Enter the name for the new profile.")); | ||
| 201 | if (name.isEmpty()) { | ||
| 202 | return; | ||
| 203 | } | ||
| 204 | touch_maps.emplace_back(Settings::TouchFromButtonMap{name.toStdString(), {}}); | ||
| 205 | ui->mapping->addItem(name); | ||
| 206 | ui->mapping->setCurrentIndex(ui->mapping->count() - 1); | ||
| 207 | } | ||
| 208 | |||
| 209 | void ConfigureTouchFromButton::DeleteMapping() { | ||
| 210 | const auto answer = QMessageBox::question( | ||
| 211 | this, tr("Delete Profile"), tr("Delete profile %1?").arg(ui->mapping->currentText())); | ||
| 212 | if (answer != QMessageBox::Yes) { | ||
| 213 | return; | ||
| 214 | } | ||
| 215 | const bool blocked = ui->mapping->blockSignals(true); | ||
| 216 | ui->mapping->removeItem(selected_index); | ||
| 217 | ui->mapping->blockSignals(blocked); | ||
| 218 | touch_maps.erase(touch_maps.begin() + selected_index); | ||
| 219 | selected_index = ui->mapping->currentIndex(); | ||
| 220 | UpdateUiDisplay(); | ||
| 221 | } | ||
| 222 | |||
| 223 | void ConfigureTouchFromButton::RenameMapping() { | ||
| 224 | const QString new_name = QInputDialog::getText(this, tr("Rename Profile"), tr("New name:")); | ||
| 225 | if (new_name.isEmpty()) { | ||
| 226 | return; | ||
| 227 | } | ||
| 228 | ui->mapping->setItemText(selected_index, new_name); | ||
| 229 | touch_maps[selected_index].name = new_name.toStdString(); | ||
| 230 | } | ||
| 231 | |||
| 232 | void ConfigureTouchFromButton::GetButtonInput(const int row_index, const bool is_new) { | ||
| 233 | binding_list_model->item(row_index, 0)->setText(tr("[press key]")); | ||
| 234 | |||
| 235 | input_setter = [this, row_index, is_new](const Common::ParamPackage& params, | ||
| 236 | const bool cancel) { | ||
| 237 | auto* cell = binding_list_model->item(row_index, 0); | ||
| 238 | if (cancel) { | ||
| 239 | if (is_new) { | ||
| 240 | binding_list_model->removeRow(row_index); | ||
| 241 | } else { | ||
| 242 | cell->setText( | ||
| 243 | ButtonToText(Common::ParamPackage{cell->data().toString().toStdString()})); | ||
| 244 | } | ||
| 245 | } else { | ||
| 246 | cell->setText(ButtonToText(params)); | ||
| 247 | cell->setData(QString::fromStdString(params.Serialize())); | ||
| 248 | } | ||
| 249 | }; | ||
| 250 | |||
| 251 | device_pollers = input_subsystem->GetPollers(InputCommon::Polling::DeviceType::Button); | ||
| 252 | |||
| 253 | for (auto& poller : device_pollers) { | ||
| 254 | poller->Start(); | ||
| 255 | } | ||
| 256 | |||
| 257 | grabKeyboard(); | ||
| 258 | grabMouse(); | ||
| 259 | qApp->setOverrideCursor(QCursor(Qt::CursorShape::ArrowCursor)); | ||
| 260 | timeout_timer->start(5000); // Cancel after 5 seconds | ||
| 261 | poll_timer->start(200); // Check for new inputs every 200ms | ||
| 262 | } | ||
| 263 | |||
| 264 | void ConfigureTouchFromButton::NewBinding(const QPoint& pos) { | ||
| 265 | auto* button = new QStandardItem(); | ||
| 266 | button->setEditable(false); | ||
| 267 | auto* x_coord = new QStandardItem(QString::number(pos.x())); | ||
| 268 | auto* y_coord = new QStandardItem(QString::number(pos.y())); | ||
| 269 | |||
| 270 | const int dot_id = ui->bottom_screen->AddDot(pos.x(), pos.y()); | ||
| 271 | button->setData(dot_id, DataRoleDot); | ||
| 272 | |||
| 273 | binding_list_model->appendRow({button, x_coord, y_coord}); | ||
| 274 | ui->binding_list->setFocus(); | ||
| 275 | ui->binding_list->setCurrentIndex(button->index()); | ||
| 276 | |||
| 277 | GetButtonInput(binding_list_model->rowCount() - 1, true); | ||
| 278 | } | ||
| 279 | |||
| 280 | void ConfigureTouchFromButton::EditBinding(const QModelIndex& qi) { | ||
| 281 | if (qi.row() >= 0 && qi.column() == 0) { | ||
| 282 | GetButtonInput(qi.row(), false); | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | void ConfigureTouchFromButton::DeleteBinding() { | ||
| 287 | const int row_index = ui->binding_list->currentIndex().row(); | ||
| 288 | if (row_index < 0) { | ||
| 289 | return; | ||
| 290 | } | ||
| 291 | ui->bottom_screen->RemoveDot(binding_list_model->index(row_index, 0).data(DataRoleDot).toInt()); | ||
| 292 | binding_list_model->removeRow(row_index); | ||
| 293 | } | ||
| 294 | |||
| 295 | void ConfigureTouchFromButton::OnBindingSelection(const QItemSelection& selected, | ||
| 296 | const QItemSelection& deselected) { | ||
| 297 | ui->button_delete_bind->setEnabled(!selected.isEmpty()); | ||
| 298 | if (!selected.isEmpty()) { | ||
| 299 | const auto dot_data = selected.indexes().first().data(DataRoleDot); | ||
| 300 | if (dot_data.isValid()) { | ||
| 301 | ui->bottom_screen->HighlightDot(dot_data.toInt()); | ||
| 302 | } | ||
| 303 | } | ||
| 304 | if (!deselected.isEmpty()) { | ||
| 305 | const auto dot_data = deselected.indexes().first().data(DataRoleDot); | ||
| 306 | if (dot_data.isValid()) { | ||
| 307 | ui->bottom_screen->HighlightDot(dot_data.toInt(), false); | ||
| 308 | } | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | void ConfigureTouchFromButton::OnBindingChanged(QStandardItem* item) { | ||
| 313 | if (item->column() == 0) { | ||
| 314 | return; | ||
| 315 | } | ||
| 316 | |||
| 317 | const bool blocked = binding_list_model->blockSignals(true); | ||
| 318 | item->setText(QString::number( | ||
| 319 | std::clamp(item->text().toInt(), 0, | ||
| 320 | static_cast<int>((item->column() == 1 ? Layout::ScreenUndocked::Width | ||
| 321 | : Layout::ScreenUndocked::Height) - | ||
| 322 | 1)))); | ||
| 323 | binding_list_model->blockSignals(blocked); | ||
| 324 | |||
| 325 | const auto dot_data = binding_list_model->index(item->row(), 0).data(DataRoleDot); | ||
| 326 | if (dot_data.isValid()) { | ||
| 327 | ui->bottom_screen->MoveDot(dot_data.toInt(), | ||
| 328 | binding_list_model->item(item->row(), 1)->text().toInt(), | ||
| 329 | binding_list_model->item(item->row(), 2)->text().toInt()); | ||
| 330 | } | ||
| 331 | } | ||
| 332 | |||
| 333 | void ConfigureTouchFromButton::OnBindingDeleted(const QModelIndex& parent, int first, int last) { | ||
| 334 | for (int i = first; i <= last; ++i) { | ||
| 335 | const auto ix = binding_list_model->index(i, 0); | ||
| 336 | if (!ix.isValid()) { | ||
| 337 | return; | ||
| 338 | } | ||
| 339 | const auto dot_data = ix.data(DataRoleDot); | ||
| 340 | if (dot_data.isValid()) { | ||
| 341 | ui->bottom_screen->RemoveDot(dot_data.toInt()); | ||
| 342 | } | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | void ConfigureTouchFromButton::SetActiveBinding(const int dot_id) { | ||
| 347 | for (int i = 0; i < binding_list_model->rowCount(); ++i) { | ||
| 348 | if (binding_list_model->index(i, 0).data(DataRoleDot) == dot_id) { | ||
| 349 | ui->binding_list->setCurrentIndex(binding_list_model->index(i, 0)); | ||
| 350 | ui->binding_list->setFocus(); | ||
| 351 | return; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | void ConfigureTouchFromButton::SetCoordinates(const int dot_id, const QPoint& pos) { | ||
| 357 | for (int i = 0; i < binding_list_model->rowCount(); ++i) { | ||
| 358 | if (binding_list_model->item(i, 0)->data(DataRoleDot) == dot_id) { | ||
| 359 | binding_list_model->item(i, 1)->setText(QString::number(pos.x())); | ||
| 360 | binding_list_model->item(i, 2)->setText(QString::number(pos.y())); | ||
| 361 | return; | ||
| 362 | } | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | void ConfigureTouchFromButton::SetPollingResult(const Common::ParamPackage& params, | ||
| 367 | const bool cancel) { | ||
| 368 | releaseKeyboard(); | ||
| 369 | releaseMouse(); | ||
| 370 | qApp->restoreOverrideCursor(); | ||
| 371 | timeout_timer->stop(); | ||
| 372 | poll_timer->stop(); | ||
| 373 | for (auto& poller : device_pollers) { | ||
| 374 | poller->Stop(); | ||
| 375 | } | ||
| 376 | if (input_setter) { | ||
| 377 | (*input_setter)(params, cancel); | ||
| 378 | input_setter.reset(); | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 382 | void ConfigureTouchFromButton::keyPressEvent(QKeyEvent* event) { | ||
| 383 | if (!input_setter && event->key() == Qt::Key_Delete) { | ||
| 384 | DeleteBinding(); | ||
| 385 | return; | ||
| 386 | } | ||
| 387 | |||
| 388 | if (!input_setter) { | ||
| 389 | return QDialog::keyPressEvent(event); | ||
| 390 | } | ||
| 391 | |||
| 392 | if (event->key() != Qt::Key_Escape) { | ||
| 393 | SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, | ||
| 394 | false); | ||
| 395 | } else { | ||
| 396 | SetPollingResult({}, true); | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | void ConfigureTouchFromButton::ApplyConfiguration() { | ||
| 401 | SaveCurrentMapping(); | ||
| 402 | accept(); | ||
| 403 | } | ||
| 404 | |||
| 405 | int ConfigureTouchFromButton::GetSelectedIndex() const { | ||
| 406 | return selected_index; | ||
| 407 | } | ||
| 408 | |||
| 409 | std::vector<Settings::TouchFromButtonMap> ConfigureTouchFromButton::GetMaps() const { | ||
| 410 | return touch_maps; | ||
| 411 | } | ||
| 412 | |||
| 413 | TouchScreenPreview::TouchScreenPreview(QWidget* parent) : QFrame(parent) { | ||
| 414 | setBackgroundRole(QPalette::ColorRole::Base); | ||
| 415 | } | ||
| 416 | |||
| 417 | TouchScreenPreview::~TouchScreenPreview() = default; | ||
| 418 | |||
| 419 | void TouchScreenPreview::SetCoordLabel(QLabel* const label) { | ||
| 420 | coord_label = label; | ||
| 421 | } | ||
| 422 | |||
| 423 | int TouchScreenPreview::AddDot(const int device_x, const int device_y) { | ||
| 424 | QFont dot_font{QStringLiteral("monospace")}; | ||
| 425 | dot_font.setStyleHint(QFont::Monospace); | ||
| 426 | dot_font.setPointSize(20); | ||
| 427 | |||
| 428 | auto* dot = new QLabel(this); | ||
| 429 | dot->setAttribute(Qt::WA_TranslucentBackground); | ||
| 430 | dot->setFont(dot_font); | ||
| 431 | dot->setText(QChar(0xD7)); // U+00D7 Multiplication Sign | ||
| 432 | dot->setAlignment(Qt::AlignmentFlag::AlignCenter); | ||
| 433 | dot->setProperty(PropId, ++max_dot_id); | ||
| 434 | dot->setProperty(PropX, device_x); | ||
| 435 | dot->setProperty(PropY, device_y); | ||
| 436 | dot->setCursor(Qt::CursorShape::PointingHandCursor); | ||
| 437 | dot->setMouseTracking(true); | ||
| 438 | dot->installEventFilter(this); | ||
| 439 | dot->show(); | ||
| 440 | PositionDot(dot, device_x, device_y); | ||
| 441 | dots.emplace_back(max_dot_id, dot); | ||
| 442 | return max_dot_id; | ||
| 443 | } | ||
| 444 | |||
| 445 | void TouchScreenPreview::RemoveDot(const int id) { | ||
| 446 | const auto iter = std::find_if(dots.begin(), dots.end(), | ||
| 447 | [id](const auto& entry) { return entry.first == id; }); | ||
| 448 | if (iter == dots.cend()) { | ||
| 449 | return; | ||
| 450 | } | ||
| 451 | |||
| 452 | iter->second->deleteLater(); | ||
| 453 | dots.erase(iter); | ||
| 454 | } | ||
| 455 | |||
| 456 | void TouchScreenPreview::HighlightDot(const int id, const bool active) const { | ||
| 457 | for (const auto& dot : dots) { | ||
| 458 | if (dot.first == id) { | ||
| 459 | // use color property from the stylesheet, or fall back to the default palette | ||
| 460 | if (dot_highlight_color.isValid()) { | ||
| 461 | dot.second->setStyleSheet( | ||
| 462 | active ? QStringLiteral("color: %1").arg(dot_highlight_color.name()) | ||
| 463 | : QString{}); | ||
| 464 | } else { | ||
| 465 | dot.second->setForegroundRole(active ? QPalette::ColorRole::LinkVisited | ||
| 466 | : QPalette::ColorRole::NoRole); | ||
| 467 | } | ||
| 468 | if (active) { | ||
| 469 | dot.second->raise(); | ||
| 470 | } | ||
| 471 | return; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | } | ||
| 475 | |||
| 476 | void TouchScreenPreview::MoveDot(const int id, const int device_x, const int device_y) const { | ||
| 477 | const auto iter = std::find_if(dots.begin(), dots.end(), | ||
| 478 | [id](const auto& entry) { return entry.first == id; }); | ||
| 479 | if (iter == dots.cend()) { | ||
| 480 | return; | ||
| 481 | } | ||
| 482 | |||
| 483 | iter->second->setProperty(PropX, device_x); | ||
| 484 | iter->second->setProperty(PropY, device_y); | ||
| 485 | PositionDot(iter->second, device_x, device_y); | ||
| 486 | } | ||
| 487 | |||
| 488 | void TouchScreenPreview::resizeEvent(QResizeEvent* event) { | ||
| 489 | if (ignore_resize) { | ||
| 490 | return; | ||
| 491 | } | ||
| 492 | |||
| 493 | const int target_width = std::min(width(), height() * 4 / 3); | ||
| 494 | const int target_height = std::min(height(), width() * 3 / 4); | ||
| 495 | if (target_width == width() && target_height == height()) { | ||
| 496 | return; | ||
| 497 | } | ||
| 498 | ignore_resize = true; | ||
| 499 | setGeometry((parentWidget()->contentsRect().width() - target_width) / 2, y(), target_width, | ||
| 500 | target_height); | ||
| 501 | ignore_resize = false; | ||
| 502 | |||
| 503 | if (event->oldSize().width() != target_width || event->oldSize().height() != target_height) { | ||
| 504 | for (const auto& dot : dots) { | ||
| 505 | PositionDot(dot.second); | ||
| 506 | } | ||
| 507 | } | ||
| 508 | } | ||
| 509 | |||
| 510 | void TouchScreenPreview::mouseMoveEvent(QMouseEvent* event) { | ||
| 511 | if (!coord_label) { | ||
| 512 | return; | ||
| 513 | } | ||
| 514 | const auto pos = MapToDeviceCoords(event->x(), event->y()); | ||
| 515 | if (pos) { | ||
| 516 | coord_label->setText(QStringLiteral("X: %1, Y: %2").arg(pos->x()).arg(pos->y())); | ||
| 517 | } else { | ||
| 518 | coord_label->clear(); | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | void TouchScreenPreview::leaveEvent(QEvent* event) { | ||
| 523 | if (coord_label) { | ||
| 524 | coord_label->clear(); | ||
| 525 | } | ||
| 526 | } | ||
| 527 | |||
| 528 | void TouchScreenPreview::mousePressEvent(QMouseEvent* event) { | ||
| 529 | if (event->button() != Qt::MouseButton::LeftButton) { | ||
| 530 | return; | ||
| 531 | } | ||
| 532 | const auto pos = MapToDeviceCoords(event->x(), event->y()); | ||
| 533 | if (pos) { | ||
| 534 | emit DotAdded(*pos); | ||
| 535 | } | ||
| 536 | } | ||
| 537 | |||
| 538 | bool TouchScreenPreview::eventFilter(QObject* obj, QEvent* event) { | ||
| 539 | switch (event->type()) { | ||
| 540 | case QEvent::Type::MouseButtonPress: { | ||
| 541 | const auto mouse_event = static_cast<QMouseEvent*>(event); | ||
| 542 | if (mouse_event->button() != Qt::MouseButton::LeftButton) { | ||
| 543 | break; | ||
| 544 | } | ||
| 545 | emit DotSelected(obj->property(PropId).toInt()); | ||
| 546 | |||
| 547 | drag_state.dot = qobject_cast<QLabel*>(obj); | ||
| 548 | drag_state.start_pos = mouse_event->globalPos(); | ||
| 549 | return true; | ||
| 550 | } | ||
| 551 | case QEvent::Type::MouseMove: { | ||
| 552 | if (!drag_state.dot) { | ||
| 553 | break; | ||
| 554 | } | ||
| 555 | const auto mouse_event = static_cast<QMouseEvent*>(event); | ||
| 556 | if (!drag_state.active) { | ||
| 557 | drag_state.active = | ||
| 558 | (mouse_event->globalPos() - drag_state.start_pos).manhattanLength() >= | ||
| 559 | QApplication::startDragDistance(); | ||
| 560 | if (!drag_state.active) { | ||
| 561 | break; | ||
| 562 | } | ||
| 563 | } | ||
| 564 | auto current_pos = mapFromGlobal(mouse_event->globalPos()); | ||
| 565 | current_pos.setX(std::clamp(current_pos.x(), contentsMargins().left(), | ||
| 566 | contentsMargins().left() + contentsRect().width() - 1)); | ||
| 567 | current_pos.setY(std::clamp(current_pos.y(), contentsMargins().top(), | ||
| 568 | contentsMargins().top() + contentsRect().height() - 1)); | ||
| 569 | const auto device_coord = MapToDeviceCoords(current_pos.x(), current_pos.y()); | ||
| 570 | if (device_coord) { | ||
| 571 | drag_state.dot->setProperty(PropX, device_coord->x()); | ||
| 572 | drag_state.dot->setProperty(PropY, device_coord->y()); | ||
| 573 | PositionDot(drag_state.dot, device_coord->x(), device_coord->y()); | ||
| 574 | emit DotMoved(drag_state.dot->property(PropId).toInt(), *device_coord); | ||
| 575 | if (coord_label) { | ||
| 576 | coord_label->setText( | ||
| 577 | QStringLiteral("X: %1, Y: %2").arg(device_coord->x()).arg(device_coord->y())); | ||
| 578 | } | ||
| 579 | } | ||
| 580 | return true; | ||
| 581 | } | ||
| 582 | case QEvent::Type::MouseButtonRelease: { | ||
| 583 | drag_state.dot.clear(); | ||
| 584 | drag_state.active = false; | ||
| 585 | return true; | ||
| 586 | } | ||
| 587 | default: | ||
| 588 | break; | ||
| 589 | } | ||
| 590 | return obj->eventFilter(obj, event); | ||
| 591 | } | ||
| 592 | |||
| 593 | std::optional<QPoint> TouchScreenPreview::MapToDeviceCoords(const int screen_x, | ||
| 594 | const int screen_y) const { | ||
| 595 | const float t_x = 0.5f + static_cast<float>(screen_x - contentsMargins().left()) * | ||
| 596 | (Layout::ScreenUndocked::Width - 1) / (contentsRect().width() - 1); | ||
| 597 | const float t_y = 0.5f + static_cast<float>(screen_y - contentsMargins().top()) * | ||
| 598 | (Layout::ScreenUndocked::Height - 1) / | ||
| 599 | (contentsRect().height() - 1); | ||
| 600 | if (t_x >= 0.5f && t_x < Layout::ScreenUndocked::Width && t_y >= 0.5f && | ||
| 601 | t_y < Layout::ScreenUndocked::Height) { | ||
| 602 | |||
| 603 | return QPoint{static_cast<int>(t_x), static_cast<int>(t_y)}; | ||
| 604 | } | ||
| 605 | return std::nullopt; | ||
| 606 | } | ||
| 607 | |||
| 608 | void TouchScreenPreview::PositionDot(QLabel* const dot, const int device_x, | ||
| 609 | const int device_y) const { | ||
| 610 | const float device_coord_x = | ||
| 611 | static_cast<float>(device_x >= 0 ? device_x : dot->property(PropX).toInt()); | ||
| 612 | int x_coord = static_cast<int>( | ||
| 613 | device_coord_x * (contentsRect().width() - 1) / (Layout::ScreenUndocked::Width - 1) + | ||
| 614 | contentsMargins().left() - static_cast<float>(dot->width()) / 2 + 0.5f); | ||
| 615 | |||
| 616 | const float device_coord_y = | ||
| 617 | static_cast<float>(device_y >= 0 ? device_y : dot->property(PropY).toInt()); | ||
| 618 | const int y_coord = static_cast<int>( | ||
| 619 | device_coord_y * (contentsRect().height() - 1) / (Layout::ScreenUndocked::Height - 1) + | ||
| 620 | contentsMargins().top() - static_cast<float>(dot->height()) / 2 + 0.5f); | ||
| 621 | |||
| 622 | dot->move(x_coord, y_coord); | ||
| 623 | } | ||
diff --git a/src/yuzu/configuration/configure_touch_from_button.h b/src/yuzu/configuration/configure_touch_from_button.h new file mode 100644 index 000000000..d9513e3bc --- /dev/null +++ b/src/yuzu/configuration/configure_touch_from_button.h | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | // Copyright 2020 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 <functional> | ||
| 8 | #include <memory> | ||
| 9 | #include <optional> | ||
| 10 | #include <vector> | ||
| 11 | #include <QDialog> | ||
| 12 | |||
| 13 | class QItemSelection; | ||
| 14 | class QModelIndex; | ||
| 15 | class QStandardItemModel; | ||
| 16 | class QStandardItem; | ||
| 17 | class QTimer; | ||
| 18 | |||
| 19 | namespace Common { | ||
| 20 | class ParamPackage; | ||
| 21 | } | ||
| 22 | |||
| 23 | namespace InputCommon { | ||
| 24 | class InputSubsystem; | ||
| 25 | } | ||
| 26 | |||
| 27 | namespace InputCommon::Polling { | ||
| 28 | class DevicePoller; | ||
| 29 | } | ||
| 30 | |||
| 31 | namespace Settings { | ||
| 32 | struct TouchFromButtonMap; | ||
| 33 | } | ||
| 34 | |||
| 35 | namespace Ui { | ||
| 36 | class ConfigureTouchFromButton; | ||
| 37 | } | ||
| 38 | |||
| 39 | class ConfigureTouchFromButton : public QDialog { | ||
| 40 | Q_OBJECT | ||
| 41 | |||
| 42 | public: | ||
| 43 | explicit ConfigureTouchFromButton(QWidget* parent, | ||
| 44 | const std::vector<Settings::TouchFromButtonMap>& touch_maps, | ||
| 45 | InputCommon::InputSubsystem* input_subsystem_, | ||
| 46 | int default_index = 0); | ||
| 47 | ~ConfigureTouchFromButton() override; | ||
| 48 | |||
| 49 | int GetSelectedIndex() const; | ||
| 50 | std::vector<Settings::TouchFromButtonMap> GetMaps() const; | ||
| 51 | |||
| 52 | public slots: | ||
| 53 | void ApplyConfiguration(); | ||
| 54 | void NewBinding(const QPoint& pos); | ||
| 55 | void SetActiveBinding(int dot_id); | ||
| 56 | void SetCoordinates(int dot_id, const QPoint& pos); | ||
| 57 | |||
| 58 | protected: | ||
| 59 | void showEvent(QShowEvent* ev) override; | ||
| 60 | void keyPressEvent(QKeyEvent* event) override; | ||
| 61 | |||
| 62 | private slots: | ||
| 63 | void NewMapping(); | ||
| 64 | void DeleteMapping(); | ||
| 65 | void RenameMapping(); | ||
| 66 | void EditBinding(const QModelIndex& qi); | ||
| 67 | void DeleteBinding(); | ||
| 68 | void OnBindingSelection(const QItemSelection& selected, const QItemSelection& deselected); | ||
| 69 | void OnBindingChanged(QStandardItem* item); | ||
| 70 | void OnBindingDeleted(const QModelIndex& parent, int first, int last); | ||
| 71 | |||
| 72 | private: | ||
| 73 | void SetConfiguration(); | ||
| 74 | void UpdateUiDisplay(); | ||
| 75 | void ConnectEvents(); | ||
| 76 | void GetButtonInput(int row_index, bool is_new); | ||
| 77 | void SetPollingResult(const Common::ParamPackage& params, bool cancel); | ||
| 78 | void SaveCurrentMapping(); | ||
| 79 | |||
| 80 | std::unique_ptr<Ui::ConfigureTouchFromButton> ui; | ||
| 81 | std::vector<Settings::TouchFromButtonMap> touch_maps; | ||
| 82 | QStandardItemModel* binding_list_model; | ||
| 83 | InputCommon::InputSubsystem* input_subsystem; | ||
| 84 | int selected_index; | ||
| 85 | |||
| 86 | std::unique_ptr<QTimer> timeout_timer; | ||
| 87 | std::unique_ptr<QTimer> poll_timer; | ||
| 88 | std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers; | ||
| 89 | std::optional<std::function<void(const Common::ParamPackage&, bool)>> input_setter; | ||
| 90 | |||
| 91 | static constexpr int DataRoleDot = Qt::ItemDataRole::UserRole + 2; | ||
| 92 | }; | ||
diff --git a/src/yuzu/configuration/configure_touch_from_button.ui b/src/yuzu/configuration/configure_touch_from_button.ui new file mode 100644 index 000000000..f581e27e0 --- /dev/null +++ b/src/yuzu/configuration/configure_touch_from_button.ui | |||
| @@ -0,0 +1,231 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureTouchFromButton</class> | ||
| 4 | <widget class="QDialog" name="ConfigureTouchFromButton"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>500</width> | ||
| 10 | <height>500</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Configure Touchscreen Mappings</string> | ||
| 15 | </property> | ||
| 16 | <layout class="QVBoxLayout"> | ||
| 17 | <item> | ||
| 18 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 19 | <item> | ||
| 20 | <widget class="QLabel" name="label"> | ||
| 21 | <property name="text"> | ||
| 22 | <string>Mapping:</string> | ||
| 23 | </property> | ||
| 24 | <property name="textFormat"> | ||
| 25 | <enum>Qt::PlainText</enum> | ||
| 26 | </property> | ||
| 27 | </widget> | ||
| 28 | </item> | ||
| 29 | <item> | ||
| 30 | <widget class="QComboBox" name="mapping"> | ||
| 31 | <property name="sizePolicy"> | ||
| 32 | <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> | ||
| 33 | <horstretch>0</horstretch> | ||
| 34 | <verstretch>0</verstretch> | ||
| 35 | </sizepolicy> | ||
| 36 | </property> | ||
| 37 | </widget> | ||
| 38 | </item> | ||
| 39 | <item> | ||
| 40 | <widget class="QPushButton" name="button_new"> | ||
| 41 | <property name="sizePolicy"> | ||
| 42 | <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||
| 43 | <horstretch>0</horstretch> | ||
| 44 | <verstretch>0</verstretch> | ||
| 45 | </sizepolicy> | ||
| 46 | </property> | ||
| 47 | <property name="text"> | ||
| 48 | <string>New</string> | ||
| 49 | </property> | ||
| 50 | </widget> | ||
| 51 | </item> | ||
| 52 | <item> | ||
| 53 | <widget class="QPushButton" name="button_delete"> | ||
| 54 | <property name="sizePolicy"> | ||
| 55 | <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||
| 56 | <horstretch>0</horstretch> | ||
| 57 | <verstretch>0</verstretch> | ||
| 58 | </sizepolicy> | ||
| 59 | </property> | ||
| 60 | <property name="text"> | ||
| 61 | <string>Delete</string> | ||
| 62 | </property> | ||
| 63 | </widget> | ||
| 64 | </item> | ||
| 65 | <item> | ||
| 66 | <widget class="QPushButton" name="button_rename"> | ||
| 67 | <property name="sizePolicy"> | ||
| 68 | <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||
| 69 | <horstretch>0</horstretch> | ||
| 70 | <verstretch>0</verstretch> | ||
| 71 | </sizepolicy> | ||
| 72 | </property> | ||
| 73 | <property name="text"> | ||
| 74 | <string>Rename</string> | ||
| 75 | </property> | ||
| 76 | </widget> | ||
| 77 | </item> | ||
| 78 | </layout> | ||
| 79 | </item> | ||
| 80 | <item> | ||
| 81 | <widget class="Line" name="line"> | ||
| 82 | <property name="orientation"> | ||
| 83 | <enum>Qt::Horizontal</enum> | ||
| 84 | </property> | ||
| 85 | </widget> | ||
| 86 | </item> | ||
| 87 | <item> | ||
| 88 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 89 | <item> | ||
| 90 | <widget class="QLabel" name="label_2"> | ||
| 91 | <property name="text"> | ||
| 92 | <string>Click the bottom area to add a point, then press a button to bind. | ||
| 93 | Drag points to change position, or double-click table cells to edit values.</string> | ||
| 94 | </property> | ||
| 95 | <property name="textFormat"> | ||
| 96 | <enum>Qt::PlainText</enum> | ||
| 97 | </property> | ||
| 98 | </widget> | ||
| 99 | </item> | ||
| 100 | <item> | ||
| 101 | <spacer name="horizontalSpacer"> | ||
| 102 | <property name="orientation"> | ||
| 103 | <enum>Qt::Horizontal</enum> | ||
| 104 | </property> | ||
| 105 | <property name="sizeHint" stdset="0"> | ||
| 106 | <size> | ||
| 107 | <width>40</width> | ||
| 108 | <height>20</height> | ||
| 109 | </size> | ||
| 110 | </property> | ||
| 111 | </spacer> | ||
| 112 | </item> | ||
| 113 | <item> | ||
| 114 | <widget class="QPushButton" name="button_delete_bind"> | ||
| 115 | <property name="text"> | ||
| 116 | <string>Delete Point</string> | ||
| 117 | </property> | ||
| 118 | </widget> | ||
| 119 | </item> | ||
| 120 | </layout> | ||
| 121 | </item> | ||
| 122 | <item> | ||
| 123 | <widget class="QTreeView" name="binding_list"> | ||
| 124 | <property name="sizePolicy"> | ||
| 125 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 126 | <horstretch>0</horstretch> | ||
| 127 | <verstretch>0</verstretch> | ||
| 128 | </sizepolicy> | ||
| 129 | </property> | ||
| 130 | <property name="rootIsDecorated"> | ||
| 131 | <bool>false</bool> | ||
| 132 | </property> | ||
| 133 | <property name="uniformRowHeights"> | ||
| 134 | <bool>true</bool> | ||
| 135 | </property> | ||
| 136 | <property name="itemsExpandable"> | ||
| 137 | <bool>false</bool> | ||
| 138 | </property> | ||
| 139 | </widget> | ||
| 140 | </item> | ||
| 141 | <item> | ||
| 142 | <widget class="TouchScreenPreview" name="bottom_screen"> | ||
| 143 | <property name="sizePolicy"> | ||
| 144 | <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||
| 145 | <horstretch>0</horstretch> | ||
| 146 | <verstretch>0</verstretch> | ||
| 147 | </sizepolicy> | ||
| 148 | </property> | ||
| 149 | <property name="minimumSize"> | ||
| 150 | <size> | ||
| 151 | <width>160</width> | ||
| 152 | <height>120</height> | ||
| 153 | </size> | ||
| 154 | </property> | ||
| 155 | <property name="baseSize"> | ||
| 156 | <size> | ||
| 157 | <width>320</width> | ||
| 158 | <height>240</height> | ||
| 159 | </size> | ||
| 160 | </property> | ||
| 161 | <property name="cursor"> | ||
| 162 | <cursorShape>CrossCursor</cursorShape> | ||
| 163 | </property> | ||
| 164 | <property name="mouseTracking"> | ||
| 165 | <bool>true</bool> | ||
| 166 | </property> | ||
| 167 | <property name="autoFillBackground"> | ||
| 168 | <bool>true</bool> | ||
| 169 | </property> | ||
| 170 | <property name="frameShape"> | ||
| 171 | <enum>QFrame::StyledPanel</enum> | ||
| 172 | </property> | ||
| 173 | <property name="frameShadow"> | ||
| 174 | <enum>QFrame::Sunken</enum> | ||
| 175 | </property> | ||
| 176 | </widget> | ||
| 177 | </item> | ||
| 178 | <item> | ||
| 179 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | ||
| 180 | <item> | ||
| 181 | <widget class="QLabel" name="coord_label"> | ||
| 182 | <property name="sizePolicy"> | ||
| 183 | <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> | ||
| 184 | <horstretch>0</horstretch> | ||
| 185 | <verstretch>0</verstretch> | ||
| 186 | </sizepolicy> | ||
| 187 | </property> | ||
| 188 | <property name="textFormat"> | ||
| 189 | <enum>Qt::PlainText</enum> | ||
| 190 | </property> | ||
| 191 | </widget> | ||
| 192 | </item> | ||
| 193 | <item> | ||
| 194 | <widget class="QDialogButtonBox" name="buttonBox"> | ||
| 195 | <property name="standardButtons"> | ||
| 196 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 197 | </property> | ||
| 198 | </widget> | ||
| 199 | </item> | ||
| 200 | </layout> | ||
| 201 | </item> | ||
| 202 | </layout> | ||
| 203 | </widget> | ||
| 204 | <customwidgets> | ||
| 205 | <customwidget> | ||
| 206 | <class>TouchScreenPreview</class> | ||
| 207 | <extends>QFrame</extends> | ||
| 208 | <header>yuzu/configuration/configure_touch_widget.h</header> | ||
| 209 | <container>1</container> | ||
| 210 | </customwidget> | ||
| 211 | </customwidgets> | ||
| 212 | <resources/> | ||
| 213 | <connections> | ||
| 214 | <connection> | ||
| 215 | <sender>buttonBox</sender> | ||
| 216 | <signal>rejected()</signal> | ||
| 217 | <receiver>ConfigureTouchFromButton</receiver> | ||
| 218 | <slot>reject()</slot> | ||
| 219 | <hints> | ||
| 220 | <hint type="sourcelabel"> | ||
| 221 | <x>249</x> | ||
| 222 | <y>428</y> | ||
| 223 | </hint> | ||
| 224 | <hint type="destinationlabel"> | ||
| 225 | <x>249</x> | ||
| 226 | <y>224</y> | ||
| 227 | </hint> | ||
| 228 | </hints> | ||
| 229 | </connection> | ||
| 230 | </connections> | ||
| 231 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_touch_widget.h b/src/yuzu/configuration/configure_touch_widget.h new file mode 100644 index 000000000..347b46583 --- /dev/null +++ b/src/yuzu/configuration/configure_touch_widget.h | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | // Copyright 2020 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 <optional> | ||
| 8 | #include <utility> | ||
| 9 | #include <vector> | ||
| 10 | #include <QFrame> | ||
| 11 | #include <QPointer> | ||
| 12 | |||
| 13 | class QLabel; | ||
| 14 | |||
| 15 | // Widget for representing touchscreen coordinates | ||
| 16 | class TouchScreenPreview : public QFrame { | ||
| 17 | Q_OBJECT | ||
| 18 | Q_PROPERTY(QColor dotHighlightColor MEMBER dot_highlight_color) | ||
| 19 | |||
| 20 | public: | ||
| 21 | explicit TouchScreenPreview(QWidget* parent); | ||
| 22 | ~TouchScreenPreview() override; | ||
| 23 | |||
| 24 | void SetCoordLabel(QLabel*); | ||
| 25 | int AddDot(int device_x, int device_y); | ||
| 26 | void RemoveDot(int id); | ||
| 27 | void HighlightDot(int id, bool active = true) const; | ||
| 28 | void MoveDot(int id, int device_x, int device_y) const; | ||
| 29 | |||
| 30 | signals: | ||
| 31 | void DotAdded(const QPoint& pos); | ||
| 32 | void DotSelected(int dot_id); | ||
| 33 | void DotMoved(int dot_id, const QPoint& pos); | ||
| 34 | |||
| 35 | protected: | ||
| 36 | void resizeEvent(QResizeEvent*) override; | ||
| 37 | void mouseMoveEvent(QMouseEvent*) override; | ||
| 38 | void leaveEvent(QEvent*) override; | ||
| 39 | void mousePressEvent(QMouseEvent*) override; | ||
| 40 | bool eventFilter(QObject*, QEvent*) override; | ||
| 41 | |||
| 42 | private: | ||
| 43 | std::optional<QPoint> MapToDeviceCoords(int screen_x, int screen_y) const; | ||
| 44 | void PositionDot(QLabel* dot, int device_x = -1, int device_y = -1) const; | ||
| 45 | |||
| 46 | bool ignore_resize = false; | ||
| 47 | QPointer<QLabel> coord_label; | ||
| 48 | |||
| 49 | std::vector<std::pair<int, QLabel*>> dots; | ||
| 50 | int max_dot_id = 0; | ||
| 51 | QColor dot_highlight_color; | ||
| 52 | static constexpr char PropId[] = "dot_id"; | ||
| 53 | static constexpr char PropX[] = "device_x"; | ||
| 54 | static constexpr char PropY[] = "device_y"; | ||
| 55 | |||
| 56 | struct DragState { | ||
| 57 | bool active = false; | ||
| 58 | QPointer<QLabel> dot; | ||
| 59 | QPoint start_pos; | ||
| 60 | }; | ||
| 61 | DragState drag_state; | ||
| 62 | }; | ||
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index cd7e78eb4..a1b61d119 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -94,6 +94,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 94 | #include "core/perf_stats.h" | 94 | #include "core/perf_stats.h" |
| 95 | #include "core/settings.h" | 95 | #include "core/settings.h" |
| 96 | #include "core/telemetry_session.h" | 96 | #include "core/telemetry_session.h" |
| 97 | #include "input_common/main.h" | ||
| 97 | #include "video_core/gpu.h" | 98 | #include "video_core/gpu.h" |
| 98 | #include "video_core/shader_notify.h" | 99 | #include "video_core/shader_notify.h" |
| 99 | #include "yuzu/about_dialog.h" | 100 | #include "yuzu/about_dialog.h" |
| @@ -186,9 +187,9 @@ static void InitializeLogging() { | |||
| 186 | } | 187 | } |
| 187 | 188 | ||
| 188 | GMainWindow::GMainWindow() | 189 | GMainWindow::GMainWindow() |
| 189 | : config(new Config()), emu_thread(nullptr), | 190 | : input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, |
| 190 | vfs(std::make_shared<FileSys::RealVfsFilesystem>()), | 191 | config{std::make_unique<Config>()}, vfs{std::make_shared<FileSys::RealVfsFilesystem>()}, |
| 191 | provider(std::make_unique<FileSys::ManualContentProvider>()) { | 192 | provider{std::make_unique<FileSys::ManualContentProvider>()} { |
| 192 | InitializeLogging(); | 193 | InitializeLogging(); |
| 193 | 194 | ||
| 194 | LoadTranslation(); | 195 | LoadTranslation(); |
| @@ -473,7 +474,7 @@ void GMainWindow::InitializeWidgets() { | |||
| 473 | #ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING | 474 | #ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING |
| 474 | ui.action_Report_Compatibility->setVisible(true); | 475 | ui.action_Report_Compatibility->setVisible(true); |
| 475 | #endif | 476 | #endif |
| 476 | render_window = new GRenderWindow(this, emu_thread.get()); | 477 | render_window = new GRenderWindow(this, emu_thread.get(), input_subsystem); |
| 477 | render_window->hide(); | 478 | render_window->hide(); |
| 478 | 479 | ||
| 479 | game_list = new GameList(vfs, provider.get(), this); | 480 | game_list = new GameList(vfs, provider.get(), this); |
| @@ -2213,7 +2214,7 @@ void GMainWindow::OnConfigure() { | |||
| 2213 | const auto old_theme = UISettings::values.theme; | 2214 | const auto old_theme = UISettings::values.theme; |
| 2214 | const bool old_discord_presence = UISettings::values.enable_discord_presence; | 2215 | const bool old_discord_presence = UISettings::values.enable_discord_presence; |
| 2215 | 2216 | ||
| 2216 | ConfigureDialog configure_dialog(this, hotkey_registry); | 2217 | ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get()); |
| 2217 | connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, | 2218 | connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, |
| 2218 | &GMainWindow::OnLanguageChanged); | 2219 | &GMainWindow::OnLanguageChanged); |
| 2219 | 2220 | ||
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 01f9131e5..0ce66a1ca 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -40,12 +40,20 @@ namespace Core::Frontend { | |||
| 40 | struct SoftwareKeyboardParameters; | 40 | struct SoftwareKeyboardParameters; |
| 41 | } // namespace Core::Frontend | 41 | } // namespace Core::Frontend |
| 42 | 42 | ||
| 43 | namespace DiscordRPC { | ||
| 44 | class DiscordInterface; | ||
| 45 | } | ||
| 46 | |||
| 43 | namespace FileSys { | 47 | namespace FileSys { |
| 44 | class ContentProvider; | 48 | class ContentProvider; |
| 45 | class ManualContentProvider; | 49 | class ManualContentProvider; |
| 46 | class VfsFilesystem; | 50 | class VfsFilesystem; |
| 47 | } // namespace FileSys | 51 | } // namespace FileSys |
| 48 | 52 | ||
| 53 | namespace InputCommon { | ||
| 54 | class InputSubsystem; | ||
| 55 | } | ||
| 56 | |||
| 49 | enum class EmulatedDirectoryTarget { | 57 | enum class EmulatedDirectoryTarget { |
| 50 | NAND, | 58 | NAND, |
| 51 | SDMC, | 59 | SDMC, |
| @@ -62,10 +70,6 @@ enum class ReinitializeKeyBehavior { | |||
| 62 | Warning, | 70 | Warning, |
| 63 | }; | 71 | }; |
| 64 | 72 | ||
| 65 | namespace DiscordRPC { | ||
| 66 | class DiscordInterface; | ||
| 67 | } | ||
| 68 | |||
| 69 | class GMainWindow : public QMainWindow { | 73 | class GMainWindow : public QMainWindow { |
| 70 | Q_OBJECT | 74 | Q_OBJECT |
| 71 | 75 | ||
| @@ -86,8 +90,6 @@ public: | |||
| 86 | GMainWindow(); | 90 | GMainWindow(); |
| 87 | ~GMainWindow() override; | 91 | ~GMainWindow() override; |
| 88 | 92 | ||
| 89 | std::unique_ptr<DiscordRPC::DiscordInterface> discord_rpc; | ||
| 90 | |||
| 91 | bool DropAction(QDropEvent* event); | 93 | bool DropAction(QDropEvent* event); |
| 92 | void AcceptDropEvent(QDropEvent* event); | 94 | void AcceptDropEvent(QDropEvent* event); |
| 93 | 95 | ||
| @@ -255,6 +257,9 @@ private: | |||
| 255 | 257 | ||
| 256 | Ui::MainWindow ui; | 258 | Ui::MainWindow ui; |
| 257 | 259 | ||
| 260 | std::unique_ptr<DiscordRPC::DiscordInterface> discord_rpc; | ||
| 261 | std::shared_ptr<InputCommon::InputSubsystem> input_subsystem; | ||
| 262 | |||
| 258 | GRenderWindow* render_window; | 263 | GRenderWindow* render_window; |
| 259 | GameList* game_list; | 264 | GameList* game_list; |
| 260 | LoadingScreen* loading_screen; | 265 | LoadingScreen* loading_screen; |
diff --git a/src/yuzu/uisettings.cpp b/src/yuzu/uisettings.cpp index a51175f36..37499fc85 100644 --- a/src/yuzu/uisettings.cpp +++ b/src/yuzu/uisettings.cpp | |||
| @@ -16,4 +16,5 @@ const Themes themes{{ | |||
| 16 | }}; | 16 | }}; |
| 17 | 17 | ||
| 18 | Values values = {}; | 18 | Values values = {}; |
| 19 | |||
| 19 | } // namespace UISettings | 20 | } // namespace UISettings |
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 2d2e82f15..ce3945485 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h | |||
| @@ -87,9 +87,6 @@ struct Values { | |||
| 87 | // logging | 87 | // logging |
| 88 | bool show_console; | 88 | bool show_console; |
| 89 | 89 | ||
| 90 | // Controllers | ||
| 91 | int profile_index; | ||
| 92 | |||
| 93 | // Game List | 90 | // Game List |
| 94 | bool show_add_ons; | 91 | bool show_add_ons; |
| 95 | uint32_t icon_size; | 92 | uint32_t icon_size; |
| @@ -100,6 +97,7 @@ struct Values { | |||
| 100 | }; | 97 | }; |
| 101 | 98 | ||
| 102 | extern Values values; | 99 | extern Values values; |
| 100 | |||
| 103 | } // namespace UISettings | 101 | } // namespace UISettings |
| 104 | 102 | ||
| 105 | Q_DECLARE_METATYPE(UISettings::GameDir*); | 103 | Q_DECLARE_METATYPE(UISettings::GameDir*); |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 8a63fd191..e9f1c6500 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -288,6 +288,8 @@ void Config::ReadValues() { | |||
| 288 | Settings::values.debug_pad_analogs[i] = default_param; | 288 | Settings::values.debug_pad_analogs[i] = default_param; |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | Settings::values.vibration_enabled = | ||
| 292 | sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true); | ||
| 291 | Settings::values.touchscreen.enabled = | 293 | Settings::values.touchscreen.enabled = |
| 292 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); | 294 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); |
| 293 | Settings::values.touchscreen.device = | 295 | Settings::values.touchscreen.device = |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index e5e684206..a804d5185 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -13,23 +13,25 @@ | |||
| 13 | #include "input_common/sdl/sdl.h" | 13 | #include "input_common/sdl/sdl.h" |
| 14 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 14 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| 15 | 15 | ||
| 16 | EmuWindow_SDL2::EmuWindow_SDL2(Core::System& system, bool fullscreen) : system{system} { | 16 | EmuWindow_SDL2::EmuWindow_SDL2(Core::System& system, bool fullscreen, |
| 17 | InputCommon::InputSubsystem* input_subsystem_) | ||
| 18 | : system{system}, input_subsystem{input_subsystem_} { | ||
| 17 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { | 19 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { |
| 18 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); | 20 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); |
| 19 | exit(1); | 21 | exit(1); |
| 20 | } | 22 | } |
| 21 | InputCommon::Init(); | 23 | input_subsystem->Initialize(); |
| 22 | SDL_SetMainReady(); | 24 | SDL_SetMainReady(); |
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | EmuWindow_SDL2::~EmuWindow_SDL2() { | 27 | EmuWindow_SDL2::~EmuWindow_SDL2() { |
| 26 | InputCommon::Shutdown(); | 28 | input_subsystem->Shutdown(); |
| 27 | SDL_Quit(); | 29 | SDL_Quit(); |
| 28 | } | 30 | } |
| 29 | 31 | ||
| 30 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { | 32 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { |
| 31 | TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); | 33 | TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); |
| 32 | InputCommon::GetMotionEmu()->Tilt(x, y); | 34 | input_subsystem->GetMotionEmu()->Tilt(x, y); |
| 33 | } | 35 | } |
| 34 | 36 | ||
| 35 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { | 37 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { |
| @@ -41,9 +43,9 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { | |||
| 41 | } | 43 | } |
| 42 | } else if (button == SDL_BUTTON_RIGHT) { | 44 | } else if (button == SDL_BUTTON_RIGHT) { |
| 43 | if (state == SDL_PRESSED) { | 45 | if (state == SDL_PRESSED) { |
| 44 | InputCommon::GetMotionEmu()->BeginTilt(x, y); | 46 | input_subsystem->GetMotionEmu()->BeginTilt(x, y); |
| 45 | } else { | 47 | } else { |
| 46 | InputCommon::GetMotionEmu()->EndTilt(); | 48 | input_subsystem->GetMotionEmu()->EndTilt(); |
| 47 | } | 49 | } |
| 48 | } | 50 | } |
| 49 | } | 51 | } |
| @@ -79,9 +81,9 @@ void EmuWindow_SDL2::OnFingerUp() { | |||
| 79 | 81 | ||
| 80 | void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { | 82 | void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { |
| 81 | if (state == SDL_PRESSED) { | 83 | if (state == SDL_PRESSED) { |
| 82 | InputCommon::GetKeyboard()->PressKey(key); | 84 | input_subsystem->GetKeyboard()->PressKey(key); |
| 83 | } else if (state == SDL_RELEASED) { | 85 | } else if (state == SDL_RELEASED) { |
| 84 | InputCommon::GetKeyboard()->ReleaseKey(key); | 86 | input_subsystem->GetKeyboard()->ReleaseKey(key); |
| 85 | } | 87 | } |
| 86 | } | 88 | } |
| 87 | 89 | ||
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h index fffac4252..82750ffec 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h | |||
| @@ -14,9 +14,14 @@ namespace Core { | |||
| 14 | class System; | 14 | class System; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace InputCommon { | ||
| 18 | class InputSubsystem; | ||
| 19 | } | ||
| 20 | |||
| 17 | class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { | 21 | class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { |
| 18 | public: | 22 | public: |
| 19 | explicit EmuWindow_SDL2(Core::System& system, bool fullscreen); | 23 | explicit EmuWindow_SDL2(Core::System& system, bool fullscreen, |
| 24 | InputCommon::InputSubsystem* input_subsystem); | ||
| 20 | ~EmuWindow_SDL2(); | 25 | ~EmuWindow_SDL2(); |
| 21 | 26 | ||
| 22 | /// Polls window events | 27 | /// Polls window events |
| @@ -76,4 +81,7 @@ protected: | |||
| 76 | 81 | ||
| 77 | /// Keeps track of how often to update the title bar during gameplay | 82 | /// Keeps track of how often to update the title bar during gameplay |
| 78 | u32 last_time = 0; | 83 | u32 last_time = 0; |
| 84 | |||
| 85 | /// Input subsystem to use with this window. | ||
| 86 | InputCommon::InputSubsystem* input_subsystem; | ||
| 79 | }; | 87 | }; |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index e78025737..881b67a76 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp | |||
| @@ -87,8 +87,9 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { | |||
| 87 | return unsupported_ext.empty(); | 87 | return unsupported_ext.empty(); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(Core::System& system, bool fullscreen) | 90 | EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(Core::System& system, bool fullscreen, |
| 91 | : EmuWindow_SDL2{system, fullscreen} { | 91 | InputCommon::InputSubsystem* input_subsystem) |
| 92 | : EmuWindow_SDL2{system, fullscreen, input_subsystem} { | ||
| 92 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); | 93 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); |
| 93 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); | 94 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); |
| 94 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); | 95 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h index 48bb41683..732a64edd 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h | |||
| @@ -8,9 +8,14 @@ | |||
| 8 | #include "core/frontend/emu_window.h" | 8 | #include "core/frontend/emu_window.h" |
| 9 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 9 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| 10 | 10 | ||
| 11 | namespace InputCommon { | ||
| 12 | class InputSubsystem; | ||
| 13 | } | ||
| 14 | |||
| 11 | class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { | 15 | class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { |
| 12 | public: | 16 | public: |
| 13 | explicit EmuWindow_SDL2_GL(Core::System& system, bool fullscreen); | 17 | explicit EmuWindow_SDL2_GL(Core::System& system, bool fullscreen, |
| 18 | InputCommon::InputSubsystem* input_subsystem); | ||
| 14 | ~EmuWindow_SDL2_GL(); | 19 | ~EmuWindow_SDL2_GL(); |
| 15 | 20 | ||
| 16 | void Present() override; | 21 | void Present() override; |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index cb8e68a39..53491f86e 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp | |||
| @@ -19,8 +19,9 @@ | |||
| 19 | #include <SDL.h> | 19 | #include <SDL.h> |
| 20 | #include <SDL_syswm.h> | 20 | #include <SDL_syswm.h> |
| 21 | 21 | ||
| 22 | EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(Core::System& system, bool fullscreen) | 22 | EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(Core::System& system, bool fullscreen, |
| 23 | : EmuWindow_SDL2{system, fullscreen} { | 23 | InputCommon::InputSubsystem* input_subsystem) |
| 24 | : EmuWindow_SDL2{system, fullscreen, input_subsystem} { | ||
| 24 | const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, | 25 | const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, |
| 25 | Common::g_scm_branch, Common::g_scm_desc); | 26 | Common::g_scm_branch, Common::g_scm_desc); |
| 26 | render_window = | 27 | render_window = |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h index 77a6ca72b..f99704d4c 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h | |||
| @@ -13,9 +13,14 @@ namespace Core { | |||
| 13 | class System; | 13 | class System; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | namespace InputCommon { | ||
| 17 | class InputSubsystem; | ||
| 18 | } | ||
| 19 | |||
| 16 | class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { | 20 | class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { |
| 17 | public: | 21 | public: |
| 18 | explicit EmuWindow_SDL2_VK(Core::System& system, bool fullscreen); | 22 | explicit EmuWindow_SDL2_VK(Core::System& system, bool fullscreen, |
| 23 | InputCommon::InputSubsystem* input_subsystem); | ||
| 19 | ~EmuWindow_SDL2_VK(); | 24 | ~EmuWindow_SDL2_VK(); |
| 20 | 25 | ||
| 21 | void Present() override; | 26 | void Present() override; |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 8efe49390..4f00c804d 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -23,12 +23,14 @@ | |||
| 23 | #include "common/telemetry.h" | 23 | #include "common/telemetry.h" |
| 24 | #include "core/core.h" | 24 | #include "core/core.h" |
| 25 | #include "core/crypto/key_manager.h" | 25 | #include "core/crypto/key_manager.h" |
| 26 | #include "core/file_sys/registered_cache.h" | ||
| 26 | #include "core/file_sys/vfs_real.h" | 27 | #include "core/file_sys/vfs_real.h" |
| 27 | #include "core/gdbstub/gdbstub.h" | 28 | #include "core/gdbstub/gdbstub.h" |
| 28 | #include "core/hle/service/filesystem/filesystem.h" | 29 | #include "core/hle/service/filesystem/filesystem.h" |
| 29 | #include "core/loader/loader.h" | 30 | #include "core/loader/loader.h" |
| 30 | #include "core/settings.h" | 31 | #include "core/settings.h" |
| 31 | #include "core/telemetry_session.h" | 32 | #include "core/telemetry_session.h" |
| 33 | #include "input_common/main.h" | ||
| 32 | #include "video_core/renderer_base.h" | 34 | #include "video_core/renderer_base.h" |
| 33 | #include "yuzu_cmd/config.h" | 35 | #include "yuzu_cmd/config.h" |
| 34 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 36 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| @@ -37,8 +39,6 @@ | |||
| 37 | #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" | 39 | #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" |
| 38 | #endif | 40 | #endif |
| 39 | 41 | ||
| 40 | #include "core/file_sys/registered_cache.h" | ||
| 41 | |||
| 42 | #ifdef _WIN32 | 42 | #ifdef _WIN32 |
| 43 | // windows.h needs to be included before shellapi.h | 43 | // windows.h needs to be included before shellapi.h |
| 44 | #include <windows.h> | 44 | #include <windows.h> |
| @@ -179,15 +179,16 @@ int main(int argc, char** argv) { | |||
| 179 | Settings::Apply(); | 179 | Settings::Apply(); |
| 180 | 180 | ||
| 181 | Core::System& system{Core::System::GetInstance()}; | 181 | Core::System& system{Core::System::GetInstance()}; |
| 182 | InputCommon::InputSubsystem input_subsystem; | ||
| 182 | 183 | ||
| 183 | std::unique_ptr<EmuWindow_SDL2> emu_window; | 184 | std::unique_ptr<EmuWindow_SDL2> emu_window; |
| 184 | switch (Settings::values.renderer_backend.GetValue()) { | 185 | switch (Settings::values.renderer_backend.GetValue()) { |
| 185 | case Settings::RendererBackend::OpenGL: | 186 | case Settings::RendererBackend::OpenGL: |
| 186 | emu_window = std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen); | 187 | emu_window = std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen, &input_subsystem); |
| 187 | break; | 188 | break; |
| 188 | case Settings::RendererBackend::Vulkan: | 189 | case Settings::RendererBackend::Vulkan: |
| 189 | #ifdef HAS_VULKAN | 190 | #ifdef HAS_VULKAN |
| 190 | emu_window = std::make_unique<EmuWindow_SDL2_VK>(system, fullscreen); | 191 | emu_window = std::make_unique<EmuWindow_SDL2_VK>(system, fullscreen, &input_subsystem); |
| 191 | break; | 192 | break; |
| 192 | #else | 193 | #else |
| 193 | LOG_CRITICAL(Frontend, "Vulkan backend has not been compiled!"); | 194 | LOG_CRITICAL(Frontend, "Vulkan backend has not been compiled!"); |
diff --git a/src/yuzu_tester/config.cpp b/src/yuzu_tester/config.cpp index 74022af23..aaf59129a 100644 --- a/src/yuzu_tester/config.cpp +++ b/src/yuzu_tester/config.cpp | |||
| @@ -75,6 +75,7 @@ void Config::ReadValues() { | |||
| 75 | Settings::values.debug_pad_analogs[i] = ""; | 75 | Settings::values.debug_pad_analogs[i] = ""; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | Settings::values.vibration_enabled = true; | ||
| 78 | Settings::values.touchscreen.enabled = ""; | 79 | Settings::values.touchscreen.enabled = ""; |
| 79 | Settings::values.touchscreen.device = ""; | 80 | Settings::values.touchscreen.device = ""; |
| 80 | Settings::values.touchscreen.finger = 0; | 81 | Settings::values.touchscreen.finger = 0; |
diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp index 8584f6671..78f75fb38 100644 --- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp +++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | #include <glad/glad.h> | 14 | #include <glad/glad.h> |
| 15 | 15 | ||
| 16 | #include "common/assert.h" | ||
| 17 | #include "common/logging/log.h" | 16 | #include "common/logging/log.h" |
| 18 | #include "common/scm_rev.h" | 17 | #include "common/scm_rev.h" |
| 19 | #include "core/settings.h" | 18 | #include "core/settings.h" |
| @@ -53,7 +52,7 @@ EmuWindow_SDL2_Hide::EmuWindow_SDL2_Hide() { | |||
| 53 | exit(1); | 52 | exit(1); |
| 54 | } | 53 | } |
| 55 | 54 | ||
| 56 | InputCommon::Init(); | 55 | input_subsystem->Initialize(); |
| 57 | 56 | ||
| 58 | SDL_SetMainReady(); | 57 | SDL_SetMainReady(); |
| 59 | 58 | ||
| @@ -105,7 +104,7 @@ EmuWindow_SDL2_Hide::EmuWindow_SDL2_Hide() { | |||
| 105 | } | 104 | } |
| 106 | 105 | ||
| 107 | EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() { | 106 | EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() { |
| 108 | InputCommon::Shutdown(); | 107 | input_subsystem->Shutdown(); |
| 109 | SDL_GL_DeleteContext(gl_context); | 108 | SDL_GL_DeleteContext(gl_context); |
| 110 | SDL_Quit(); | 109 | SDL_Quit(); |
| 111 | } | 110 | } |
diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h index c13a82df2..a553b4b95 100644 --- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h +++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | 8 | ||
| 9 | struct SDL_Window; | 9 | struct SDL_Window; |
| 10 | 10 | ||
| 11 | namespace InputCommon { | ||
| 12 | class InputSubsystem; | ||
| 13 | } | ||
| 14 | |||
| 11 | class EmuWindow_SDL2_Hide : public Core::Frontend::EmuWindow { | 15 | class EmuWindow_SDL2_Hide : public Core::Frontend::EmuWindow { |
| 12 | public: | 16 | public: |
| 13 | explicit EmuWindow_SDL2_Hide(); | 17 | explicit EmuWindow_SDL2_Hide(); |
| @@ -25,6 +29,8 @@ private: | |||
| 25 | /// Whether the GPU and driver supports the OpenGL extension required | 29 | /// Whether the GPU and driver supports the OpenGL extension required |
| 26 | bool SupportsRequiredGLExtensions(); | 30 | bool SupportsRequiredGLExtensions(); |
| 27 | 31 | ||
| 32 | std::unique_ptr<InputCommon::InputSubsystem> input_subsystem; | ||
| 33 | |||
| 28 | /// Internal SDL2 render window | 34 | /// Internal SDL2 render window |
| 29 | SDL_Window* render_window; | 35 | SDL_Window* render_window; |
| 30 | 36 | ||