From 5219615418920be8502aa24507572cf0930d65ea Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Fri, 21 Aug 2020 07:39:24 -0400 Subject: =?UTF-8?q?Project=20Mj=C3=B6lnir:=20Part=202=20-=20Controller=20A?= =?UTF-8?q?pplet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Its-Rei --- dist/icons/controller/applet_dual_joycon.png | Bin 0 -> 3554 bytes dist/icons/controller/applet_dual_joycon_dark.png | Bin 0 -> 3554 bytes .../applet_dual_joycon_dark_disabled.png | Bin 0 -> 3527 bytes .../controller/applet_dual_joycon_disabled.png | Bin 0 -> 3314 bytes .../controller/applet_dual_joycon_midnight.png | Bin 0 -> 3549 bytes .../applet_dual_joycon_midnight_disabled.png | Bin 0 -> 3584 bytes dist/icons/controller/applet_handheld.png | Bin 0 -> 1671 bytes dist/icons/controller/applet_handheld_dark.png | Bin 0 -> 1637 bytes .../controller/applet_handheld_dark_disabled.png | Bin 0 -> 2642 bytes dist/icons/controller/applet_handheld_disabled.png | Bin 0 -> 2221 bytes dist/icons/controller/applet_handheld_midnight.png | Bin 0 -> 1644 bytes .../applet_handheld_midnight_disabled.png | Bin 0 -> 2634 bytes dist/icons/controller/applet_pro_controller.png | Bin 0 -> 4382 bytes .../controller/applet_pro_controller_dark.png | Bin 0 -> 4236 bytes .../applet_pro_controller_dark_disabled.png | Bin 0 -> 4477 bytes .../controller/applet_pro_controller_disabled.png | Bin 0 -> 4173 bytes .../controller/applet_pro_controller_midnight.png | Bin 0 -> 4376 bytes .../applet_pro_controller_midnight_disabled.png | Bin 0 -> 4459 bytes .../icons/controller/applet_single_joycon_left.png | Bin 0 -> 2083 bytes .../controller/applet_single_joycon_left_dark.png | Bin 0 -> 2067 bytes .../applet_single_joycon_left_dark_disabled.png | Bin 0 -> 2520 bytes .../applet_single_joycon_left_disabled.png | Bin 0 -> 2179 bytes .../applet_single_joycon_left_midnight.png | Bin 0 -> 2065 bytes ...applet_single_joycon_left_midnight_disabled.png | Bin 0 -> 2529 bytes .../controller/applet_single_joycon_right.png | Bin 0 -> 2150 bytes .../controller/applet_single_joycon_right_dark.png | Bin 0 -> 2146 bytes .../applet_single_joycon_right_dark_disabled.png | Bin 0 -> 2556 bytes .../applet_single_joycon_right_disabled.png | Bin 0 -> 2212 bytes .../applet_single_joycon_right_midnight.png | Bin 0 -> 2150 bytes ...pplet_single_joycon_right_midnight_disabled.png | Bin 0 -> 2611 bytes dist/icons/controller/controller.qrc | 30 + dist/qt_themes/default/style.qss | 206 +- dist/qt_themes/qdarkstyle/style.qss | 290 ++- dist/qt_themes/qdarkstyle_midnight_blue/style.qss | 270 ++- src/core/CMakeLists.txt | 4 + src/core/frontend/applets/controller.cpp | 40 + src/core/frontend/applets/controller.h | 45 + src/core/hle/service/am/applets/applets.cpp | 71 +- src/core/hle/service/am/applets/applets.h | 19 +- src/core/hle/service/am/applets/controller.cpp | 197 ++ src/core/hle/service/am/applets/controller.h | 119 + src/core/hle/service/hid/controllers/npad.cpp | 28 +- src/core/hle/service/hid/controllers/npad.h | 6 +- src/yuzu/CMakeLists.txt | 12 +- src/yuzu/applets/controller.cpp | 568 +++++ src/yuzu/applets/controller.h | 125 + src/yuzu/applets/controller.ui | 2432 ++++++++++++++++++++ src/yuzu/configuration/configure_input.cpp | 21 +- src/yuzu/configuration/configure_input.h | 2 +- src/yuzu/configuration/configure_input_dialog.cpp | 37 + src/yuzu/configuration/configure_input_dialog.h | 38 + src/yuzu/configuration/configure_input_dialog.ui | 57 + src/yuzu/main.cpp | 35 +- src/yuzu/main.h | 6 + 54 files changed, 4515 insertions(+), 143 deletions(-) create mode 100644 dist/icons/controller/applet_dual_joycon.png create mode 100644 dist/icons/controller/applet_dual_joycon_dark.png create mode 100644 dist/icons/controller/applet_dual_joycon_dark_disabled.png create mode 100644 dist/icons/controller/applet_dual_joycon_disabled.png create mode 100644 dist/icons/controller/applet_dual_joycon_midnight.png create mode 100644 dist/icons/controller/applet_dual_joycon_midnight_disabled.png create mode 100644 dist/icons/controller/applet_handheld.png create mode 100644 dist/icons/controller/applet_handheld_dark.png create mode 100644 dist/icons/controller/applet_handheld_dark_disabled.png create mode 100644 dist/icons/controller/applet_handheld_disabled.png create mode 100644 dist/icons/controller/applet_handheld_midnight.png create mode 100644 dist/icons/controller/applet_handheld_midnight_disabled.png create mode 100644 dist/icons/controller/applet_pro_controller.png create mode 100644 dist/icons/controller/applet_pro_controller_dark.png create mode 100644 dist/icons/controller/applet_pro_controller_dark_disabled.png create mode 100644 dist/icons/controller/applet_pro_controller_disabled.png create mode 100644 dist/icons/controller/applet_pro_controller_midnight.png create mode 100644 dist/icons/controller/applet_pro_controller_midnight_disabled.png create mode 100644 dist/icons/controller/applet_single_joycon_left.png create mode 100644 dist/icons/controller/applet_single_joycon_left_dark.png create mode 100644 dist/icons/controller/applet_single_joycon_left_dark_disabled.png create mode 100644 dist/icons/controller/applet_single_joycon_left_disabled.png create mode 100644 dist/icons/controller/applet_single_joycon_left_midnight.png create mode 100644 dist/icons/controller/applet_single_joycon_left_midnight_disabled.png create mode 100644 dist/icons/controller/applet_single_joycon_right.png create mode 100644 dist/icons/controller/applet_single_joycon_right_dark.png create mode 100644 dist/icons/controller/applet_single_joycon_right_dark_disabled.png create mode 100644 dist/icons/controller/applet_single_joycon_right_disabled.png create mode 100644 dist/icons/controller/applet_single_joycon_right_midnight.png create mode 100644 dist/icons/controller/applet_single_joycon_right_midnight_disabled.png create mode 100644 src/core/frontend/applets/controller.cpp create mode 100644 src/core/frontend/applets/controller.h create mode 100644 src/core/hle/service/am/applets/controller.cpp create mode 100644 src/core/hle/service/am/applets/controller.h create mode 100644 src/yuzu/applets/controller.cpp create mode 100644 src/yuzu/applets/controller.h create mode 100644 src/yuzu/applets/controller.ui create mode 100644 src/yuzu/configuration/configure_input_dialog.cpp create mode 100644 src/yuzu/configuration/configure_input_dialog.h create mode 100644 src/yuzu/configuration/configure_input_dialog.ui diff --git a/dist/icons/controller/applet_dual_joycon.png b/dist/icons/controller/applet_dual_joycon.png new file mode 100644 index 000000000..32e0a04ae Binary files /dev/null and b/dist/icons/controller/applet_dual_joycon.png differ diff --git a/dist/icons/controller/applet_dual_joycon_dark.png b/dist/icons/controller/applet_dual_joycon_dark.png new file mode 100644 index 000000000..6adc66356 Binary files /dev/null and b/dist/icons/controller/applet_dual_joycon_dark.png differ diff --git a/dist/icons/controller/applet_dual_joycon_dark_disabled.png b/dist/icons/controller/applet_dual_joycon_dark_disabled.png new file mode 100644 index 000000000..208603ee7 Binary files /dev/null and b/dist/icons/controller/applet_dual_joycon_dark_disabled.png differ diff --git a/dist/icons/controller/applet_dual_joycon_disabled.png b/dist/icons/controller/applet_dual_joycon_disabled.png new file mode 100644 index 000000000..43950618d Binary files /dev/null and b/dist/icons/controller/applet_dual_joycon_disabled.png differ diff --git a/dist/icons/controller/applet_dual_joycon_midnight.png b/dist/icons/controller/applet_dual_joycon_midnight.png new file mode 100644 index 000000000..c7edea8a3 Binary files /dev/null and b/dist/icons/controller/applet_dual_joycon_midnight.png differ diff --git a/dist/icons/controller/applet_dual_joycon_midnight_disabled.png b/dist/icons/controller/applet_dual_joycon_midnight_disabled.png new file mode 100644 index 000000000..ee1aafc85 Binary files /dev/null and b/dist/icons/controller/applet_dual_joycon_midnight_disabled.png differ diff --git a/dist/icons/controller/applet_handheld.png b/dist/icons/controller/applet_handheld.png new file mode 100644 index 000000000..7f8dd2227 Binary files /dev/null and b/dist/icons/controller/applet_handheld.png differ diff --git a/dist/icons/controller/applet_handheld_dark.png b/dist/icons/controller/applet_handheld_dark.png new file mode 100644 index 000000000..41f6d7aea Binary files /dev/null and b/dist/icons/controller/applet_handheld_dark.png differ diff --git a/dist/icons/controller/applet_handheld_dark_disabled.png b/dist/icons/controller/applet_handheld_dark_disabled.png new file mode 100644 index 000000000..5a136ddd1 Binary files /dev/null and b/dist/icons/controller/applet_handheld_dark_disabled.png differ diff --git a/dist/icons/controller/applet_handheld_disabled.png b/dist/icons/controller/applet_handheld_disabled.png new file mode 100644 index 000000000..53f8ce7ad Binary files /dev/null and b/dist/icons/controller/applet_handheld_disabled.png differ diff --git a/dist/icons/controller/applet_handheld_midnight.png b/dist/icons/controller/applet_handheld_midnight.png new file mode 100644 index 000000000..7188b9154 Binary files /dev/null and b/dist/icons/controller/applet_handheld_midnight.png differ diff --git a/dist/icons/controller/applet_handheld_midnight_disabled.png b/dist/icons/controller/applet_handheld_midnight_disabled.png new file mode 100644 index 000000000..6ccfc3253 Binary files /dev/null and b/dist/icons/controller/applet_handheld_midnight_disabled.png differ diff --git a/dist/icons/controller/applet_pro_controller.png b/dist/icons/controller/applet_pro_controller.png new file mode 100644 index 000000000..e32258855 Binary files /dev/null and b/dist/icons/controller/applet_pro_controller.png differ diff --git a/dist/icons/controller/applet_pro_controller_dark.png b/dist/icons/controller/applet_pro_controller_dark.png new file mode 100644 index 000000000..c122b7b11 Binary files /dev/null and b/dist/icons/controller/applet_pro_controller_dark.png differ diff --git a/dist/icons/controller/applet_pro_controller_dark_disabled.png b/dist/icons/controller/applet_pro_controller_dark_disabled.png new file mode 100644 index 000000000..416e1e2fb Binary files /dev/null and b/dist/icons/controller/applet_pro_controller_dark_disabled.png differ diff --git a/dist/icons/controller/applet_pro_controller_disabled.png b/dist/icons/controller/applet_pro_controller_disabled.png new file mode 100644 index 000000000..72a549ea9 Binary files /dev/null and b/dist/icons/controller/applet_pro_controller_disabled.png differ diff --git a/dist/icons/controller/applet_pro_controller_midnight.png b/dist/icons/controller/applet_pro_controller_midnight.png new file mode 100644 index 000000000..622e57fa1 Binary files /dev/null and b/dist/icons/controller/applet_pro_controller_midnight.png differ diff --git a/dist/icons/controller/applet_pro_controller_midnight_disabled.png b/dist/icons/controller/applet_pro_controller_midnight_disabled.png new file mode 100644 index 000000000..2907f3be4 Binary files /dev/null and b/dist/icons/controller/applet_pro_controller_midnight_disabled.png differ diff --git a/dist/icons/controller/applet_single_joycon_left.png b/dist/icons/controller/applet_single_joycon_left.png new file mode 100644 index 000000000..47c44d43a Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_left.png differ diff --git a/dist/icons/controller/applet_single_joycon_left_dark.png b/dist/icons/controller/applet_single_joycon_left_dark.png new file mode 100644 index 000000000..69530b69c Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_left_dark.png differ diff --git a/dist/icons/controller/applet_single_joycon_left_dark_disabled.png b/dist/icons/controller/applet_single_joycon_left_dark_disabled.png new file mode 100644 index 000000000..cfe4b1475 Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_left_dark_disabled.png differ diff --git a/dist/icons/controller/applet_single_joycon_left_disabled.png b/dist/icons/controller/applet_single_joycon_left_disabled.png new file mode 100644 index 000000000..c0102dc20 Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_left_disabled.png differ diff --git a/dist/icons/controller/applet_single_joycon_left_midnight.png b/dist/icons/controller/applet_single_joycon_left_midnight.png new file mode 100644 index 000000000..56522bccb Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_left_midnight.png differ diff --git a/dist/icons/controller/applet_single_joycon_left_midnight_disabled.png b/dist/icons/controller/applet_single_joycon_left_midnight_disabled.png new file mode 100644 index 000000000..62434c188 Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_left_midnight_disabled.png differ diff --git a/dist/icons/controller/applet_single_joycon_right.png b/dist/icons/controller/applet_single_joycon_right.png new file mode 100644 index 000000000..b0d4fba90 Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_right.png differ diff --git a/dist/icons/controller/applet_single_joycon_right_dark.png b/dist/icons/controller/applet_single_joycon_right_dark.png new file mode 100644 index 000000000..af26cce4b Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_right_dark.png differ diff --git a/dist/icons/controller/applet_single_joycon_right_dark_disabled.png b/dist/icons/controller/applet_single_joycon_right_dark_disabled.png new file mode 100644 index 000000000..b33efab42 Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_right_dark_disabled.png differ diff --git a/dist/icons/controller/applet_single_joycon_right_disabled.png b/dist/icons/controller/applet_single_joycon_right_disabled.png new file mode 100644 index 000000000..01ca38322 Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_right_disabled.png differ diff --git a/dist/icons/controller/applet_single_joycon_right_midnight.png b/dist/icons/controller/applet_single_joycon_right_midnight.png new file mode 100644 index 000000000..5bf70e21e Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_right_midnight.png differ diff --git a/dist/icons/controller/applet_single_joycon_right_midnight_disabled.png b/dist/icons/controller/applet_single_joycon_right_midnight_disabled.png new file mode 100644 index 000000000..e6693b027 Binary files /dev/null and b/dist/icons/controller/applet_single_joycon_right_midnight_disabled.png differ diff --git a/dist/icons/controller/controller.qrc b/dist/icons/controller/controller.qrc index f44725d8f..76083a9ac 100644 --- a/dist/icons/controller/controller.qrc +++ b/dist/icons/controller/controller.qrc @@ -21,5 +21,35 @@ single_joycon_right_vertical.png single_joycon_right_vertical_dark.png single_joycon_right_vertical_midnight.png + applet_dual_joycon.png + applet_dual_joycon_dark.png + applet_dual_joycon_midnight.png + applet_handheld.png + applet_handheld_dark.png + applet_handheld_midnight.png + applet_pro_controller.png + applet_pro_controller_dark.png + applet_pro_controller_midnight.png + applet_single_joycon_left.png + applet_single_joycon_left_dark.png + applet_single_joycon_left_midnight.png + applet_single_joycon_right.png + applet_single_joycon_right_dark.png + applet_single_joycon_right_midnight.png + applet_dual_joycon_disabled.png + applet_dual_joycon_dark_disabled.png + applet_dual_joycon_midnight_disabled.png + applet_handheld_disabled.png + applet_handheld_dark_disabled.png + applet_handheld_midnight_disabled.png + applet_pro_controller_disabled.png + applet_pro_controller_dark_disabled.png + applet_pro_controller_midnight_disabled.png + applet_single_joycon_left_disabled.png + applet_single_joycon_left_dark_disabled.png + applet_single_joycon_left_midnight_disabled.png + applet_single_joycon_right_disabled.png + applet_single_joycon_right_dark_disabled.png + applet_single_joycon_right_midnight_disabled.png diff --git a/dist/qt_themes/default/style.qss b/dist/qt_themes/default/style.qss index 5da56520b..5b05b436b 100644 --- a/dist/qt_themes/default/style.qss +++ b/dist/qt_themes/default/style.qss @@ -41,6 +41,99 @@ QPushButton#buttonRefreshDevices { max-height: 20px; } +QWidget#bottomPerGameInput, +QWidget#topControllerApplet, +QWidget#bottomControllerApplet, +QGroupBox#groupPlayer1Connected:checked, +QGroupBox#groupPlayer2Connected:checked, +QGroupBox#groupPlayer3Connected:checked, +QGroupBox#groupPlayer4Connected:checked, +QGroupBox#groupPlayer5Connected:checked, +QGroupBox#groupPlayer6Connected:checked, +QGroupBox#groupPlayer7Connected:checked, +QGroupBox#groupPlayer8Connected:checked { + background-color: #f5f5f5; +} + +QWidget#topControllerApplet { + border-bottom: 1px solid #828790 +} + +QWidget#bottomPerGameInput, +QWidget#bottomControllerApplet { + border-top: 1px solid #828790 +} + +QWidget#topPerGameInput, +QWidget#middleControllerApplet { + background-color: #fff; +} + +QWidget#topPerGameInput QComboBox, +QWidget#middleControllerApplet QComboBox { + width: 123px; +} + +QWidget#connectedControllers { + background: transparent; +} + +QWidget#playersSupported, +QWidget#controllersSupported, +QWidget#controllerSupported1, +QWidget#controllerSupported2, +QWidget#controllerSupported3, +QWidget#controllerSupported4, +QWidget#controllerSupported5, +QWidget#controllerSupported6 { + border: none; + background: transparent; +} + +QGroupBox#groupPlayer1Connected, +QGroupBox#groupPlayer2Connected, +QGroupBox#groupPlayer3Connected, +QGroupBox#groupPlayer4Connected, +QGroupBox#groupPlayer5Connected, +QGroupBox#groupPlayer6Connected, +QGroupBox#groupPlayer7Connected, +QGroupBox#groupPlayer8Connected { + border: 1px solid #828790; + border-radius: 3px; + padding: 0px; + min-height: 98px; + max-height: 98px; +} + +QGroupBox#groupPlayer1Connected:unchecked, +QGroupBox#groupPlayer2Connected:unchecked, +QGroupBox#groupPlayer3Connected:unchecked, +QGroupBox#groupPlayer4Connected:unchecked, +QGroupBox#groupPlayer5Connected:unchecked, +QGroupBox#groupPlayer6Connected:unchecked, +QGroupBox#groupPlayer7Connected:unchecked, +QGroupBox#groupPlayer8Connected:unchecked { + border: 1px solid #d9d9d9; +} + +QGroupBox#groupPlayer1Connected::title, +QGroupBox#groupPlayer2Connected::title, +QGroupBox#groupPlayer3Connected::title, +QGroupBox#groupPlayer4Connected::title, +QGroupBox#groupPlayer5Connected::title, +QGroupBox#groupPlayer6Connected::title, +QGroupBox#groupPlayer7Connected::title, +QGroupBox#groupPlayer8Connected::title { + subcontrol-origin: margin; + subcontrol-position: top left; + padding-left: 0px; + padding-right: 0px; + padding-top: 1px; + margin-left: 0px; + margin-right: -4px; + margin-bottom: 4px; +} + QCheckBox#checkboxPlayer1Connected, QCheckBox#checkboxPlayer2Connected, QCheckBox#checkboxPlayer3Connected, @@ -49,7 +142,43 @@ QCheckBox#checkboxPlayer5Connected, QCheckBox#checkboxPlayer6Connected, QCheckBox#checkboxPlayer7Connected, QCheckBox#checkboxPlayer8Connected { - spacing: 0px; + spacing: 0px; +} + +QWidget#Player1LEDs QCheckBox, +QWidget#Player2LEDs QCheckBox, +QWidget#Player3LEDs QCheckBox, +QWidget#Player4LEDs QCheckBox, +QWidget#Player5LEDs QCheckBox, +QWidget#Player6LEDs QCheckBox, +QWidget#Player7LEDs QCheckBox, +QWidget#Player8LEDs QCheckBox { + spacing: 0px; +} + +QWidget#Player1LEDs QCheckBox::indicator, +QWidget#Player2LEDs QCheckBox::indicator, +QWidget#Player3LEDs QCheckBox::indicator, +QWidget#Player4LEDs QCheckBox::indicator, +QWidget#Player5LEDs QCheckBox::indicator, +QWidget#Player6LEDs QCheckBox::indicator, +QWidget#Player7LEDs QCheckBox::indicator, +QWidget#Player8LEDs QCheckBox::indicator { + width: 6px; + height: 6px; + margin-left: 0px; +} + +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer1Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer2Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer3Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer4Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer5Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer6Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer7Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer8Connected::indicator { + width: 12px; + height: 12px; } QCheckBox#checkboxPlayer1Connected::indicator, @@ -60,10 +189,38 @@ QCheckBox#checkboxPlayer5Connected::indicator, QCheckBox#checkboxPlayer6Connected::indicator, QCheckBox#checkboxPlayer7Connected::indicator, QCheckBox#checkboxPlayer8Connected::indicator { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } +QGroupBox#groupPlayer1Connected::indicator, +QGroupBox#groupPlayer2Connected::indicator, +QGroupBox#groupPlayer3Connected::indicator, +QGroupBox#groupPlayer4Connected::indicator, +QGroupBox#groupPlayer5Connected::indicator, +QGroupBox#groupPlayer6Connected::indicator, +QGroupBox#groupPlayer7Connected::indicator, +QGroupBox#groupPlayer8Connected::indicator { + width: 16px; + height: 16px; +} + +QWidget#Player1LEDs QCheckBox::indicator:checked, +QWidget#Player2LEDs QCheckBox::indicator:checked, +QWidget#Player3LEDs QCheckBox::indicator:checked, +QWidget#Player4LEDs QCheckBox::indicator:checked, +QWidget#Player5LEDs QCheckBox::indicator:checked, +QWidget#Player6LEDs QCheckBox::indicator:checked, +QWidget#Player7LEDs QCheckBox::indicator:checked, +QWidget#Player8LEDs QCheckBox::indicator:checked, +QGroupBox#groupPlayer1Connected::indicator:checked, +QGroupBox#groupPlayer2Connected::indicator:checked, +QGroupBox#groupPlayer3Connected::indicator:checked, +QGroupBox#groupPlayer4Connected::indicator:checked, +QGroupBox#groupPlayer5Connected::indicator:checked, +QGroupBox#groupPlayer6Connected::indicator:checked, +QGroupBox#groupPlayer7Connected::indicator:checked, +QGroupBox#groupPlayer8Connected::indicator:checked, QCheckBox#checkboxPlayer1Connected::indicator:checked, QCheckBox#checkboxPlayer2Connected::indicator:checked, QCheckBox#checkboxPlayer3Connected::indicator:checked, @@ -73,12 +230,28 @@ QCheckBox#checkboxPlayer6Connected::indicator:checked, QCheckBox#checkboxPlayer7Connected::indicator:checked, QCheckBox#checkboxPlayer8Connected::indicator:checked, QGroupBox#groupConnectedController::indicator:checked { - border-radius: 2px; - border: 1px solid black; - background: #39ff14; - image: none; + border-radius: 2px; + border: 1px solid #929192; + background: #39ff14; + image: none; } +QWidget#Player1LEDs QCheckBox::indicator:unchecked, +QWidget#Player2LEDs QCheckBox::indicator:unchecked, +QWidget#Player3LEDs QCheckBox::indicator:unchecked, +QWidget#Player4LEDs QCheckBox::indicator:unchecked, +QWidget#Player5LEDs QCheckBox::indicator:unchecked, +QWidget#Player6LEDs QCheckBox::indicator:unchecked, +QWidget#Player7LEDs QCheckBox::indicator:unchecked, +QWidget#Player8LEDs QCheckBox::indicator:unchecked, +QGroupBox#groupPlayer1Connected::indicator:unchecked, +QGroupBox#groupPlayer2Connected::indicator:unchecked, +QGroupBox#groupPlayer3Connected::indicator:unchecked, +QGroupBox#groupPlayer4Connected::indicator:unchecked, +QGroupBox#groupPlayer5Connected::indicator:unchecked, +QGroupBox#groupPlayer6Connected::indicator:unchecked, +QGroupBox#groupPlayer7Connected::indicator:unchecked, +QGroupBox#groupPlayer8Connected::indicator:unchecked, QCheckBox#checkboxPlayer1Connected::indicator:unchecked, QCheckBox#checkboxPlayer2Connected::indicator:unchecked, QCheckBox#checkboxPlayer3Connected::indicator:unchecked, @@ -88,8 +261,19 @@ QCheckBox#checkboxPlayer6Connected::indicator:unchecked, QCheckBox#checkboxPlayer7Connected::indicator:unchecked, QCheckBox#checkboxPlayer8Connected::indicator:unchecked, QGroupBox#groupConnectedController::indicator:unchecked { - border-radius: 2px; - border: 1px solid black; - background: transparent; - image: none; + border-radius: 2px; + border: 1px solid #929192; + background: transparent; + image: none; +} + +QWidget#controllerPlayer1, +QWidget#controllerPlayer2, +QWidget#controllerPlayer3, +QWidget#controllerPlayer4, +QWidget#controllerPlayer5, +QWidget#controllerPlayer6, +QWidget#controllerPlayer7, +QWidget#controllerPlayer8 { + background: transparent; } diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss index 16218f0c2..537558c1b 100644 --- a/dist/qt_themes/qdarkstyle/style.qss +++ b/dist/qt_themes/qdarkstyle/style.qss @@ -1284,6 +1284,135 @@ QPushButton#buttonRefreshDevices { padding: 0px 0px; } +QSpinBox#spinboxLStickRange, +QSpinBox#spinboxRStickRange { + padding: 4px 0px 5px 0px; + min-width: 63px; +} + +QSpinBox#vibrationSpin { + padding: 4px 0px 5px 0px; + min-width: 63px; +} + +QSpinBox#spinboxLStickRange:up-button, +QSpinBox#spinboxRStickRange:up-button, +QSpinBox#vibrationSpin:up-button { + left: -2px; +} + +QSpinBox#spinboxLStickRange:down-button, +QSpinBox#spinboxRStickRange:down-button, +QSpinBox#vibrationSpin:down-button { + right: -1px; +} + +QGroupBox#motionGroup::indicator, +QGroupBox#vibrationGroup::indicator { + margin-left: 0px; +} + +QGroupBox#motionGroup::title, +QGroupBox#vibrationGroup::title { + spacing: 2px; + padding-left: 1px; + padding-right: 1px; +} + +QWidget#bottomPerGameInput, +QWidget#topControllerApplet, +QWidget#bottomControllerApplet, +QGroupBox#groupPlayer1Connected:checked, +QGroupBox#groupPlayer2Connected:checked, +QGroupBox#groupPlayer3Connected:checked, +QGroupBox#groupPlayer4Connected:checked, +QGroupBox#groupPlayer5Connected:checked, +QGroupBox#groupPlayer6Connected:checked, +QGroupBox#groupPlayer7Connected:checked, +QGroupBox#groupPlayer8Connected:checked { + background-color: #232629; +} + +QWidget#topPerGameInput, +QWidget#middleControllerApplet { + background-color: #31363b; +} + +QWidget#topPerGameInput QComboBox, +QWidget#middleControllerApplet QComboBox { + width: 119px; +} + +QRadioButton#radioDocked { + margin-left: -3px; +} + + +QRadioButton#radioUndocked { + margin-right: 5px; +} + +QWidget#connectedControllers { + background: transparent; +} + +QWidget#playersSupported, +QWidget#controllersSupported, +QWidget#controllerSupported1, +QWidget#controllerSupported2, +QWidget#controllerSupported3, +QWidget#controllerSupported4, +QWidget#controllerSupported5, +QWidget#controllerSupported6 { + border: none; + background: transparent; +} + +QGroupBox#groupPlayer1Connected, +QGroupBox#groupPlayer2Connected, +QGroupBox#groupPlayer3Connected, +QGroupBox#groupPlayer4Connected, +QGroupBox#groupPlayer5Connected, +QGroupBox#groupPlayer6Connected, +QGroupBox#groupPlayer7Connected, +QGroupBox#groupPlayer8Connected { + border: 1px solid #76797c; + border-radius: 3px; + padding: 0px; + min-height: 98px; + max-height: 98px; + margin-top: 0px; +} + +QGroupBox#groupPlayer1Connected:unchecked, +QGroupBox#groupPlayer2Connected:unchecked, +QGroupBox#groupPlayer3Connected:unchecked, +QGroupBox#groupPlayer4Connected:unchecked, +QGroupBox#groupPlayer5Connected:unchecked, +QGroupBox#groupPlayer6Connected:unchecked, +QGroupBox#groupPlayer7Connected:unchecked, +QGroupBox#groupPlayer8Connected:unchecked { + border: 1px solid #54575b; +} + +QGroupBox#groupPlayer1Connected::title, +QGroupBox#groupPlayer2Connected::title, +QGroupBox#groupPlayer3Connected::title, +QGroupBox#groupPlayer4Connected::title, +QGroupBox#groupPlayer5Connected::title, +QGroupBox#groupPlayer6Connected::title, +QGroupBox#groupPlayer7Connected::title, +QGroupBox#groupPlayer8Connected::title { + subcontrol-origin: margin; + subcontrol-position: top left; + padding-left: 0px; + padding-right: 0px; + padding-top: 1px; + margin-left: -2px; + margin-right: -4px; + margin-bottom: 6px; +} + QCheckBox#checkboxPlayer1Connected, QCheckBox#checkboxPlayer2Connected, QCheckBox#checkboxPlayer3Connected, @@ -1292,7 +1421,56 @@ QCheckBox#checkboxPlayer5Connected, QCheckBox#checkboxPlayer6Connected, QCheckBox#checkboxPlayer7Connected, QCheckBox#checkboxPlayer8Connected { - spacing: 0px; + spacing: 0px; +} + +QWidget#Player1LEDs, +QWidget#Player2LEDs, +QWidget#Player3LEDs, +QWidget#Player4LEDs, +QWidget#Player5LEDs, +QWidget#Player6LEDs, +QWidget#Player7LEDs, +QWidget#Player8LEDs { + background: transparent; +} + +QWidget#Player1LEDs QCheckBox, +QWidget#Player2LEDs QCheckBox, +QWidget#Player3LEDs QCheckBox, +QWidget#Player4LEDs QCheckBox, +QWidget#Player5LEDs QCheckBox, +QWidget#Player6LEDs QCheckBox, +QWidget#Player7LEDs QCheckBox, +QWidget#Player8LEDs QCheckBox { + spacing: 0px; + margin-bottom: 0px; + margin-right: 0px; +} + +QWidget#Player1LEDs QCheckBox::indicator, +QWidget#Player2LEDs QCheckBox::indicator, +QWidget#Player3LEDs QCheckBox::indicator, +QWidget#Player4LEDs QCheckBox::indicator, +QWidget#Player5LEDs QCheckBox::indicator, +QWidget#Player6LEDs QCheckBox::indicator, +QWidget#Player7LEDs QCheckBox::indicator, +QWidget#Player8LEDs QCheckBox::indicator { + width: 6px; + height: 6px; + margin-left: 0px; +} + +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer1Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer2Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer3Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer4Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer5Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer6Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer7Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer8Connected::indicator { + width: 12px; + height: 12px; } QCheckBox#checkboxPlayer1Connected::indicator, @@ -1307,6 +1485,34 @@ QCheckBox#checkboxPlayer8Connected::indicator { height: 14px; } +QGroupBox#groupPlayer1Connected::indicator, +QGroupBox#groupPlayer2Connected::indicator, +QGroupBox#groupPlayer3Connected::indicator, +QGroupBox#groupPlayer4Connected::indicator, +QGroupBox#groupPlayer5Connected::indicator, +QGroupBox#groupPlayer6Connected::indicator, +QGroupBox#groupPlayer7Connected::indicator, +QGroupBox#groupPlayer8Connected::indicator { + width: 16px; + height: 16px; +} + +QWidget#Player1LEDs QCheckBox::indicator:checked, +QWidget#Player2LEDs QCheckBox::indicator:checked, +QWidget#Player3LEDs QCheckBox::indicator:checked, +QWidget#Player4LEDs QCheckBox::indicator:checked, +QWidget#Player5LEDs QCheckBox::indicator:checked, +QWidget#Player6LEDs QCheckBox::indicator:checked, +QWidget#Player7LEDs QCheckBox::indicator:checked, +QWidget#Player8LEDs QCheckBox::indicator:checked, +QGroupBox#groupPlayer1Connected::indicator:checked, +QGroupBox#groupPlayer2Connected::indicator:checked, +QGroupBox#groupPlayer3Connected::indicator:checked, +QGroupBox#groupPlayer4Connected::indicator:checked, +QGroupBox#groupPlayer5Connected::indicator:checked, +QGroupBox#groupPlayer6Connected::indicator:checked, +QGroupBox#groupPlayer7Connected::indicator:checked, +QGroupBox#groupPlayer8Connected::indicator:checked, QCheckBox#checkboxPlayer1Connected::indicator:checked, QCheckBox#checkboxPlayer2Connected::indicator:checked, QCheckBox#checkboxPlayer3Connected::indicator:checked, @@ -1316,12 +1522,28 @@ QCheckBox#checkboxPlayer6Connected::indicator:checked, QCheckBox#checkboxPlayer7Connected::indicator:checked, QCheckBox#checkboxPlayer8Connected::indicator:checked, QGroupBox#groupConnectedController::indicator:checked { - border-radius: 2px; - border: 1px solid #929192; - background: #39ff14; - image: none; -} - + border-radius: 2px; + border: 1px solid #929192; + background: #39ff14; + image: none; +} + +QWidget#Player1LEDs QCheckBox::indicator:unchecked, +QWidget#Player2LEDs QCheckBox::indicator:unchecked, +QWidget#Player3LEDs QCheckBox::indicator:unchecked, +QWidget#Player4LEDs QCheckBox::indicator:unchecked, +QWidget#Player5LEDs QCheckBox::indicator:unchecked, +QWidget#Player6LEDs QCheckBox::indicator:unchecked, +QWidget#Player7LEDs QCheckBox::indicator:unchecked, +QWidget#Player8LEDs QCheckBox::indicator:unchecked, +QGroupBox#groupPlayer1Connected::indicator:unchecked, +QGroupBox#groupPlayer2Connected::indicator:unchecked, +QGroupBox#groupPlayer3Connected::indicator:unchecked, +QGroupBox#groupPlayer4Connected::indicator:unchecked, +QGroupBox#groupPlayer5Connected::indicator:unchecked, +QGroupBox#groupPlayer6Connected::indicator:unchecked, +QGroupBox#groupPlayer7Connected::indicator:unchecked, +QGroupBox#groupPlayer8Connected::indicator:unchecked, QCheckBox#checkboxPlayer1Connected::indicator:unchecked, QCheckBox#checkboxPlayer2Connected::indicator:unchecked, QCheckBox#checkboxPlayer3Connected::indicator:unchecked, @@ -1331,45 +1553,21 @@ QCheckBox#checkboxPlayer6Connected::indicator:unchecked, QCheckBox#checkboxPlayer7Connected::indicator:unchecked, QCheckBox#checkboxPlayer8Connected::indicator:unchecked, QGroupBox#groupConnectedController::indicator:unchecked { - border-radius: 2px; - border: 1px solid #929192; - background: transparent; - image: none; -} - -QSpinBox#spinboxLStickRange, -QSpinBox#spinboxRStickRange { - padding: 4px 0px 5px 0px; - min-width: 63px; -} - -QSpinBox#vibrationSpin { - padding: 4px 0px 5px 0px; - min-width: 63px; -} - -QSpinBox#spinboxLStickRange:up-button, -QSpinBox#spinboxRStickRange:up-button, -QSpinBox#vibrationSpin:up-button { - left: -2px; -} - -QSpinBox#spinboxLStickRange:down-button, -QSpinBox#spinboxRStickRange:down-button, -QSpinBox#vibrationSpin:down-button { - right: -1px; -} - -QGroupBox#motionGroup::indicator, -QGroupBox#vibrationGroup::indicator { - margin-left: 0px; -} - -QGroupBox#motionGroup::title, -QGroupBox#vibrationGroup::title { - spacing: 2px; - padding-left: 1px; - padding-right: 1px; + border-radius: 2px; + border: 1px solid #929192; + background: transparent; + image: none; +} + +QWidget#controllerPlayer1, +QWidget#controllerPlayer2, +QWidget#controllerPlayer3, +QWidget#controllerPlayer4, +QWidget#controllerPlayer5, +QWidget#controllerPlayer6, +QWidget#controllerPlayer7, +QWidget#controllerPlayer8 { + background: transparent; } /* touchscreen mapping widget */ diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss index a714e1475..9f6a0ff1d 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss @@ -2205,7 +2205,179 @@ QPushButton#buttonRefreshDevices { padding: 0px 0px; } +QSpinBox#spinboxLStickRange, +QSpinBox#spinboxRStickRange { + min-width: 38px; +} + +QGroupBox#motionGroup::indicator, +QGroupBox#vibrationGroup::indicator { + margin-left: 0px; +} + +QWidget#bottomPerGameInput QGroupBox#motionGroup, +QWidget#bottomPerGameInput QGroupBox#vibrationGroup, +QWidget#bottomPerGameInput QGroupBox#inputConfigGroup { + padding: 0px; +} + +QGroupBox#motionGroup::title, +QGroupBox#vibrationGroup::title { + spacing: 2px; + padding-left: 1px; + padding-right: 1px; +} + +QListWidget#selectorList { + background-color: #0f1922; +} + +QSpinBox, +QLineEdit, +QTreeView#hotkey_list, +QScrollArea#scrollArea QTreeView { + background-color: #0f1922; +} + +QWidget#bottomPerGameInput, +QWidget#topControllerApplet, +QWidget#bottomControllerApplet, +QGroupBox#groupPlayer1Connected:checked, +QGroupBox#groupPlayer2Connected:checked, +QGroupBox#groupPlayer3Connected:checked, +QGroupBox#groupPlayer4Connected:checked, +QGroupBox#groupPlayer5Connected:checked, +QGroupBox#groupPlayer6Connected:checked, +QGroupBox#groupPlayer7Connected:checked, +QGroupBox#groupPlayer8Connected:checked { + background-color: #0f1922; +} + +QWidget#topPerGameInput, +QWidget#middleControllerApplet { + background-color: #19232d; +} + +QWidget#topPerGameInput QComboBox, +QWidget#middleControllerApplet QComboBox { + padding-right: 2px; + width: 127px; +} + +QGroupBox#handheldGroup { + padding-left: 0px; +} + +QRadioButton#radioDocked { + margin-left: -1px; + padding-left: 0px; +} + +QRadioButton#radioDocked::indicator { + margin-left: 0px; +} + + +QRadioButton#radioUndocked { + margin-right: 2px; +} + +QWidget#connectedControllers { + background: transparent; +} + +QWidget#playersSupported, +QWidget#controllersSupported, +QWidget#controllerSupported1, +QWidget#controllerSupported2, +QWidget#controllerSupported3, +QWidget#controllerSupported4, +QWidget#controllerSupported5, +QWidget#controllerSupported6 { + border: none; + background: transparent; +} + +QGroupBox#groupPlayer1Connected, +QGroupBox#groupPlayer2Connected, +QGroupBox#groupPlayer3Connected, +QGroupBox#groupPlayer4Connected, +QGroupBox#groupPlayer5Connected, +QGroupBox#groupPlayer6Connected, +QGroupBox#groupPlayer7Connected, +QGroupBox#groupPlayer8Connected { + border: 1px solid #76797c; + border-radius: 3px; + padding: 0px; + min-height: 98px; + max-height: 98px; + margin-top: 0px; +} + + +QGroupBox#groupPlayer1Connected:unchecked, +QGroupBox#groupPlayer2Connected:unchecked, +QGroupBox#groupPlayer3Connected:unchecked, +QGroupBox#groupPlayer4Connected:unchecked, +QGroupBox#groupPlayer5Connected:unchecked, +QGroupBox#groupPlayer6Connected:unchecked, +QGroupBox#groupPlayer7Connected:unchecked, +QGroupBox#groupPlayer8Connected:unchecked { + border: 1px solid #32414b; +} + +QGroupBox#groupPlayer1Connected::title, +QGroupBox#groupPlayer2Connected::title, +QGroupBox#groupPlayer3Connected::title, +QGroupBox#groupPlayer4Connected::title, +QGroupBox#groupPlayer5Connected::title, +QGroupBox#groupPlayer6Connected::title, +QGroupBox#groupPlayer7Connected::title, +QGroupBox#groupPlayer8Connected::title { + subcontrol-origin: margin; + subcontrol-position: top left; + padding-left: 0px; + padding-right: 0px; + padding-top: 1px; + margin-left: -2px; + margin-right: -4px; + margin-bottom: 6px; +} + +QCheckBox#checkboxPlayer1Connected, +QCheckBox#checkboxPlayer2Connected, +QCheckBox#checkboxPlayer3Connected, +QCheckBox#checkboxPlayer4Connected, +QCheckBox#checkboxPlayer5Connected, +QCheckBox#checkboxPlayer6Connected, +QCheckBox#checkboxPlayer7Connected, +QCheckBox#checkboxPlayer8Connected { + spacing: 0px; +} + +QWidget#connectedControllers QLabel { + padding: 0px; +} + +QWidget#Player1LEDs, +QWidget#Player2LEDs, +QWidget#Player3LEDs, +QWidget#Player4LEDs, +QWidget#Player5LEDs, +QWidget#Player6LEDs, +QWidget#Player7LEDs, +QWidget#Player8LEDs { + background: transparent; +} +QWidget#Player1LEDs QCheckBox, +QWidget#Player2LEDs QCheckBox, +QWidget#Player3LEDs QCheckBox, +QWidget#Player4LEDs QCheckBox, +QWidget#Player5LEDs QCheckBox, +QWidget#Player6LEDs QCheckBox, +QWidget#Player7LEDs QCheckBox, +QWidget#Player8LEDs QCheckBox, QCheckBox#checkboxPlayer1Connected, QCheckBox#checkboxPlayer2Connected, QCheckBox#checkboxPlayer3Connected, @@ -2215,6 +2387,34 @@ QCheckBox#checkboxPlayer6Connected, QCheckBox#checkboxPlayer7Connected, QCheckBox#checkboxPlayer8Connected { spacing: 0px; + padding-top: 0px; + padding-bottom: 0px; + background: transparent; +} + +QWidget#Player1LEDs QCheckBox::indicator, +QWidget#Player2LEDs QCheckBox::indicator, +QWidget#Player3LEDs QCheckBox::indicator, +QWidget#Player4LEDs QCheckBox::indicator, +QWidget#Player5LEDs QCheckBox::indicator, +QWidget#Player6LEDs QCheckBox::indicator, +QWidget#Player7LEDs QCheckBox::indicator, +QWidget#Player8LEDs QCheckBox::indicator { + width: 6px; + height: 6px; + margin-left: 0px; +} + +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer1Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer2Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer3Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer4Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer5Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer6Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer7Connected::indicator, +QWidget#bottomPerGameInput QCheckBox#checkboxPlayer8Connected::indicator { + width: 12px; + height: 12px; } QCheckBox#checkboxPlayer1Connected::indicator, @@ -2227,8 +2427,25 @@ QCheckBox#checkboxPlayer7Connected::indicator, QCheckBox#checkboxPlayer8Connected::indicator { width: 14px; height: 14px; + margin-left: 2px; } +QWidget#Player1LEDs QCheckBox::indicator:checked, +QWidget#Player2LEDs QCheckBox::indicator:checked, +QWidget#Player3LEDs QCheckBox::indicator:checked, +QWidget#Player4LEDs QCheckBox::indicator:checked, +QWidget#Player5LEDs QCheckBox::indicator:checked, +QWidget#Player6LEDs QCheckBox::indicator:checked, +QWidget#Player7LEDs QCheckBox::indicator:checked, +QWidget#Player8LEDs QCheckBox::indicator:checked, +QGroupBox#groupPlayer1Connected::indicator:checked, +QGroupBox#groupPlayer2Connected::indicator:checked, +QGroupBox#groupPlayer3Connected::indicator:checked, +QGroupBox#groupPlayer4Connected::indicator:checked, +QGroupBox#groupPlayer5Connected::indicator:checked, +QGroupBox#groupPlayer6Connected::indicator:checked, +QGroupBox#groupPlayer7Connected::indicator:checked, +QGroupBox#groupPlayer8Connected::indicator:checked, QCheckBox#checkboxPlayer1Connected::indicator:checked, QCheckBox#checkboxPlayer2Connected::indicator:checked, QCheckBox#checkboxPlayer3Connected::indicator:checked, @@ -2244,6 +2461,22 @@ QGroupBox#groupConnectedController::indicator:checked { image: none; } +QWidget#Player1LEDs QCheckBox::indicator:unchecked, +QWidget#Player2LEDs QCheckBox::indicator:unchecked, +QWidget#Player3LEDs QCheckBox::indicator:unchecked, +QWidget#Player4LEDs QCheckBox::indicator:unchecked, +QWidget#Player5LEDs QCheckBox::indicator:unchecked, +QWidget#Player6LEDs QCheckBox::indicator:unchecked, +QWidget#Player7LEDs QCheckBox::indicator:unchecked, +QWidget#Player8LEDs QCheckBox::indicator:unchecked, +QGroupBox#groupPlayer1Connected::indicator:unchecked, +QGroupBox#groupPlayer2Connected::indicator:unchecked, +QGroupBox#groupPlayer3Connected::indicator:unchecked, +QGroupBox#groupPlayer4Connected::indicator:unchecked, +QGroupBox#groupPlayer5Connected::indicator:unchecked, +QGroupBox#groupPlayer6Connected::indicator:unchecked, +QGroupBox#groupPlayer7Connected::indicator:unchecked, +QGroupBox#groupPlayer8Connected::indicator:unchecked, QCheckBox#checkboxPlayer1Connected::indicator:unchecked, QCheckBox#checkboxPlayer2Connected::indicator:unchecked, QCheckBox#checkboxPlayer3Connected::indicator:unchecked, @@ -2255,34 +2488,17 @@ QCheckBox#checkboxPlayer8Connected::indicator:unchecked, QGroupBox#groupConnectedController::indicator:unchecked { border-radius: 2px; border: 1px solid #929192; - background: transparent; + background: #19232d; image: none; } -QSpinBox#spinboxLStickRange, -QSpinBox#spinboxRStickRange { - min-width: 38px; -} - -QGroupBox#motionGroup::indicator, -QGroupBox#vibrationGroup::indicator { - margin-left: 0px; -} - -QGroupBox#motionGroup::title, -QGroupBox#vibrationGroup::title { -spacing: 2px; - padding-left: 1px; - padding-right: 1px; -} - -QListWidget#selectorList { - background-color: #0f1922; +QWidget#controllerPlayer1, +QWidget#controllerPlayer2, +QWidget#controllerPlayer3, +QWidget#controllerPlayer4, +QWidget#controllerPlayer5, +QWidget#controllerPlayer6, +QWidget#controllerPlayer7, +QWidget#controllerPlayer8 { + background: transparent; } - -QSpinBox, -QLineEdit, -QTreeView#hotkey_list, -QScrollArea#scrollArea QTreeView { - background-color: #0f1922; -} \ No newline at end of file diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c85c9485f..a39940e4c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -126,6 +126,8 @@ add_library(core STATIC file_sys/vfs_vector.h file_sys/xts_archive.cpp file_sys/xts_archive.h + frontend/applets/controller.cpp + frontend/applets/controller.h frontend/applets/error.cpp frontend/applets/error.h frontend/applets/general_frontend.cpp @@ -244,6 +246,8 @@ add_library(core STATIC hle/service/am/applet_oe.h hle/service/am/applets/applets.cpp hle/service/am/applets/applets.h + hle/service/am/applets/controller.cpp + hle/service/am/applets/controller.h hle/service/am/applets/error.cpp hle/service/am/applets/error.h hle/service/am/applets/general_backend.cpp diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp new file mode 100644 index 000000000..0fbc7932c --- /dev/null +++ b/src/core/frontend/applets/controller.cpp @@ -0,0 +1,40 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/core.h" +#include "core/frontend/applets/controller.h" +#include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/hid/hid.h" +#include "core/hle/service/sm/sm.h" + +namespace Core::Frontend { + +ControllerApplet::~ControllerApplet() = default; + +DefaultControllerApplet::~DefaultControllerApplet() = default; + +void DefaultControllerApplet::ReconfigureControllers(std::function callback, + ControllerParameters parameters) const { + LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); + + auto& npad = + Core::System::GetInstance() + .ServiceManager() + .GetService("hid") + ->GetAppletResource() + ->GetController(Service::HID::HidController::NPad); + + auto& players = Settings::values.players; + + // Deduce the best configuration based on the input parameters. + for (std::size_t index = 0; index < players.size(); ++index) { + // First, disconnect all controllers regardless of the value of keep_controllers_connected. + // This makes it easy to connect the desired controllers. + npad.DisconnectNPadAtIndex(index); + } + + callback(); +} + +} // namespace Core::Frontend diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h new file mode 100644 index 000000000..0908f2b69 --- /dev/null +++ b/src/core/frontend/applets/controller.h @@ -0,0 +1,45 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "common/common_types.h" + +namespace Core::Frontend { + +using BorderColor = std::array; + +struct ControllerParameters { + s8 min_players{}; + s8 max_players{}; + bool keep_controllers_connected{}; + bool enable_single_mode{}; + bool enable_border_color{}; + std::vector border_colors{}; + bool allow_pro_controller{}; + bool allow_handheld{}; + bool allow_dual_joycons{}; + bool allow_left_joycon{}; + bool allow_right_joycon{}; +}; + +class ControllerApplet { +public: + virtual ~ControllerApplet(); + + virtual void ReconfigureControllers(std::function callback, + ControllerParameters parameters) const = 0; +}; + +class DefaultControllerApplet final : public ControllerApplet { +public: + ~DefaultControllerApplet() override; + + void ReconfigureControllers(std::function callback, + ControllerParameters parameters) const override; +}; + +} // namespace Core::Frontend diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index c3261f3e6..4e0800f9a 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -5,6 +5,7 @@ #include #include "common/assert.h" #include "core/core.h" +#include "core/frontend/applets/controller.h" #include "core/frontend/applets/error.h" #include "core/frontend/applets/general_frontend.h" #include "core/frontend/applets/profile_select.h" @@ -15,6 +16,7 @@ #include "core/hle/kernel/writable_event.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/am/applets/controller.h" #include "core/hle/service/am/applets/error.h" #include "core/hle/service/am/applets/general_backend.h" #include "core/hle/service/am/applets/profile_select.h" @@ -140,14 +142,14 @@ void Applet::Initialize() { AppletFrontendSet::AppletFrontendSet() = default; -AppletFrontendSet::AppletFrontendSet(ParentalControlsApplet parental_controls, ErrorApplet error, +AppletFrontendSet::AppletFrontendSet(ControllerApplet controller, ECommerceApplet e_commerce, + ErrorApplet error, ParentalControlsApplet parental_controls, PhotoViewer photo_viewer, ProfileSelect profile_select, - SoftwareKeyboard software_keyboard, WebBrowser web_browser, - ECommerceApplet e_commerce) - : parental_controls{std::move(parental_controls)}, error{std::move(error)}, - photo_viewer{std::move(photo_viewer)}, profile_select{std::move(profile_select)}, - software_keyboard{std::move(software_keyboard)}, web_browser{std::move(web_browser)}, - e_commerce{std::move(e_commerce)} {} + SoftwareKeyboard software_keyboard, WebBrowser web_browser) + : controller{std::move(controller)}, e_commerce{std::move(e_commerce)}, error{std::move(error)}, + parental_controls{std::move(parental_controls)}, photo_viewer{std::move(photo_viewer)}, + profile_select{std::move(profile_select)}, software_keyboard{std::move(software_keyboard)}, + web_browser{std::move(web_browser)} {} AppletFrontendSet::~AppletFrontendSet() = default; @@ -164,20 +166,37 @@ const AppletFrontendSet& AppletManager::GetAppletFrontendSet() const { } void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { - if (set.parental_controls != nullptr) - frontend.parental_controls = std::move(set.parental_controls); - if (set.error != nullptr) + if (set.controller != nullptr) { + frontend.controller = std::move(set.controller); + } + + if (set.e_commerce != nullptr) { + frontend.e_commerce = std::move(set.e_commerce); + } + + if (set.error != nullptr) { frontend.error = std::move(set.error); - if (set.photo_viewer != nullptr) + } + + if (set.parental_controls != nullptr) { + frontend.parental_controls = std::move(set.parental_controls); + } + + if (set.photo_viewer != nullptr) { frontend.photo_viewer = std::move(set.photo_viewer); - if (set.profile_select != nullptr) + } + + if (set.profile_select != nullptr) { frontend.profile_select = std::move(set.profile_select); - if (set.software_keyboard != nullptr) + } + + if (set.software_keyboard != nullptr) { frontend.software_keyboard = std::move(set.software_keyboard); - if (set.web_browser != nullptr) + } + + if (set.web_browser != nullptr) { frontend.web_browser = std::move(set.web_browser); - if (set.e_commerce != nullptr) - frontend.e_commerce = std::move(set.e_commerce); + } } void AppletManager::SetDefaultAppletFrontendSet() { @@ -186,15 +205,23 @@ void AppletManager::SetDefaultAppletFrontendSet() { } void AppletManager::SetDefaultAppletsIfMissing() { - if (frontend.parental_controls == nullptr) { - frontend.parental_controls = - std::make_unique(); + if (frontend.controller == nullptr) { + frontend.controller = std::make_unique(); + } + + if (frontend.e_commerce == nullptr) { + frontend.e_commerce = std::make_unique(); } if (frontend.error == nullptr) { frontend.error = std::make_unique(); } + if (frontend.parental_controls == nullptr) { + frontend.parental_controls = + std::make_unique(); + } + if (frontend.photo_viewer == nullptr) { frontend.photo_viewer = std::make_unique(); } @@ -211,10 +238,6 @@ void AppletManager::SetDefaultAppletsIfMissing() { if (frontend.web_browser == nullptr) { frontend.web_browser = std::make_unique(); } - - if (frontend.e_commerce == nullptr) { - frontend.e_commerce = std::make_unique(); - } } void AppletManager::ClearAll() { @@ -225,6 +248,8 @@ std::shared_ptr AppletManager::GetApplet(AppletId id) const { switch (id) { case AppletId::Auth: return std::make_shared(system, *frontend.parental_controls); + case AppletId::Controller: + return std::make_shared(system, *frontend.controller); case AppletId::Error: return std::make_shared(system, *frontend.error); case AppletId::ProfileSelect: diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index e75be86a2..a1f4cf897 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -17,6 +17,7 @@ class System; } namespace Core::Frontend { +class ControllerApplet; class ECommerceApplet; class ErrorApplet; class ParentalControlsApplet; @@ -155,19 +156,20 @@ protected: }; struct AppletFrontendSet { - using ParentalControlsApplet = std::unique_ptr; + using ControllerApplet = std::unique_ptr; + using ECommerceApplet = std::unique_ptr; using ErrorApplet = std::unique_ptr; + using ParentalControlsApplet = std::unique_ptr; using PhotoViewer = std::unique_ptr; using ProfileSelect = std::unique_ptr; using SoftwareKeyboard = std::unique_ptr; using WebBrowser = std::unique_ptr; - using ECommerceApplet = std::unique_ptr; AppletFrontendSet(); - AppletFrontendSet(ParentalControlsApplet parental_controls, ErrorApplet error, - PhotoViewer photo_viewer, ProfileSelect profile_select, - SoftwareKeyboard software_keyboard, WebBrowser web_browser, - ECommerceApplet e_commerce); + AppletFrontendSet(ControllerApplet controller, ECommerceApplet e_commerce, ErrorApplet error, + ParentalControlsApplet parental_controls, PhotoViewer photo_viewer, + ProfileSelect profile_select, SoftwareKeyboard software_keyboard, + WebBrowser web_browser); ~AppletFrontendSet(); AppletFrontendSet(const AppletFrontendSet&) = delete; @@ -176,13 +178,14 @@ struct AppletFrontendSet { AppletFrontendSet(AppletFrontendSet&&) noexcept; AppletFrontendSet& operator=(AppletFrontendSet&&) noexcept; - ParentalControlsApplet parental_controls; + ControllerApplet controller; + ECommerceApplet e_commerce; ErrorApplet error; + ParentalControlsApplet parental_controls; PhotoViewer photo_viewer; ProfileSelect profile_select; SoftwareKeyboard software_keyboard; WebBrowser web_browser; - ECommerceApplet e_commerce; }; class AppletManager { diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp new file mode 100644 index 000000000..2a45a388f --- /dev/null +++ b/src/core/hle/service/am/applets/controller.cpp @@ -0,0 +1,197 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "common/string_util.h" +#include "core/core.h" +#include "core/frontend/applets/controller.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/applets/controller.h" +#include "core/hle/service/hid/controllers/npad.h" + +namespace Service::AM::Applets { + +// This error code (0x183ACA) is thrown when the applet fails to initialize. +[[maybe_unused]] constexpr ResultCode ERR_CONTROLLER_APPLET_3101{ErrorModule::HID, 3101}; +// This error code (0x183CCA) is thrown when the u32 result in ControllerSupportResultInfo is 2. +[[maybe_unused]] constexpr ResultCode ERR_CONTROLLER_APPLET_3102{ErrorModule::HID, 3102}; + +static Core::Frontend::ControllerParameters ConvertToFrontendParameters( + ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, + std::vector identification_colors) { + HID::Controller_NPad::NPadType npad_style_set; + npad_style_set.raw = private_arg.style_set; + + return { + .min_players = header.player_count_min, + .max_players = header.player_count_max, + .keep_controllers_connected = header.enable_take_over_connection, + .enable_single_mode = header.enable_single_mode, + .enable_border_color = header.enable_identification_color, + .border_colors = identification_colors, + .allow_pro_controller = npad_style_set.pro_controller == 1, + .allow_handheld = npad_style_set.handheld == 1, + .allow_dual_joycons = npad_style_set.joycon_dual == 1, + .allow_left_joycon = npad_style_set.joycon_left == 1, + .allow_right_joycon = npad_style_set.joycon_right == 1, + }; +} + +Controller::Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_) + : Applet{system_.Kernel()}, frontend(frontend_) {} + +Controller::~Controller() = default; + +void Controller::Initialize() { + Applet::Initialize(); + + LOG_INFO(Service_HID, "Initializing Controller Applet."); + + LOG_DEBUG(Service_HID, + "Initializing Applet with common_args: arg_version={}, lib_version={}, " + "play_startup_sound={}, size={}, system_tick={}, theme_color={}", + common_args.arguments_version, common_args.library_version, + common_args.play_startup_sound, common_args.size, common_args.system_tick, + common_args.theme_color); + + library_applet_version = LibraryAppletVersion{common_args.library_version}; + + const auto private_arg_storage = broker.PopNormalDataToApplet(); + ASSERT(private_arg_storage != nullptr); + + const auto& private_arg = private_arg_storage->GetData(); + ASSERT(private_arg.size() == sizeof(ControllerSupportArgPrivate)); + + std::memcpy(&controller_private_arg, private_arg.data(), sizeof(ControllerSupportArgPrivate)); + ASSERT_MSG(controller_private_arg.arg_private_size == sizeof(ControllerSupportArgPrivate), + "Unknown ControllerSupportArgPrivate revision={} with size={}", + library_applet_version, controller_private_arg.arg_private_size); + + switch (controller_private_arg.mode) { + case ControllerSupportMode::ShowControllerSupport: { + const auto user_arg_storage = broker.PopNormalDataToApplet(); + ASSERT(user_arg_storage != nullptr); + + const auto& user_arg = user_arg_storage->GetData(); + switch (library_applet_version) { + case LibraryAppletVersion::Version3: + case LibraryAppletVersion::Version4: + case LibraryAppletVersion::Version5: + ASSERT(user_arg.size() == sizeof(ControllerSupportArgOld)); + std::memcpy(&controller_user_arg_old, user_arg.data(), sizeof(ControllerSupportArgOld)); + break; + case LibraryAppletVersion::Version7: + ASSERT(user_arg.size() == sizeof(ControllerSupportArgNew)); + std::memcpy(&controller_user_arg_new, user_arg.data(), sizeof(ControllerSupportArgNew)); + break; + default: + UNIMPLEMENTED_MSG("Unknown ControllerSupportArg revision={} with size={}", + library_applet_version, controller_private_arg.arg_size); + ASSERT(user_arg.size() >= sizeof(ControllerSupportArgNew)); + std::memcpy(&controller_user_arg_new, user_arg.data(), sizeof(ControllerSupportArgNew)); + break; + } + break; + } + case ControllerSupportMode::ShowControllerStrapGuide: + case ControllerSupportMode::ShowControllerFirmwareUpdate: + default: { + UNIMPLEMENTED_MSG("Unimplemented ControllerSupportMode={}", controller_private_arg.mode); + break; + } + } +} + +bool Controller::TransactionComplete() const { + return complete; +} + +ResultCode Controller::GetStatus() const { + return status; +} + +void Controller::ExecuteInteractive() { + UNREACHABLE_MSG("Attempted to call interactive execution on non-interactive applet."); +} + +void Controller::Execute() { + switch (controller_private_arg.mode) { + case ControllerSupportMode::ShowControllerSupport: { + const auto parameters = [this] { + switch (library_applet_version) { + case LibraryAppletVersion::Version3: + case LibraryAppletVersion::Version4: + case LibraryAppletVersion::Version5: + return ConvertToFrontendParameters( + controller_private_arg, controller_user_arg_old.header, + std::vector( + controller_user_arg_old.identification_colors.begin(), + controller_user_arg_old.identification_colors.end())); + case LibraryAppletVersion::Version7: + default: + return ConvertToFrontendParameters( + controller_private_arg, controller_user_arg_new.header, + std::vector( + controller_user_arg_new.identification_colors.begin(), + controller_user_arg_new.identification_colors.end())); + } + }(); + + is_single_mode = parameters.enable_single_mode; + + LOG_DEBUG( + Service_HID, + "Controller Parameters: min_players={}, max_players={}, keep_controllers_connected={}, " + "enable_single_mode={}, enable_border_color={}, allow_pro_controller={}, " + "allow_handheld={}, allow_dual_joycons={}, allow_left_joycon={}, allow_right_joycon={}", + parameters.min_players, parameters.max_players, parameters.keep_controllers_connected, + parameters.enable_single_mode, parameters.enable_border_color, + parameters.allow_pro_controller, parameters.allow_handheld, + parameters.allow_dual_joycons, parameters.allow_left_joycon, + parameters.allow_right_joycon); + + frontend.ReconfigureControllers([this] { ConfigurationComplete(); }, parameters); + break; + } + case ControllerSupportMode::ShowControllerStrapGuide: + case ControllerSupportMode::ShowControllerFirmwareUpdate: + default: { + ConfigurationComplete(); + break; + } + } +} + +void Controller::ConfigurationComplete() { + ControllerSupportResultInfo result_info{}; + + const auto& players = Settings::values.players; + + // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. + // Otherwise, only count connected players from P1-P8. + result_info.player_count = + is_single_mode ? 1 + : static_cast(std::count_if( + players.begin(), players.end() - 2, + [](Settings::PlayerInput player) { return player.connected; })); + + result_info.selected_id = HID::Controller_NPad::IndexToNPad( + std::distance(players.begin(), + std::find_if(players.begin(), players.end(), + [](Settings::PlayerInput player) { return player.connected; }))); + + result_info.result = 0; + + LOG_DEBUG(Service_HID, "Result Info: player_count={}, selected_id={}, result={}", + result_info.player_count, result_info.selected_id, result_info.result); + + complete = true; + out_data = std::vector(sizeof(ControllerSupportResultInfo)); + std::memcpy(out_data.data(), &result_info, out_data.size()); + broker.PushNormalDataFromApplet(std::make_shared(std::move(out_data))); + broker.SignalStateChanged(); +} + +} // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h new file mode 100644 index 000000000..90a78d508 --- /dev/null +++ b/src/core/hle/service/am/applets/controller.h @@ -0,0 +1,119 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "core/hle/result.h" +#include "core/hle/service/am/applets/applets.h" + +namespace Core { +class System; +} + +namespace Service::AM::Applets { + +using IdentificationColor = std::array; + +enum class LibraryAppletVersion : u32_le { + Version3 = 0x3, // 1.0.0 - 2.3.0 + Version4 = 0x4, // 3.0.0 - 5.1.0 + Version5 = 0x5, // 6.0.0 - 7.0.1 + Version7 = 0x7, // 8.0.0+ +}; + +enum class ControllerSupportMode : u8 { + ShowControllerSupport = 0, + ShowControllerStrapGuide = 1, + ShowControllerFirmwareUpdate = 2, +}; + +enum class ControllerSupportCaller : u8 { + Application = 0, + System = 1, +}; + +struct ControllerSupportArgPrivate { + u32 arg_private_size{}; + u32 arg_size{}; + bool flag_0{}; + bool flag_1{}; + ControllerSupportMode mode{}; + ControllerSupportCaller caller{}; + u32 style_set{}; + u32 joy_hold_type{}; +}; +static_assert(sizeof(ControllerSupportArgPrivate) == 0x14, + "ControllerSupportArgPrivate has incorrect size."); + +struct ControllerSupportArgHeader { + s8 player_count_min{}; + s8 player_count_max{}; + bool enable_take_over_connection{}; + bool enable_left_justify{}; + bool enable_permit_joy_dual{}; + bool enable_single_mode{}; + bool enable_identification_color{}; +}; +static_assert(sizeof(ControllerSupportArgHeader) == 0x7, + "ControllerSupportArgHeader has incorrect size."); + +// LibraryAppletVersion 0x3, 0x4, 0x5 +struct ControllerSupportArgOld { + ControllerSupportArgHeader header{}; + std::array identification_colors{}; + bool enable_explain_text{}; + std::array, 4> explain_text{}; +}; +static_assert(sizeof(ControllerSupportArgOld) == 0x21C, + "ControllerSupportArgOld has incorrect size."); + +// LibraryAppletVersion 0x7 +struct ControllerSupportArgNew { + ControllerSupportArgHeader header{}; + std::array identification_colors{}; + bool enable_explain_text{}; + std::array, 8> explain_text{}; +}; +static_assert(sizeof(ControllerSupportArgNew) == 0x430, + "ControllerSupportArgNew has incorrect size."); + +struct ControllerSupportResultInfo { + s8 player_count{}; + INSERT_PADDING_BYTES(3); + u32 selected_id{}; + u32 result{}; +}; +static_assert(sizeof(ControllerSupportResultInfo) == 0xC, + "ControllerSupportResultInfo has incorrect size."); + +class Controller final : public Applet { +public: + explicit Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_); + ~Controller() override; + + void Initialize() override; + + bool TransactionComplete() const override; + ResultCode GetStatus() const override; + void ExecuteInteractive() override; + void Execute() override; + + void ConfigurationComplete(); + +private: + const Core::Frontend::ControllerApplet& frontend; + + LibraryAppletVersion library_applet_version; + ControllerSupportArgPrivate controller_private_arg; + ControllerSupportArgOld controller_user_arg_old; + ControllerSupportArgNew controller_user_arg_new; + bool complete{false}; + ResultCode status{RESULT_SUCCESS}; + bool is_single_mode{false}; + std::vector out_data; +}; + +} // namespace Service::AM::Applets diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 45fde8df2..efb953d93 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -193,7 +193,8 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { controller.battery_level[0] = BATTERY_FULL; controller.battery_level[1] = BATTERY_FULL; controller.battery_level[2] = BATTERY_FULL; - styleset_changed_events[controller_idx].writable->Signal(); + + SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); } void Controller_NPad::OnInit() { @@ -518,13 +519,17 @@ void Controller_NPad::VibrateController(const std::vector& controller_ids, last_processed_vibration = vibrations.back(); } +Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { + return last_processed_vibration; +} + std::shared_ptr Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; return styleset_event.readable; } -Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { - return last_processed_vibration; +void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { + styleset_changed_events[NPadIdToIndex(npad_id)].writable->Signal(); } void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { @@ -534,7 +539,7 @@ void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::siz void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected) { if (!connected) { - DisconnectNPad(IndexToNPad(npad_index)); + DisconnectNPadAtIndex(npad_index); return; } @@ -554,16 +559,19 @@ void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::siz } void Controller_NPad::DisconnectNPad(u32 npad_id) { - const auto npad_index = NPadIdToIndex(npad_id); - connected_controllers[npad_index].is_connected = false; + DisconnectNPadAtIndex(NPadIdToIndex(npad_id)); +} + +void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) { Settings::values.players[npad_index].connected = false; + connected_controllers[npad_index].is_connected = false; auto& controller = shared_memory_entries[npad_index]; controller.joy_styles.raw = 0; // Zero out controller.device_type.raw = 0; controller.properties.raw = 0; - styleset_changed_events[npad_index].writable->Signal(); + SignalStyleSetChangedEvent(IndexToNPad(npad_index)); } void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { @@ -650,13 +658,13 @@ void Controller_NPad::ClearAllConnectedControllers() { } void Controller_NPad::DisconnectAllConnectedControllers() { - for (ControllerHolder& controller : connected_controllers) { + for (auto& controller : connected_controllers) { controller.is_connected = false; } } void Controller_NPad::ConnectAllDisconnectedControllers() { - for (ControllerHolder& controller : connected_controllers) { + for (auto& controller : connected_controllers) { if (controller.type != NPadControllerType::None && !controller.is_connected) { controller.is_connected = true; } @@ -664,7 +672,7 @@ void Controller_NPad::ConnectAllDisconnectedControllers() { } void Controller_NPad::ClearAllControllers() { - for (ControllerHolder& controller : connected_controllers) { + for (auto& controller : connected_controllers) { controller.type = NPadControllerType::None; controller.is_connected = false; } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 75ce5b731..40c763376 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -115,15 +115,19 @@ public: void VibrateController(const std::vector& controller_ids, const std::vector& vibrations); - std::shared_ptr GetStyleSetChangedEvent(u32 npad_id) const; Vibration GetLastVibration() const; + std::shared_ptr GetStyleSetChangedEvent(u32 npad_id) const; + void SignalStyleSetChangedEvent(u32 npad_id) const; + // Adds a new controller at an index. void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); // Adds a new controller at an index with connection status. void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); void DisconnectNPad(u32 npad_id); + void DisconnectNPadAtIndex(std::size_t index); + void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; LedPattern GetLedPattern(u32 npad_id); diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 3ea4e5601..cc0291b15 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -9,6 +9,9 @@ add_executable(yuzu about_dialog.cpp about_dialog.h aboutdialog.ui + applets/controller.cpp + applets/controller.h + applets/controller.ui applets/error.cpp applets/error.h applets/profile_select.cpp @@ -62,12 +65,15 @@ add_executable(yuzu configuration/configure_input.cpp configuration/configure_input.h configuration/configure_input.ui - configuration/configure_input_player.cpp - configuration/configure_input_player.h - configuration/configure_input_player.ui configuration/configure_input_advanced.cpp configuration/configure_input_advanced.h configuration/configure_input_advanced.ui + configuration/configure_input_dialog.cpp + configuration/configure_input_dialog.h + configuration/configure_input_dialog.ui + configuration/configure_input_player.cpp + configuration/configure_input_player.h + configuration/configure_input_player.ui configuration/configure_motion_touch.cpp configuration/configure_motion_touch.h configuration/configure_motion_touch.ui diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp new file mode 100644 index 000000000..8ccf61be0 --- /dev/null +++ b/src/yuzu/applets/controller.cpp @@ -0,0 +1,568 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "core/core.h" +#include "core/hle/lock.h" +#include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/hid/hid.h" +#include "core/hle/service/sm/sm.h" +#include "ui_controller.h" +#include "yuzu/applets/controller.h" +#include "yuzu/configuration/configure_input_dialog.h" +#include "yuzu/main.h" + +constexpr std::array, 8> led_patterns = {{ + {1, 0, 0, 0}, + {1, 1, 0, 0}, + {1, 1, 1, 0}, + {1, 1, 1, 1}, + {1, 0, 0, 1}, + {1, 0, 1, 0}, + {1, 0, 1, 1}, + {0, 1, 1, 0}, +}}; + +namespace { + +void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, + bool connected) { + Core::System& system{Core::System::GetInstance()}; + + if (!system.IsPoweredOn()) { + return; + } + + Service::SM::ServiceManager& sm = system.ServiceManager(); + + auto& npad = + sm.GetService("hid") + ->GetAppletResource() + ->GetController(Service::HID::HidController::NPad); + + npad.UpdateControllerAt(npad.MapSettingsTypeToNPad(controller_type), npad_index, connected); +} + +bool IsControllerCompatible(Settings::ControllerType controller_type, + Core::Frontend::ControllerParameters parameters) { + switch (controller_type) { + case Settings::ControllerType::ProController: + return parameters.allow_pro_controller; + case Settings::ControllerType::DualJoyconDetached: + return parameters.allow_dual_joycons; + case Settings::ControllerType::LeftJoycon: + return parameters.allow_left_joycon; + case Settings::ControllerType::RightJoycon: + return parameters.allow_right_joycon; + case Settings::ControllerType::Handheld: + return parameters.enable_single_mode && parameters.allow_handheld; + default: + return false; + } +} + +/// Maps the controller type combobox index to Controller Type enum +constexpr Settings::ControllerType GetControllerTypeFromIndex(int index) { + switch (index) { + case 0: + default: + return Settings::ControllerType::ProController; + case 1: + return Settings::ControllerType::DualJoyconDetached; + case 2: + return Settings::ControllerType::LeftJoycon; + case 3: + return Settings::ControllerType::RightJoycon; + case 4: + return Settings::ControllerType::Handheld; + } +} + +/// Maps the Controller Type enum to controller type combobox index +constexpr int GetIndexFromControllerType(Settings::ControllerType type) { + switch (type) { + case Settings::ControllerType::ProController: + default: + return 0; + case Settings::ControllerType::DualJoyconDetached: + return 1; + case Settings::ControllerType::LeftJoycon: + return 2; + case Settings::ControllerType::RightJoycon: + return 3; + case Settings::ControllerType::Handheld: + return 4; + } +} + +} // namespace + +QtControllerSelectorDialog::QtControllerSelectorDialog( + QWidget* parent, Core::Frontend::ControllerParameters parameters_, InputCommon::InputSubsystem* input_subsystem_) + : QDialog(parent), ui(std::make_unique()), + parameters(std::move(parameters_)), input_subsystem(input_subsystem_) { + ui->setupUi(this); + + player_widgets = { + ui->widgetPlayer1, ui->widgetPlayer2, ui->widgetPlayer3, ui->widgetPlayer4, + ui->widgetPlayer5, ui->widgetPlayer6, ui->widgetPlayer7, ui->widgetPlayer8, + }; + + player_groupboxes = { + ui->groupPlayer1Connected, ui->groupPlayer2Connected, ui->groupPlayer3Connected, + ui->groupPlayer4Connected, ui->groupPlayer5Connected, ui->groupPlayer6Connected, + ui->groupPlayer7Connected, ui->groupPlayer8Connected, + }; + + connected_controller_icons = { + ui->controllerPlayer1, ui->controllerPlayer2, ui->controllerPlayer3, ui->controllerPlayer4, + ui->controllerPlayer5, ui->controllerPlayer6, ui->controllerPlayer7, ui->controllerPlayer8, + }; + + led_patterns_boxes = {{ + {ui->checkboxPlayer1LED1, ui->checkboxPlayer1LED2, ui->checkboxPlayer1LED3, + ui->checkboxPlayer1LED4}, + {ui->checkboxPlayer2LED1, ui->checkboxPlayer2LED2, ui->checkboxPlayer2LED3, + ui->checkboxPlayer2LED4}, + {ui->checkboxPlayer3LED1, ui->checkboxPlayer3LED2, ui->checkboxPlayer3LED3, + ui->checkboxPlayer3LED4}, + {ui->checkboxPlayer4LED1, ui->checkboxPlayer4LED2, ui->checkboxPlayer4LED3, + ui->checkboxPlayer4LED4}, + {ui->checkboxPlayer5LED1, ui->checkboxPlayer5LED2, ui->checkboxPlayer5LED3, + ui->checkboxPlayer5LED4}, + {ui->checkboxPlayer6LED1, ui->checkboxPlayer6LED2, ui->checkboxPlayer6LED3, + ui->checkboxPlayer6LED4}, + {ui->checkboxPlayer7LED1, ui->checkboxPlayer7LED2, ui->checkboxPlayer7LED3, + ui->checkboxPlayer7LED4}, + {ui->checkboxPlayer8LED1, ui->checkboxPlayer8LED2, ui->checkboxPlayer8LED3, + ui->checkboxPlayer8LED4}, + }}; + + emulated_controllers = { + ui->comboPlayer1Emulated, ui->comboPlayer2Emulated, ui->comboPlayer3Emulated, + ui->comboPlayer4Emulated, ui->comboPlayer5Emulated, ui->comboPlayer6Emulated, + ui->comboPlayer7Emulated, ui->comboPlayer8Emulated, + }; + + player_labels = { + ui->labelPlayer1, ui->labelPlayer2, ui->labelPlayer3, ui->labelPlayer4, + ui->labelPlayer5, ui->labelPlayer6, ui->labelPlayer7, ui->labelPlayer8, + }; + + connected_controller_labels = { + ui->labelConnectedPlayer1, ui->labelConnectedPlayer2, ui->labelConnectedPlayer3, + ui->labelConnectedPlayer4, ui->labelConnectedPlayer5, ui->labelConnectedPlayer6, + ui->labelConnectedPlayer7, ui->labelConnectedPlayer8, + }; + + connected_controller_checkboxes = { + ui->checkboxPlayer1Connected, ui->checkboxPlayer2Connected, ui->checkboxPlayer3Connected, + ui->checkboxPlayer4Connected, ui->checkboxPlayer5Connected, ui->checkboxPlayer6Connected, + ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected, + }; + + for (std::size_t i = 0; i < player_widgets.size(); ++i) { + connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) { + if (checked) { + for (std::size_t index = 0; index <= i; ++index) { + connected_controller_checkboxes[index]->setChecked(checked); + } + } else { + for (std::size_t index = i; index < player_widgets.size(); ++index) { + connected_controller_checkboxes[index]->setChecked(checked); + } + } + }); + + connect(emulated_controllers[i], qOverload(&QComboBox::currentIndexChanged), + [this, i](int) { + UpdateControllerIcon(i); + UpdateControllerState(i); + UpdateLEDPattern(i); + CheckIfParametersMet(); + }); + + connect(connected_controller_checkboxes[i], &QCheckBox::stateChanged, [this, i](int state) { + player_groupboxes[i]->setChecked(state == Qt::Checked); + UpdateControllerIcon(i); + UpdateControllerState(i); + UpdateLEDPattern(i); + UpdateBorderColor(i); + CheckIfParametersMet(); + }); + + if (i == 0) { + connect(emulated_controllers[i], qOverload(&QComboBox::currentIndexChanged), + [this](int index) { + UpdateDockedState(GetControllerTypeFromIndex(index) == + Settings::ControllerType::Handheld); + }); + } + } + + connect(ui->inputConfigButton, &QPushButton::clicked, this, + &QtControllerSelectorDialog::CallConfigureInputDialog); + + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, + &QtControllerSelectorDialog::ApplyConfiguration); + + SetSupportedControllers(); + DisableUnsupportedPlayers(); + LoadConfiguration(); + + // If keep_controllers_connected is false, forcefully disconnect all controllers + if (!parameters.keep_controllers_connected) { + for (auto player : player_groupboxes) { + player->setChecked(false); + } + } + + CheckIfParametersMet(); + + resize(0, 0); +} + +QtControllerSelectorDialog::~QtControllerSelectorDialog() = default; + +void QtControllerSelectorDialog::ApplyConfiguration() { + const bool pre_docked_mode = Settings::values.use_docked_mode; + Settings::values.use_docked_mode = ui->radioDocked->isChecked(); + OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); + + Settings::values.vibration_enabled = ui->vibrationGroup->isChecked(); +} + +void QtControllerSelectorDialog::CallConfigureInputDialog() { + const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; + + ConfigureInputDialog dialog(this, max_supported_players, input_subsystem); + + dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | + Qt::WindowSystemMenuHint); + dialog.setWindowModality(Qt::WindowModal); + dialog.exec(); + + dialog.ApplyConfiguration(); + + LoadConfiguration(); + CheckIfParametersMet(); +} + +void QtControllerSelectorDialog::CheckIfParametersMet() { + // Here, we check and validate the current configuration against all applicable parameters. + const auto& players = Settings::values.players; + + const auto num_connected_players = + std::count_if(player_groupboxes.begin(), player_groupboxes.end(), + [this](const QGroupBox* player) { return player->isChecked(); }); + + const auto min_supported_players = parameters.enable_single_mode ? 1 : parameters.min_players; + const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; + + // First, check against the number of connected players. + if (num_connected_players < min_supported_players || + num_connected_players > max_supported_players) { + parameters_met = false; + ui->buttonBox->setEnabled(parameters_met); + return; + } + + // Next, check against all connected controllers. + const auto all_controllers_compatible = [this] { + for (std::size_t index = 0; index < player_widgets.size(); ++index) { + // Skip controllers that are not used, we only care about the currently connected ones. + if (!player_groupboxes[index]->isChecked() || !player_groupboxes[index]->isEnabled()) { + continue; + } + + const auto compatible = IsControllerCompatible( + GetControllerTypeFromIndex(emulated_controllers[index]->currentIndex()), + parameters); + + // If any controller is found to be incompatible, return false early. + if (!compatible) { + return false; + } + } + + // Reaching here means all currently connected controllers are compatible. + return true; + }(); + + if (!all_controllers_compatible) { + parameters_met = false; + ui->buttonBox->setEnabled(parameters_met); + return; + } + + parameters_met = true; + ui->buttonBox->setEnabled(parameters_met); +} + +void QtControllerSelectorDialog::SetSupportedControllers() { + const QString theme = [this] { + if (QIcon::themeName().contains(QStringLiteral("dark"))) { + return QStringLiteral("_dark"); + } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { + return QStringLiteral("_midnight"); + } else { + return QString{}; + } + }(); + + if (parameters.enable_single_mode && parameters.allow_handheld) { + ui->controllerSupported1->setStyleSheet( + QStringLiteral("image: url(:/controller/applet_handheld%0); ").arg(theme)); + } else { + ui->controllerSupported1->setStyleSheet( + QStringLiteral("image: url(:/controller/applet_handheld%0_disabled); ").arg(theme)); + } + + if (parameters.allow_dual_joycons) { + ui->controllerSupported2->setStyleSheet( + QStringLiteral("image: url(:/controller/applet_dual_joycon%0); ").arg(theme)); + } else { + ui->controllerSupported2->setStyleSheet( + QStringLiteral("image: url(:/controller/applet_dual_joycon%0_disabled); ").arg(theme)); + } + + if (parameters.allow_left_joycon) { + ui->controllerSupported3->setStyleSheet( + QStringLiteral("image: url(:/controller/applet_joycon_left%0); ").arg(theme)); + } else { + ui->controllerSupported3->setStyleSheet( + QStringLiteral("image: url(:/controller/applet_joycon_left%0_disabled); ").arg(theme)); + } + + if (parameters.allow_right_joycon) { + ui->controllerSupported4->setStyleSheet( + QStringLiteral("image: url(:/controller/applet_joycon_right%0); ").arg(theme)); + } else { + ui->controllerSupported4->setStyleSheet( + QStringLiteral("image: url(:/controller/applet_joycon_right%0_disabled); ").arg(theme)); + } + + if (parameters.allow_pro_controller) { + ui->controllerSupported5->setStyleSheet( + QStringLiteral("image: url(:/controller/applet_pro_controller%0); ").arg(theme)); + } else { + ui->controllerSupported5->setStyleSheet( + QStringLiteral("image: url(:/controller/applet_pro_controller%0_disabled); ") + .arg(theme)); + } + + // enable_single_mode overrides min_players and max_players. + if (parameters.enable_single_mode) { + ui->numberSupportedLabel->setText(QStringLiteral("1")); + return; + } + + if (parameters.min_players == parameters.max_players) { + ui->numberSupportedLabel->setText(QStringLiteral("%1").arg(parameters.max_players)); + } else { + ui->numberSupportedLabel->setText( + QStringLiteral("%1 - %2").arg(parameters.min_players).arg(parameters.max_players)); + } +} + +void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) { + if (!player_groupboxes[player_index]->isChecked()) { + connected_controller_icons[player_index]->setStyleSheet(QString{}); + player_labels[player_index]->show(); + return; + } + + const QString stylesheet = [this, player_index] { + switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex())) { + case Settings::ControllerType::ProController: + return QStringLiteral("image: url(:/controller/applet_pro_controller%0); "); + case Settings::ControllerType::DualJoyconDetached: + return QStringLiteral("image: url(:/controller/applet_dual_joycon%0); "); + case Settings::ControllerType::LeftJoycon: + return QStringLiteral("image: url(:/controller/applet_joycon_left%0); "); + case Settings::ControllerType::RightJoycon: + return QStringLiteral("image: url(:/controller/applet_joycon_right%0); "); + case Settings::ControllerType::Handheld: + return QStringLiteral("image: url(:/controller/applet_handheld%0); "); + default: + return QString{}; + } + }(); + + const QString theme = [this] { + if (QIcon::themeName().contains(QStringLiteral("dark"))) { + return QStringLiteral("_dark"); + } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { + return QStringLiteral("_midnight"); + } else { + return QString{}; + } + }(); + + connected_controller_icons[player_index]->setStyleSheet(stylesheet.arg(theme)); + player_labels[player_index]->hide(); +} + +void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) { + auto& player = Settings::values.players[player_index]; + + player.controller_type = + GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex()); + player.connected = player_groupboxes[player_index]->isChecked(); + + // Player 2-8 + if (player_index != 0) { + UpdateController(player.controller_type, player_index, player.connected); + return; + } + + // Player 1 and Handheld + auto& handheld = Settings::values.players[8]; + // If Handheld is selected, copy all the settings from Player 1 to Handheld. + if (player.controller_type == Settings::ControllerType::Handheld) { + handheld = player; + handheld.connected = player_groupboxes[player_index]->isChecked(); + player.connected = false; // Disconnect Player 1 + } else { + player.connected = player_groupboxes[player_index]->isChecked(); + handheld.connected = false; // Disconnect Handheld + } + + UpdateController(player.controller_type, player_index, player.connected); + UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected); +} + +void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { + if (!player_groupboxes[player_index]->isChecked() || + GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex()) == + Settings::ControllerType::Handheld) { + led_patterns_boxes[player_index][0]->setChecked(false); + led_patterns_boxes[player_index][1]->setChecked(false); + led_patterns_boxes[player_index][2]->setChecked(false); + led_patterns_boxes[player_index][3]->setChecked(false); + return; + } + + led_patterns_boxes[player_index][0]->setChecked(led_patterns[player_index][0]); + led_patterns_boxes[player_index][1]->setChecked(led_patterns[player_index][1]); + led_patterns_boxes[player_index][2]->setChecked(led_patterns[player_index][2]); + led_patterns_boxes[player_index][3]->setChecked(led_patterns[player_index][3]); +} + +void QtControllerSelectorDialog::UpdateBorderColor(std::size_t player_index) { + if (!parameters.enable_border_color || player_index >= parameters.max_players || + player_groupboxes[player_index]->styleSheet().contains(QStringLiteral("QGroupBox"))) { + return; + } + + player_groupboxes[player_index]->setStyleSheet( + player_groupboxes[player_index]->styleSheet().append( + QStringLiteral("QGroupBox#groupPlayer%1Connected:checked " + "{ border: 1px solid rgba(%2, %3, %4, %5); }") + .arg(player_index + 1) + .arg(parameters.border_colors[player_index][0]) + .arg(parameters.border_colors[player_index][1]) + .arg(parameters.border_colors[player_index][2]) + .arg(parameters.border_colors[player_index][3]))); +} + +void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) { + // Disallow changing the console mode if the controller type is handheld. + ui->radioDocked->setEnabled(!is_handheld); + ui->radioUndocked->setEnabled(!is_handheld); + + ui->radioDocked->setChecked(Settings::values.use_docked_mode); + ui->radioUndocked->setChecked(!Settings::values.use_docked_mode); + + // Also force into undocked mode if the controller type is handheld. + if (is_handheld) { + ui->radioUndocked->setChecked(true); + } +} + +void QtControllerSelectorDialog::DisableUnsupportedPlayers() { + const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; + + switch (max_supported_players) { + case 0: + default: + UNREACHABLE(); + return; + case 1: + ui->widgetSpacer->hide(); + ui->widgetSpacer2->hide(); + ui->widgetSpacer3->hide(); + ui->widgetSpacer4->hide(); + break; + case 2: + ui->widgetSpacer->hide(); + ui->widgetSpacer2->hide(); + ui->widgetSpacer3->hide(); + break; + case 3: + ui->widgetSpacer->hide(); + ui->widgetSpacer2->hide(); + break; + case 4: + ui->widgetSpacer->hide(); + break; + case 5: + case 6: + case 7: + case 8: + break; + } + + for (std::size_t index = max_supported_players; index < player_widgets.size(); ++index) { + // Disconnect any unsupported players here and disable or hide them if applicable. + Settings::values.players[index].connected = false; + UpdateController(Settings::values.players[index].controller_type, index, false); + // Hide the player widgets when max_supported_controllers is less than or equal to 4. + if (max_supported_players <= 4) { + player_widgets[index]->hide(); + } + + // Disable and hide the following to prevent these from interaction. + player_widgets[index]->setDisabled(true); + connected_controller_checkboxes[index]->setDisabled(true); + connected_controller_labels[index]->hide(); + connected_controller_checkboxes[index]->hide(); + } +} + +void QtControllerSelectorDialog::LoadConfiguration() { + for (std::size_t index = 0; index < player_widgets.size(); ++index) { + const auto connected = Settings::values.players[index].connected || + (index == 0 && Settings::values.players[8].connected); + player_groupboxes[index]->setChecked(connected); + emulated_controllers[index]->setCurrentIndex( + GetIndexFromControllerType(Settings::values.players[index].controller_type)); + } + + UpdateDockedState(Settings::values.players[8].connected); + + ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); +} + +QtControllerSelector::QtControllerSelector(GMainWindow& parent) { + connect(this, &QtControllerSelector::MainWindowReconfigureControllers, &parent, + &GMainWindow::ControllerSelectorReconfigureControllers, Qt::QueuedConnection); + connect(&parent, &GMainWindow::ControllerSelectorReconfigureFinished, this, + &QtControllerSelector::MainWindowReconfigureFinished, Qt::QueuedConnection); +} + +QtControllerSelector::~QtControllerSelector() = default; + +void QtControllerSelector::ReconfigureControllers( + std::function callback, Core::Frontend::ControllerParameters parameters) const { + this->callback = std::move(callback); + emit MainWindowReconfigureControllers(parameters); +} + +void QtControllerSelector::MainWindowReconfigureFinished() { + // Acquire the HLE mutex + std::lock_guard lock(HLE::g_hle_lock); + callback(); +} diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h new file mode 100644 index 000000000..1ec290e6c --- /dev/null +++ b/src/yuzu/applets/controller.h @@ -0,0 +1,125 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include "core/frontend/applets/controller.h" + +class GMainWindow; +class QCheckBox; +class QComboBox; +class QDialogButtonBox; +class QGroupBox; +class QLabel; + +namespace InputCommon { +class InputSubsystem; +} + +namespace Ui { +class QtControllerSelectorDialog; +} + +class QtControllerSelectorDialog final : public QDialog { + Q_OBJECT + +public: + explicit QtControllerSelectorDialog(QWidget* parent, + Core::Frontend::ControllerParameters parameters_, + InputCommon::InputSubsystem* input_subsystem_); + ~QtControllerSelectorDialog() override; + +private: + // Applies the current configuration. + void ApplyConfiguration(); + + // Initializes the "Configure Input" Dialog. + void CallConfigureInputDialog(); + + // Checks the current configuration against the given parameters and + // sets the value of parameters_met. + void CheckIfParametersMet(); + + // Sets the controller icons for "Supported Controller Types". + void SetSupportedControllers(); + + // Updates the controller icons per player. + void UpdateControllerIcon(std::size_t player_index); + + // Updates the controller state (type and connection status) per player. + void UpdateControllerState(std::size_t player_index); + + // Updates the LED pattern per player. + void UpdateLEDPattern(std::size_t player_index); + + // Updates the border color per player. + void UpdateBorderColor(std::size_t player_index); + + // Updates the console mode. + void UpdateDockedState(bool is_handheld); + + // Disables and disconnects unsupported players based on the given parameters. + void DisableUnsupportedPlayers(); + + // Loads the current input configuration into the frontend applet. + void LoadConfiguration(); + + std::unique_ptr ui; + + // Parameters sent in from the backend HLE applet. + Core::Frontend::ControllerParameters parameters; + + InputCommon::InputSubsystem* input_subsystem; + + // This is true if and only if all parameters are met. Otherwise, this is false. + // This determines whether the "Ok" button can be clicked to exit the applet. + bool parameters_met{false}; + + // Widgets encapsulating the groupboxes and comboboxes per player. + std::array player_widgets; + + // Groupboxes encapsulating the controller icons and LED patterns per player. + std::array player_groupboxes; + + // Icons for currently connected controllers/players. + std::array connected_controller_icons; + + // Labels that represent the player numbers in place of the controller icons. + std::array player_labels; + + // LED patterns for currently connected controllers/players. + std::array, 8> led_patterns_boxes; + + // Comboboxes with a list of emulated controllers per player. + std::array emulated_controllers; + + // Labels representing the number of connected controllers + // above the "Connected Controllers" checkboxes. + std::array connected_controller_labels; + + // Checkboxes representing the "Connected Controllers". + std::array connected_controller_checkboxes; +}; + +class QtControllerSelector final : public QObject, public Core::Frontend::ControllerApplet { + Q_OBJECT + +public: + explicit QtControllerSelector(GMainWindow& parent); + ~QtControllerSelector() override; + + void ReconfigureControllers(std::function callback, + Core::Frontend::ControllerParameters parameters) const override; + +signals: + void MainWindowReconfigureControllers(Core::Frontend::ControllerParameters parameters) const; + +private: + void MainWindowReconfigureFinished(); + + mutable std::function callback; +}; diff --git a/src/yuzu/applets/controller.ui b/src/yuzu/applets/controller.ui new file mode 100644 index 000000000..d7db46613 --- /dev/null +++ b/src/yuzu/applets/controller.ui @@ -0,0 +1,2432 @@ + + + QtControllerSelectorDialog + + + + 0 + 0 + 839 + 630 + + + + Controller Applet + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 10 + + + 0 + + + 10 + + + 0 + + + 10 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + 75 + true + + + + Supported Controller Types: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + + + + + + + 0 + 0 + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + 0 + + + 0 + + + 16 + + + 14 + + + 16 + + + + + + 75 + true + + + + Players: + + + Qt::AlignCenter + + + false + + + + + + + + 14 + + + + 1 - 8 + + + Qt::AlignCenter + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 5 + + + + + + 5 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 100 + 100 + + + + + 100 + 100 + + + + + + + true + + + false + + + + 7 + + + 14 + + + 7 + + + 14 + + + 4 + + + + + + + + + 16 + + + + + P4 + + + + + + + + + + false + + + + 0 + 10 + + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + 0 + 10 + + + + + + + + + Pro Controller + + + + + Dual Joycons + + + + + Left Joycon + + + + + Right Joycon + + + + + + + + + Use Current Config + + + + + + + + + + + + 5 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 100 + 100 + + + + + 100 + 100 + + + + + + + true + + + false + + + + 7 + + + 14 + + + 7 + + + 14 + + + 4 + + + + + + + + + 16 + + + + + P2 + + + + + + + + + + false + + + + 0 + 10 + + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + 0 + 10 + + + + + + + + + Pro Controller + + + + + Dual Joycons + + + + + Left Joycon + + + + + Right Joycon + + + + + + + + + Use Current Config + + + + + + + + + + + + 5 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 100 + 100 + + + + + 100 + 100 + + + + + + + true + + + false + + + + 7 + + + 14 + + + 7 + + + 14 + + + 4 + + + + + + + + + 16 + + + + + P1 + + + + + + + + + + false + + + + 0 + 10 + + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::LeftToRight + + + + + + + + + + + + + + + + + + + + + + + 0 + 10 + + + + + + + + + Pro Controller + + + + + Dual Joycons + + + + + Left Joycon + + + + + Right Joycon + + + + + Handheld + + + + + + + + + Use Current Config + + + + + + + + + + + + 25 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 25 + 20 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + + + + 5 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 100 + 100 + + + + + 100 + 100 + + + + + + + true + + + false + + + + 7 + + + 14 + + + 7 + + + 14 + + + 4 + + + + + + + + + 16 + + + + + P3 + + + + + + + + + + false + + + + 0 + 10 + + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + 0 + 10 + + + + + + + + false + + + + Pro Controller + + + + + Dual Joycons + + + + + Left Joycon + + + + + Right Joycon + + + + + + + + + Use Current Config + + + + + + + + + + + + 0 + 25 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + 20 + 25 + + + + + + + + + + + + 5 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 100 + 100 + + + + + 100 + 100 + + + + + + + true + + + false + + + + 7 + + + 14 + + + 7 + + + 14 + + + 4 + + + + + + + + + 16 + + + + + P7 + + + + + + + + + + false + + + + 0 + 10 + + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + 0 + 10 + + + + + + + + + Pro Controller + + + + + Dual Joycons + + + + + Left Joycon + + + + + Right Joycon + + + + + + + + + Use Current Config + + + + + + + + + + + + 5 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 100 + 100 + + + + + 100 + 100 + + + + + + + true + + + false + + + + 7 + + + 14 + + + 7 + + + 14 + + + 4 + + + + + + + + + 16 + + + + + P8 + + + + + + + + + + false + + + + 0 + 10 + + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + 0 + 10 + + + + + + + + + Pro Controller + + + + + Dual Joycons + + + + + Left Joycon + + + + + Right Joycon + + + + + + + + + Use Current Config + + + + + + + + + + + + 5 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 100 + 100 + + + + + 100 + 100 + + + + + + + true + + + false + + + + 7 + + + 14 + + + 7 + + + 14 + + + 4 + + + + + + + + + 16 + + + + + P5 + + + + + + + + + + false + + + + 0 + 10 + + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::LeftToRight + + + + + + + + + + + + + + + + + + + + + + + 0 + 10 + + + + + + + + + Pro Controller + + + + + Dual Joycons + + + + + Left Joycon + + + + + Right Joycon + + + + + + + + + Use Current Config + + + + + + + + + + + + 5 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 100 + 100 + + + + + 100 + 100 + + + + + + + true + + + false + + + + 7 + + + 14 + + + 7 + + + 14 + + + 4 + + + + + + + + + 16 + + + + + P6 + + + + + + + + + + false + + + + 0 + 10 + + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + 0 + 10 + + + + + + + + + Pro Controller + + + + + Dual Joycons + + + + + Left Joycon + + + + + Right Joycon + + + + + + + + + Use Current Config + + + + + + + + + + + + 0 + 25 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + 20 + 25 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + + + + 25 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 25 + 20 + + + + + + + + + + + + 0 + 25 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + 20 + 25 + + + + + + + + + + + + + + + + + 15 + + + 15 + + + 8 + + + 15 + + + 15 + + + + + + 16777215 + 16777215 + + + + Console Mode + + + + 6 + + + 6 + + + 6 + + + 3 + + + 6 + + + + + Docked + + + true + + + + + + + Undocked + + + + + + + + + + Vibration + + + true + + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 65 + 0 + + + + + 65 + 16777215 + + + + % + + + 1 + + + 200 + + + 100 + + + + + + + + + + Motion + + + true + + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 57 + 0 + + + + + 55 + 16777215 + + + + min-width: 55px; + + + Configure + + + + + + + + + + Input Config + + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 65 + 16777215 + + + + min-width: 55px; + + + Open + + + + + + + + + + + 5 + + + 0 + + + 0 + + + 0 + + + 3 + + + + + + + + + + + + Controllers + + + + + + + + + + + + + + 1 + + + Qt::AlignCenter + + + + + + + + + + + + + + Qt::LeftToRight + + + false + + + + + + + 2 + + + Qt::AlignCenter + + + + + + + 4 + + + Qt::AlignCenter + + + + + + + 3 + + + Qt::AlignCenter + + + + + + + Connected + + + + + + + + + + + + + + 5 + + + Qt::AlignCenter + + + + + + + + + + + + + + 7 + + + Qt::AlignCenter + + + + + + + + + + + + + + 6 + + + Qt::AlignCenter + + + + + + + 8 + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + false + + + QDialogButtonBox::Ok + + + + + + + + + + + + + + + buttonBox + accepted() + QtControllerSelectorDialog + accept() + + + 20 + 20 + + + 20 + 20 + + + + + diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index ae3e31762..3befcc739 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -70,7 +70,7 @@ ConfigureInput::ConfigureInput(QWidget* parent) ConfigureInput::~ConfigureInput() = default; -void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem) { +void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, std::size_t max_players) { player_controllers = { new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem), new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem), @@ -93,6 +93,11 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem) { ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected, }; + std::array player_connected_labels = { + ui->label, ui->label_3, ui->label_4, ui->label_5, + ui->label_6, ui->label_7, ui->label_8, ui->label_9, + }; + for (std::size_t i = 0; i < player_tabs.size(); ++i) { player_tabs[i]->setLayout(new QHBoxLayout(player_tabs[i])); player_tabs[i]->layout()->addWidget(player_controllers[i]); @@ -112,6 +117,13 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem) { connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) { player_controllers[i]->ConnectPlayer(state == Qt::Checked); }); + + // Remove/hide all the elements that exceed max_players, if applicable. + if (i >= max_players) { + ui->tabWidget->removeTab(static_cast(max_players)); + player_connected[i]->hide(); + player_connected_labels[i]->hide(); + } } // Only the first player can choose handheld mode so connect the signal just to player 1 connect(player_controllers[0], &ConfigureInputPlayer::HandheldStateChanged, @@ -175,8 +187,7 @@ void ConfigureInput::RetranslateUI() { void ConfigureInput::LoadConfiguration() { LoadPlayerControllerIndices(); - UpdateDockedState(Settings::values.players[0].controller_type == - Settings::ControllerType::Handheld); + UpdateDockedState(Settings::values.players[8].connected); ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); } @@ -208,14 +219,14 @@ void ConfigureInput::RestoreDefaults() { } void ConfigureInput::UpdateDockedState(bool is_handheld) { - // If the controller type is handheld only, disallow changing docked mode + // Disallow changing the console mode if the controller type is handheld. ui->radioDocked->setEnabled(!is_handheld); ui->radioUndocked->setEnabled(!is_handheld); ui->radioDocked->setChecked(Settings::values.use_docked_mode); ui->radioUndocked->setChecked(!Settings::values.use_docked_mode); - // If its handheld only, force docked mode off (since you can't play handheld in a dock) + // Also force into undocked mode if the controller type is handheld. if (is_handheld) { ui->radioUndocked->setChecked(true); } diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index d08a24f96..0e8b2fd4e 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h @@ -37,7 +37,7 @@ public: ~ConfigureInput() override; /// Initializes the input dialog with the given input subsystem. - void Initialize(InputCommon::InputSubsystem* input_subsystem_); + void Initialize(InputCommon::InputSubsystem* input_subsystem_, std::size_t max_players = 8); /// Save all button configurations to settings file. void ApplyConfiguration(); diff --git a/src/yuzu/configuration/configure_input_dialog.cpp b/src/yuzu/configuration/configure_input_dialog.cpp new file mode 100644 index 000000000..1866003c2 --- /dev/null +++ b/src/yuzu/configuration/configure_input_dialog.cpp @@ -0,0 +1,37 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "ui_configure_input_dialog.h" +#include "yuzu/configuration/configure_input_dialog.h" + +ConfigureInputDialog::ConfigureInputDialog(QWidget* parent, std::size_t max_players, + InputCommon::InputSubsystem* input_subsystem) + : QDialog(parent), ui(std::make_unique()), + input_widget(new ConfigureInput(this)) { + ui->setupUi(this); + + input_widget->Initialize(input_subsystem, max_players); + + ui->inputLayout->addWidget(input_widget); + + RetranslateUI(); +} + +ConfigureInputDialog::~ConfigureInputDialog() = default; + +void ConfigureInputDialog::ApplyConfiguration() { + input_widget->ApplyConfiguration(); +} + +void ConfigureInputDialog::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QDialog::changeEvent(event); +} + +void ConfigureInputDialog::RetranslateUI() { + ui->retranslateUi(this); +} diff --git a/src/yuzu/configuration/configure_input_dialog.h b/src/yuzu/configuration/configure_input_dialog.h new file mode 100644 index 000000000..d1bd865f9 --- /dev/null +++ b/src/yuzu/configuration/configure_input_dialog.h @@ -0,0 +1,38 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include "yuzu/configuration/configure_input.h" + +class QPushButton; + +namespace InputCommon { +class InputSubsystem; +} + +namespace Ui { +class ConfigureInputDialog; +} + +class ConfigureInputDialog : public QDialog { + Q_OBJECT + +public: + explicit ConfigureInputDialog(QWidget* parent, std::size_t max_players, + InputCommon::InputSubsystem* input_subsystem); + ~ConfigureInputDialog() override; + + void ApplyConfiguration(); + +private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + + std::unique_ptr ui; + + ConfigureInput* input_widget; +}; diff --git a/src/yuzu/configuration/configure_input_dialog.ui b/src/yuzu/configuration/configure_input_dialog.ui new file mode 100644 index 000000000..b92ddb200 --- /dev/null +++ b/src/yuzu/configuration/configure_input_dialog.ui @@ -0,0 +1,57 @@ + + + ConfigureInputDialog + + + + 0 + 0 + 70 + 540 + + + + Configure Input + + + + 2 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + + + + + QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + ConfigureInputDialog + accept() + + + diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index a1b61d119..2ac8344a3 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -11,6 +11,7 @@ #endif // VFS includes must be before glad as they will conflict with Windows file api, which uses defines. +#include "applets/controller.h" #include "applets/error.h" #include "applets/profile_select.h" #include "applets/software_keyboard.h" @@ -19,7 +20,9 @@ #include "configuration/configure_per_game.h" #include "core/file_sys/vfs.h" #include "core/file_sys/vfs_real.h" +#include "core/frontend/applets/controller.h" #include "core/frontend/applets/general_frontend.h" +#include "core/frontend/applets/software_keyboard.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_oe.h" @@ -84,7 +87,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "core/file_sys/romfs.h" #include "core/file_sys/savedata_factory.h" #include "core/file_sys/submission_package.h" -#include "core/frontend/applets/software_keyboard.h" #include "core/hle/kernel/process.h" #include "core/hle/service/am/am.h" #include "core/hle/service/filesystem/filesystem.h" @@ -283,6 +285,19 @@ GMainWindow::~GMainWindow() { delete render_window; } +void GMainWindow::ControllerSelectorReconfigureControllers( + const Core::Frontend::ControllerParameters& parameters) { + QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get()); + dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | + Qt::WindowSystemMenuHint); + dialog.setWindowModality(Qt::WindowModal); + dialog.exec(); + + emit ControllerSelectorReconfigureFinished(); + + UpdateStatusButtons(); +} + void GMainWindow::ProfileSelectorSelectProfile() { const Service::Account::ProfileManager manager; int index = 0; @@ -291,10 +306,12 @@ void GMainWindow::ProfileSelectorSelectProfile() { dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); + if (dialog.exec() == QDialog::Rejected) { emit ProfileSelectorFinishedSelection(std::nullopt); return; } + index = dialog.GetIndex(); } @@ -966,13 +983,14 @@ bool GMainWindow::LoadROM(const QString& filename) { system.SetFilesystem(vfs); system.SetAppletFrontendSet({ - nullptr, // Parental Controls - std::make_unique(*this), // - nullptr, // Photo Viewer - std::make_unique(*this), // - std::make_unique(*this), // - std::make_unique(*this), // - nullptr, // E-Commerce + std::make_unique(*this), // Controller Selector + nullptr, // E-Commerce + std::make_unique(*this), // Error Display + nullptr, // Parental Controls + nullptr, // Photo Viewer + std::make_unique(*this), // Profile Selector + std::make_unique(*this), // Software Keyboard + std::make_unique(*this), // Web Browser }); system.RegisterHostThread(); @@ -2047,6 +2065,7 @@ void GMainWindow::OnStartGame() { emu_thread->SetRunning(true); + qRegisterMetaType("Core::Frontend::ControllerParameters"); qRegisterMetaType( "Core::Frontend::SoftwareKeyboardParameters"); qRegisterMetaType("Core::System::ResultStatus"); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 0ce66a1ca..afcfa68a9 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -37,6 +37,7 @@ enum class InstalledEntryType; class GameListPlaceholder; namespace Core::Frontend { +struct ControllerParameters; struct SoftwareKeyboardParameters; } // namespace Core::Frontend @@ -116,9 +117,12 @@ signals: void UpdateInstallProgress(); + void ControllerSelectorReconfigureFinished(); + void ErrorDisplayFinished(); void ProfileSelectorFinishedSelection(std::optional uuid); + void SoftwareKeyboardFinishedText(std::optional text); void SoftwareKeyboardFinishedCheckDialog(); @@ -127,6 +131,8 @@ signals: public slots: void OnLoadComplete(); + void ControllerSelectorReconfigureControllers( + const Core::Frontend::ControllerParameters& parameters); void ErrorDisplayDisplayError(QString body); void ProfileSelectorSelectProfile(); void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); -- cgit v1.2.3 From 5ce3015945e327751a053f7a5a1331a33f07819e Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 27 Aug 2020 01:21:48 -0400 Subject: applets/controller: Implement "Explain Text" "Explain Text" is additional text that is shown for each player in the controller applet. --- src/core/frontend/applets/controller.h | 3 + src/core/hle/service/am/applets/controller.cpp | 37 ++-- src/core/hle/service/am/applets/controller.h | 5 +- src/yuzu/applets/controller.cpp | 20 ++ src/yuzu/applets/controller.h | 6 + src/yuzu/applets/controller.ui | 258 ++++++++++++++++++++++++- 6 files changed, 304 insertions(+), 25 deletions(-) diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h index 0908f2b69..a227f15cd 100644 --- a/src/core/frontend/applets/controller.h +++ b/src/core/frontend/applets/controller.h @@ -11,6 +11,7 @@ namespace Core::Frontend { using BorderColor = std::array; +using ExplainText = std::array; struct ControllerParameters { s8 min_players{}; @@ -19,6 +20,8 @@ struct ControllerParameters { bool enable_single_mode{}; bool enable_border_color{}; std::vector border_colors{}; + bool enable_explain_text{}; + std::vector explain_text{}; bool allow_pro_controller{}; bool allow_handheld{}; bool allow_dual_joycons{}; diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index 2a45a388f..63c85256d 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp @@ -19,8 +19,8 @@ namespace Service::AM::Applets { [[maybe_unused]] constexpr ResultCode ERR_CONTROLLER_APPLET_3102{ErrorModule::HID, 3102}; static Core::Frontend::ControllerParameters ConvertToFrontendParameters( - ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, - std::vector identification_colors) { + ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, + std::vector identification_colors, std::vector text) { HID::Controller_NPad::NPadType npad_style_set; npad_style_set.raw = private_arg.style_set; @@ -31,6 +31,8 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters( .enable_single_mode = header.enable_single_mode, .enable_border_color = header.enable_identification_color, .border_colors = identification_colors, + .enable_explain_text = enable_text, + .explain_text = text, .allow_pro_controller = npad_style_set.pro_controller == 1, .allow_handheld = npad_style_set.handheld == 1, .allow_dual_joycons = npad_style_set.joycon_dual == 1, @@ -126,31 +128,38 @@ void Controller::Execute() { case LibraryAppletVersion::Version5: return ConvertToFrontendParameters( controller_private_arg, controller_user_arg_old.header, + controller_user_arg_old.enable_explain_text, std::vector( controller_user_arg_old.identification_colors.begin(), - controller_user_arg_old.identification_colors.end())); + controller_user_arg_old.identification_colors.end()), + std::vector(controller_user_arg_old.explain_text.begin(), + controller_user_arg_old.explain_text.end())); case LibraryAppletVersion::Version7: default: return ConvertToFrontendParameters( controller_private_arg, controller_user_arg_new.header, + controller_user_arg_new.enable_explain_text, std::vector( controller_user_arg_new.identification_colors.begin(), - controller_user_arg_new.identification_colors.end())); + controller_user_arg_new.identification_colors.end()), + std::vector(controller_user_arg_new.explain_text.begin(), + controller_user_arg_new.explain_text.end())); } }(); is_single_mode = parameters.enable_single_mode; - LOG_DEBUG( - Service_HID, - "Controller Parameters: min_players={}, max_players={}, keep_controllers_connected={}, " - "enable_single_mode={}, enable_border_color={}, allow_pro_controller={}, " - "allow_handheld={}, allow_dual_joycons={}, allow_left_joycon={}, allow_right_joycon={}", - parameters.min_players, parameters.max_players, parameters.keep_controllers_connected, - parameters.enable_single_mode, parameters.enable_border_color, - parameters.allow_pro_controller, parameters.allow_handheld, - parameters.allow_dual_joycons, parameters.allow_left_joycon, - parameters.allow_right_joycon); + LOG_DEBUG(Service_HID, + "Controller Parameters: min_players={}, max_players={}, " + "keep_controllers_connected={}, enable_single_mode={}, enable_border_color={}, " + "enable_explain_text={}, allow_pro_controller={}, allow_handheld={}, " + "allow_dual_joycons={}, allow_left_joycon={}, allow_right_joycon={}", + parameters.min_players, parameters.max_players, + parameters.keep_controllers_connected, parameters.enable_single_mode, + parameters.enable_border_color, parameters.enable_explain_text, + parameters.allow_pro_controller, parameters.allow_handheld, + parameters.allow_dual_joycons, parameters.allow_left_joycon, + parameters.allow_right_joycon); frontend.ReconfigureControllers([this] { ConfigurationComplete(); }, parameters); break; diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h index 90a78d508..31ba2af4f 100644 --- a/src/core/hle/service/am/applets/controller.h +++ b/src/core/hle/service/am/applets/controller.h @@ -16,6 +16,7 @@ class System; namespace Service::AM::Applets { using IdentificationColor = std::array; +using ExplainText = std::array; enum class LibraryAppletVersion : u32_le { Version3 = 0x3, // 1.0.0 - 2.3.0 @@ -65,7 +66,7 @@ struct ControllerSupportArgOld { ControllerSupportArgHeader header{}; std::array identification_colors{}; bool enable_explain_text{}; - std::array, 4> explain_text{}; + std::array explain_text{}; }; static_assert(sizeof(ControllerSupportArgOld) == 0x21C, "ControllerSupportArgOld has incorrect size."); @@ -75,7 +76,7 @@ struct ControllerSupportArgNew { ControllerSupportArgHeader header{}; std::array identification_colors{}; bool enable_explain_text{}; - std::array, 8> explain_text{}; + std::array explain_text{}; }; static_assert(sizeof(ControllerSupportArgNew) == 0x430, "ControllerSupportArgNew has incorrect size."); diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index 8ccf61be0..7482174c6 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp @@ -4,6 +4,7 @@ #include +#include "common/string_util.h" #include "core/core.h" #include "core/hle/lock.h" #include "core/hle/service/hid/controllers/npad.h" @@ -45,6 +46,7 @@ void UpdateController(Settings::ControllerType controller_type, std::size_t npad npad.UpdateControllerAt(npad.MapSettingsTypeToNPad(controller_type), npad_index, connected); } +// Returns true if the given controller type is compatible with the given parameters. bool IsControllerCompatible(Settings::ControllerType controller_type, Core::Frontend::ControllerParameters parameters) { switch (controller_type) { @@ -140,6 +142,12 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( ui->checkboxPlayer8LED4}, }}; + explain_text_labels = { + ui->labelPlayer1Explain, ui->labelPlayer2Explain, ui->labelPlayer3Explain, + ui->labelPlayer4Explain, ui->labelPlayer5Explain, ui->labelPlayer6Explain, + ui->labelPlayer7Explain, ui->labelPlayer8Explain, + }; + emulated_controllers = { ui->comboPlayer1Emulated, ui->comboPlayer2Emulated, ui->comboPlayer3Emulated, ui->comboPlayer4Emulated, ui->comboPlayer5Emulated, ui->comboPlayer6Emulated, @@ -200,6 +208,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( Settings::ControllerType::Handheld); }); } + + SetExplainText(i); } connect(ui->inputConfigButton, &QPushButton::clicked, this, @@ -468,6 +478,16 @@ void QtControllerSelectorDialog::UpdateBorderColor(std::size_t player_index) { .arg(parameters.border_colors[player_index][3]))); } +void QtControllerSelectorDialog::SetExplainText(std::size_t player_index) { + if (!parameters.enable_explain_text || player_index >= parameters.max_players) { + return; + } + + explain_text_labels[player_index]->setText(QString::fromStdString( + Common::StringFromFixedZeroTerminatedBuffer(parameters.explain_text[player_index].data(), + parameters.explain_text[player_index].size()))); +} + void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) { // Disallow changing the console mode if the controller type is handheld. ui->radioDocked->setEnabled(!is_handheld); diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h index 1ec290e6c..db59dd631 100644 --- a/src/yuzu/applets/controller.h +++ b/src/yuzu/applets/controller.h @@ -59,6 +59,9 @@ private: // Updates the border color per player. void UpdateBorderColor(std::size_t player_index); + // Sets the "Explain Text" per player. + void SetExplainText(std::size_t player_index); + // Updates the console mode. void UpdateDockedState(bool is_handheld); @@ -94,6 +97,9 @@ private: // LED patterns for currently connected controllers/players. std::array, 8> led_patterns_boxes; + // Labels representing additional information known as "Explain Text" per player. + std::array explain_text_labels; + // Comboboxes with a list of emulated controllers per player. std::array emulated_controllers; diff --git a/src/yuzu/applets/controller.ui b/src/yuzu/applets/controller.ui index d7db46613..c4108a979 100644 --- a/src/yuzu/applets/controller.ui +++ b/src/yuzu/applets/controller.ui @@ -468,13 +468,43 @@ - + 0 10 + + + 150 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + + @@ -635,13 +665,43 @@ - + 0 10 + + + 150 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + + @@ -806,13 +866,43 @@ - + 0 10 + + + 150 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + + @@ -1086,13 +1176,43 @@ - + 0 10 + + + 150 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + + @@ -1296,13 +1416,43 @@ - + 0 10 + + + 150 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + + @@ -1463,13 +1613,43 @@ - + 0 10 + + + 150 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + + @@ -1634,13 +1814,43 @@ - + 0 10 + + + 150 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + + @@ -1801,13 +2011,43 @@ - + 0 10 + + + 150 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + + @@ -2395,7 +2635,7 @@ - false + true QDialogButtonBox::Ok -- cgit v1.2.3 From aeec0f8a38cbe247bbe619a69842700208ee2d79 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 27 Aug 2020 01:46:14 -0400 Subject: applets/controller: Make 8 a static constexpr value of NUM_PLAYERS Avoids repetitive usages of the int literal '8' or calls to player_widgets.size() --- src/yuzu/applets/controller.cpp | 15 ++++++++++----- src/yuzu/applets/controller.h | 22 ++++++++++++---------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index 7482174c6..4783446a8 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp @@ -171,14 +171,14 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected, }; - for (std::size_t i = 0; i < player_widgets.size(); ++i) { + for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) { if (checked) { for (std::size_t index = 0; index <= i; ++index) { connected_controller_checkboxes[index]->setChecked(checked); } } else { - for (std::size_t index = i; index < player_widgets.size(); ++index) { + for (std::size_t index = i; index < NUM_PLAYERS; ++index) { connected_controller_checkboxes[index]->setChecked(checked); } } @@ -237,6 +237,11 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( QtControllerSelectorDialog::~QtControllerSelectorDialog() = default; void QtControllerSelectorDialog::ApplyConfiguration() { + // Update the controller state once more, just to be sure they are properly applied. + for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { + UpdateControllerState(index); + } + const bool pre_docked_mode = Settings::values.use_docked_mode; Settings::values.use_docked_mode = ui->radioDocked->isChecked(); OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); @@ -281,7 +286,7 @@ void QtControllerSelectorDialog::CheckIfParametersMet() { // Next, check against all connected controllers. const auto all_controllers_compatible = [this] { - for (std::size_t index = 0; index < player_widgets.size(); ++index) { + for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { // Skip controllers that are not used, we only care about the currently connected ones. if (!player_groupboxes[index]->isChecked() || !player_groupboxes[index]->isEnabled()) { continue; @@ -535,7 +540,7 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() { break; } - for (std::size_t index = max_supported_players; index < player_widgets.size(); ++index) { + for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) { // Disconnect any unsupported players here and disable or hide them if applicable. Settings::values.players[index].connected = false; UpdateController(Settings::values.players[index].controller_type, index, false); @@ -553,7 +558,7 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() { } void QtControllerSelectorDialog::LoadConfiguration() { - for (std::size_t index = 0; index < player_widgets.size(); ++index) { + for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { const auto connected = Settings::values.players[index].connected || (index == 0 && Settings::values.players[8].connected); player_groupboxes[index]->setChecked(connected); diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h index db59dd631..6ab4bea09 100644 --- a/src/yuzu/applets/controller.h +++ b/src/yuzu/applets/controller.h @@ -79,36 +79,38 @@ private: InputCommon::InputSubsystem* input_subsystem; // This is true if and only if all parameters are met. Otherwise, this is false. - // This determines whether the "Ok" button can be clicked to exit the applet. + // This determines whether the "OK" button can be clicked to exit the applet. bool parameters_met{false}; + static constexpr std::size_t NUM_PLAYERS = 8; + // Widgets encapsulating the groupboxes and comboboxes per player. - std::array player_widgets; + std::array player_widgets; // Groupboxes encapsulating the controller icons and LED patterns per player. - std::array player_groupboxes; + std::array player_groupboxes; // Icons for currently connected controllers/players. - std::array connected_controller_icons; + std::array connected_controller_icons; // Labels that represent the player numbers in place of the controller icons. - std::array player_labels; + std::array player_labels; // LED patterns for currently connected controllers/players. - std::array, 8> led_patterns_boxes; + std::array, NUM_PLAYERS> led_patterns_boxes; // Labels representing additional information known as "Explain Text" per player. - std::array explain_text_labels; + std::array explain_text_labels; // Comboboxes with a list of emulated controllers per player. - std::array emulated_controllers; + std::array emulated_controllers; // Labels representing the number of connected controllers // above the "Connected Controllers" checkboxes. - std::array connected_controller_labels; + std::array connected_controller_labels; // Checkboxes representing the "Connected Controllers". - std::array connected_controller_checkboxes; + std::array connected_controller_checkboxes; }; class QtControllerSelector final : public QObject, public Core::Frontend::ControllerApplet { -- cgit v1.2.3 From 72b2f5d34f2f24bdcb252d2158d43aa7f827e60b Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 27 Aug 2020 03:52:26 -0400 Subject: applets/controller: Load configuration prior to setting up connections This avoids unintentionally changing the states of elements while loading them in. --- src/yuzu/applets/controller.cpp | 46 +++++++++++++++++++++++------------------ src/yuzu/applets/controller.h | 6 +++--- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index 4783446a8..4920d2df6 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp @@ -171,7 +171,18 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected, }; + // Setup/load everything prior to setting up connections. + // This avoids unintentionally changing the states of elements while loading them in. + SetSupportedControllers(); + DisableUnsupportedPlayers(); + LoadConfiguration(); + for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { + SetExplainText(i); + UpdateControllerIcon(i); + UpdateLEDPattern(i); + UpdateBorderColor(i); + connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) { if (checked) { for (std::size_t index = 0; index <= i; ++index) { @@ -208,8 +219,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( Settings::ControllerType::Handheld); }); } - - SetExplainText(i); } connect(ui->inputConfigButton, &QPushButton::clicked, this, @@ -218,10 +227,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QtControllerSelectorDialog::ApplyConfiguration); - SetSupportedControllers(); - DisableUnsupportedPlayers(); - LoadConfiguration(); - // If keep_controllers_connected is false, forcefully disconnect all controllers if (!parameters.keep_controllers_connected) { for (auto player : player_groupboxes) { @@ -249,6 +254,21 @@ void QtControllerSelectorDialog::ApplyConfiguration() { Settings::values.vibration_enabled = ui->vibrationGroup->isChecked(); } +void QtControllerSelectorDialog::LoadConfiguration() { + for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { + const auto connected = Settings::values.players[index].connected || + (index == 0 && Settings::values.players[8].connected); + player_groupboxes[index]->setChecked(connected); + connected_controller_checkboxes[index]->setChecked(connected); + emulated_controllers[index]->setCurrentIndex( + GetIndexFromControllerType(Settings::values.players[index].controller_type)); + } + + UpdateDockedState(Settings::values.players[8].connected); + + ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); +} + void QtControllerSelectorDialog::CallConfigureInputDialog() { const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; @@ -557,20 +577,6 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() { } } -void QtControllerSelectorDialog::LoadConfiguration() { - for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { - const auto connected = Settings::values.players[index].connected || - (index == 0 && Settings::values.players[8].connected); - player_groupboxes[index]->setChecked(connected); - emulated_controllers[index]->setCurrentIndex( - GetIndexFromControllerType(Settings::values.players[index].controller_type)); - } - - UpdateDockedState(Settings::values.players[8].connected); - - ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); -} - QtControllerSelector::QtControllerSelector(GMainWindow& parent) { connect(this, &QtControllerSelector::MainWindowReconfigureControllers, &parent, &GMainWindow::ControllerSelectorReconfigureControllers, Qt::QueuedConnection); diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h index 6ab4bea09..2d6d588c6 100644 --- a/src/yuzu/applets/controller.h +++ b/src/yuzu/applets/controller.h @@ -37,6 +37,9 @@ private: // Applies the current configuration. void ApplyConfiguration(); + // Loads the current input configuration into the frontend applet. + void LoadConfiguration(); + // Initializes the "Configure Input" Dialog. void CallConfigureInputDialog(); @@ -68,9 +71,6 @@ private: // Disables and disconnects unsupported players based on the given parameters. void DisableUnsupportedPlayers(); - // Loads the current input configuration into the frontend applet. - void LoadConfiguration(); - std::unique_ptr ui; // Parameters sent in from the backend HLE applet. -- cgit v1.2.3 From 7299356f370a0981abed519e42343bb84cccb9c1 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 27 Aug 2020 05:33:46 -0400 Subject: applets/controller: Implement fallback applet for the SDL frontend Implement the fallback applet for the SDL frontend, connecting only the minimum amount of players required. --- src/core/frontend/applets/controller.cpp | 35 ++++++++++- src/core/hle/service/hid/controllers/npad.cpp | 88 --------------------------- src/core/hle/service/hid/controllers/npad.h | 1 - 3 files changed, 34 insertions(+), 90 deletions(-) diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 0fbc7932c..34eacbb45 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp @@ -27,11 +27,44 @@ void DefaultControllerApplet::ReconfigureControllers(std::function callb auto& players = Settings::values.players; + const auto min_supported_players = parameters.enable_single_mode ? 1 : parameters.min_players; + + // Disconnect Handheld first. + npad.DisconnectNPadAtIndex(8); + // Deduce the best configuration based on the input parameters. - for (std::size_t index = 0; index < players.size(); ++index) { + for (std::size_t index = 0; index < players.size() - 2; ++index) { // First, disconnect all controllers regardless of the value of keep_controllers_connected. // This makes it easy to connect the desired controllers. npad.DisconnectNPadAtIndex(index); + + // Only connect the minimum number of required players. + if (index >= min_supported_players) { + continue; + } + + // Connect controllers based on the following priority list from highest to lowest priority: + // Pro Controller -> Dual Joycons -> Left Joycon -> Right Joycon -> Handheld + if (parameters.allow_pro_controller) { + npad.AddNewControllerAt( + npad.MapSettingsTypeToNPad(Settings::ControllerType::ProController), index); + } else if (parameters.allow_dual_joycons) { + npad.AddNewControllerAt( + npad.MapSettingsTypeToNPad(Settings::ControllerType::DualJoyconDetached), index); + } else if (parameters.allow_left_joycon) { + npad.AddNewControllerAt( + npad.MapSettingsTypeToNPad(Settings::ControllerType::LeftJoycon), index); + } else if (parameters.allow_right_joycon) { + npad.AddNewControllerAt( + npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); + } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && + !Settings::values.use_docked_mode) { + // We should *never* reach here under any normal circumstances. + npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld), + index); + } else { + UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!"); + } } callback(); diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index efb953d93..a92018914 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -720,92 +720,4 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const return false; } -Controller_NPad::NPadControllerType Controller_NPad::DecideBestController( - NPadControllerType priority) const { - if (IsControllerSupported(priority)) { - return priority; - } - const auto is_docked = Settings::values.use_docked_mode; - if (is_docked && priority == NPadControllerType::Handheld) { - priority = NPadControllerType::JoyDual; - if (IsControllerSupported(priority)) { - return priority; - } - } - std::vector priority_list; - switch (priority) { - case NPadControllerType::ProController: - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::Handheld: - priority_list.push_back(NPadControllerType::JoyDual); - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::JoyDual: - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::JoyLeft: - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::JoyRight: - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::Pokeball: - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - break; - default: - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::JoyDual); - break; - } - - const auto iter = std::find_if(priority_list.begin(), priority_list.end(), - [this](auto type) { return IsControllerSupported(type); }); - if (iter == priority_list.end()) { - UNIMPLEMENTED_MSG("Could not find supported controller!"); - return priority; - } - - return *iter; -} - } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 40c763376..0f2d33857 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -318,7 +318,6 @@ private: void InitNewlyAddedController(std::size_t controller_idx); bool IsControllerSupported(NPadControllerType controller) const; - NPadControllerType DecideBestController(NPadControllerType priority) const; void RequestPadStateUpdate(u32 npad_id); u32 press_state{}; -- cgit v1.2.3 From 6597b3817cd1e03577185aea7eb88856e046dc4d Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 27 Aug 2020 11:58:28 -0400 Subject: main: Apply settings after applet configuration is complete. --- src/yuzu/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 2ac8344a3..68ad43a80 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -295,6 +295,10 @@ void GMainWindow::ControllerSelectorReconfigureControllers( emit ControllerSelectorReconfigureFinished(); + // Don't forget to apply settings. + Settings::Apply(); + config->Save(); + UpdateStatusButtons(); } -- cgit v1.2.3 From 371226448a93d0553ded77750eaccbffa4a799e4 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Thu, 27 Aug 2020 23:38:26 -0400 Subject: applets/controller: Modify heuristic to account for certain games Now left and right joycons have the same priority (meaning both needs to be supported by the game). Explanation of the new heuristic: Assign left joycons to even player indices and right joycons to odd player indices. We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and a right Joycon for Player 2 in 2 Player Assist mode. --- src/core/frontend/applets/controller.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 34eacbb45..715d9fffd 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp @@ -44,19 +44,24 @@ void DefaultControllerApplet::ReconfigureControllers(std::function callb } // Connect controllers based on the following priority list from highest to lowest priority: - // Pro Controller -> Dual Joycons -> Left Joycon -> Right Joycon -> Handheld + // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld if (parameters.allow_pro_controller) { npad.AddNewControllerAt( npad.MapSettingsTypeToNPad(Settings::ControllerType::ProController), index); } else if (parameters.allow_dual_joycons) { npad.AddNewControllerAt( npad.MapSettingsTypeToNPad(Settings::ControllerType::DualJoyconDetached), index); - } else if (parameters.allow_left_joycon) { - npad.AddNewControllerAt( - npad.MapSettingsTypeToNPad(Settings::ControllerType::LeftJoycon), index); - } else if (parameters.allow_right_joycon) { - npad.AddNewControllerAt( - npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); + } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) { + // Assign left joycons to even player indices and right joycons to odd player indices. + // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and + // a right Joycon for Player 2 in 2 Player Assist mode. + if (index % 2 == 0) { + npad.AddNewControllerAt( + npad.MapSettingsTypeToNPad(Settings::ControllerType::LeftJoycon), index); + } else { + npad.AddNewControllerAt( + npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); + } } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && !Settings::values.use_docked_mode) { // We should *never* reach here under any normal circumstances. -- cgit v1.2.3 From f95ea04995cf6ad8ea212078078780eb3ecfd460 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Fri, 28 Aug 2020 09:02:50 -0400 Subject: applets/controller: Set min_players to have a minimum value of 1. - Some games like Shipped have a minimum requirement of 0 connected players and is undesired behavior. We must require a minimum of 1 player connected regardless of what games may ask. --- src/core/hle/service/am/applets/controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index 63c85256d..6edb35704 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp @@ -25,7 +25,7 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters( npad_style_set.raw = private_arg.style_set; return { - .min_players = header.player_count_min, + .min_players = std::max(s8(1), header.player_count_min), .max_players = header.player_count_max, .keep_controllers_connected = header.enable_take_over_connection, .enable_single_mode = header.enable_single_mode, -- cgit v1.2.3 From 1ec71b6ea05b1a2ce5f1f6de4b4a979db7218aab Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Fri, 28 Aug 2020 11:44:36 -0400 Subject: clang-format --- src/yuzu/applets/controller.cpp | 3 ++- src/yuzu/configuration/configure_input.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index 4920d2df6..f2690b8dc 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp @@ -102,7 +102,8 @@ constexpr int GetIndexFromControllerType(Settings::ControllerType type) { } // namespace QtControllerSelectorDialog::QtControllerSelectorDialog( - QWidget* parent, Core::Frontend::ControllerParameters parameters_, InputCommon::InputSubsystem* input_subsystem_) + QWidget* parent, Core::Frontend::ControllerParameters parameters_, + InputCommon::InputSubsystem* input_subsystem_) : QDialog(parent), ui(std::make_unique()), parameters(std::move(parameters_)), input_subsystem(input_subsystem_) { ui->setupUi(this); diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 3befcc739..7ea17a4db 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -70,7 +70,8 @@ ConfigureInput::ConfigureInput(QWidget* parent) ConfigureInput::~ConfigureInput() = default; -void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, std::size_t max_players) { +void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, + std::size_t max_players) { player_controllers = { new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem), new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem), -- cgit v1.2.3 From 076e4d44c3dbfef173e7fdc189144a554dcfe483 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Fri, 28 Aug 2020 12:45:15 -0400 Subject: Address feedback --- src/core/frontend/applets/controller.cpp | 2 ++ src/core/hle/service/am/applets/controller.cpp | 4 ++++ src/core/hle/service/am/applets/controller.h | 3 +++ src/yuzu/applets/controller.cpp | 5 +++-- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 715d9fffd..31a5cb2cc 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/assert.h" +#include "common/logging/log.h" #include "core/core.h" #include "core/frontend/applets/controller.h" #include "core/hle/service/hid/controllers/npad.h" diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index 6edb35704..2151da783 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp @@ -3,10 +3,14 @@ // Refer to the license.txt file included. #include +#include +#include "common/assert.h" +#include "common/logging/log.h" #include "common/string_util.h" #include "core/core.h" #include "core/frontend/applets/controller.h" +#include "core/hle/result.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/controller.h" #include "core/hle/service/hid/controllers/npad.h" diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h index 31ba2af4f..f7bb3fba9 100644 --- a/src/core/hle/service/am/applets/controller.h +++ b/src/core/hle/service/am/applets/controller.h @@ -5,7 +5,10 @@ #pragma once #include +#include +#include "common/common_funcs.h" +#include "common/common_types.h" #include "core/hle/result.h" #include "core/hle/service/am/applets/applets.h" diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index f2690b8dc..c960eb3dd 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp @@ -4,6 +4,7 @@ #include +#include "common/assert.h" #include "common/string_util.h" #include "core/core.h" #include "core/hle/lock.h" @@ -15,6 +16,8 @@ #include "yuzu/configuration/configure_input_dialog.h" #include "yuzu/main.h" +namespace { + constexpr std::array, 8> led_patterns = {{ {1, 0, 0, 0}, {1, 1, 0, 0}, @@ -26,8 +29,6 @@ constexpr std::array, 8> led_patterns = {{ {0, 1, 1, 0}, }}; -namespace { - void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, bool connected) { Core::System& system{Core::System::GetInstance()}; -- cgit v1.2.3 From b65456b958f64dee6215962b11430f57f89dd5a8 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Fri, 28 Aug 2020 13:14:19 -0400 Subject: applets/controller: Resolve several compiler warnings Resolves -Wsign-compare and -Wunused-variable --- src/core/frontend/applets/controller.cpp | 3 ++- src/yuzu/applets/controller.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 31a5cb2cc..4505da758 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp @@ -29,7 +29,8 @@ void DefaultControllerApplet::ReconfigureControllers(std::function callb auto& players = Settings::values.players; - const auto min_supported_players = parameters.enable_single_mode ? 1 : parameters.min_players; + const std::size_t min_supported_players = + parameters.enable_single_mode ? 1 : parameters.min_players; // Disconnect Handheld first. npad.DisconnectNPadAtIndex(8); diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index c960eb3dd..9d45f2a01 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp @@ -289,11 +289,9 @@ void QtControllerSelectorDialog::CallConfigureInputDialog() { void QtControllerSelectorDialog::CheckIfParametersMet() { // Here, we check and validate the current configuration against all applicable parameters. - const auto& players = Settings::values.players; - - const auto num_connected_players = + const auto num_connected_players = static_cast( std::count_if(player_groupboxes.begin(), player_groupboxes.end(), - [this](const QGroupBox* player) { return player->isChecked(); }); + [this](const QGroupBox* player) { return player->isChecked(); })); const auto min_supported_players = parameters.enable_single_mode ? 1 : parameters.min_players; const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; @@ -489,7 +487,8 @@ void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { } void QtControllerSelectorDialog::UpdateBorderColor(std::size_t player_index) { - if (!parameters.enable_border_color || player_index >= parameters.max_players || + if (!parameters.enable_border_color || + player_index >= static_cast(parameters.max_players) || player_groupboxes[player_index]->styleSheet().contains(QStringLiteral("QGroupBox"))) { return; } @@ -506,7 +505,8 @@ void QtControllerSelectorDialog::UpdateBorderColor(std::size_t player_index) { } void QtControllerSelectorDialog::SetExplainText(std::size_t player_index) { - if (!parameters.enable_explain_text || player_index >= parameters.max_players) { + if (!parameters.enable_explain_text || + player_index >= static_cast(parameters.max_players)) { return; } -- cgit v1.2.3 From 5043036688126eeaa71752cfc5885fba7626fe20 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Mon, 31 Aug 2020 00:27:19 -0400 Subject: Resolve spacing inconsistencies in style.qrc/qss files --- dist/icons/controller/controller.qrc | 20 ++--- dist/qt_themes/default/style.qss | 84 ++++++++++----------- dist/qt_themes/qdarkstyle/style.qrc | 2 +- dist/qt_themes/qdarkstyle/style.qss | 90 +++++++++++------------ dist/qt_themes/qdarkstyle_midnight_blue/style.qrc | 2 +- dist/qt_themes/qdarkstyle_midnight_blue/style.qss | 20 ++--- 6 files changed, 109 insertions(+), 109 deletions(-) diff --git a/dist/icons/controller/controller.qrc b/dist/icons/controller/controller.qrc index 76083a9ac..1c4e960c0 100644 --- a/dist/icons/controller/controller.qrc +++ b/dist/icons/controller/controller.qrc @@ -21,34 +21,34 @@ single_joycon_right_vertical.png single_joycon_right_vertical_dark.png single_joycon_right_vertical_midnight.png - applet_dual_joycon.png + applet_dual_joycon.png applet_dual_joycon_dark.png applet_dual_joycon_midnight.png - applet_handheld.png + applet_handheld.png applet_handheld_dark.png applet_handheld_midnight.png applet_pro_controller.png - applet_pro_controller_dark.png - applet_pro_controller_midnight.png + applet_pro_controller_dark.png + applet_pro_controller_midnight.png applet_single_joycon_left.png - applet_single_joycon_left_dark.png - applet_single_joycon_left_midnight.png + applet_single_joycon_left_dark.png + applet_single_joycon_left_midnight.png applet_single_joycon_right.png applet_single_joycon_right_dark.png applet_single_joycon_right_midnight.png applet_dual_joycon_disabled.png applet_dual_joycon_dark_disabled.png applet_dual_joycon_midnight_disabled.png - applet_handheld_disabled.png + applet_handheld_disabled.png applet_handheld_dark_disabled.png applet_handheld_midnight_disabled.png - applet_pro_controller_disabled.png + applet_pro_controller_disabled.png applet_pro_controller_dark_disabled.png applet_pro_controller_midnight_disabled.png - applet_single_joycon_left_disabled.png + applet_single_joycon_left_disabled.png applet_single_joycon_left_dark_disabled.png applet_single_joycon_left_midnight_disabled.png - applet_single_joycon_right_disabled.png + applet_single_joycon_right_disabled.png applet_single_joycon_right_dark_disabled.png applet_single_joycon_right_midnight_disabled.png diff --git a/dist/qt_themes/default/style.qss b/dist/qt_themes/default/style.qss index 5b05b436b..b6dd2063d 100644 --- a/dist/qt_themes/default/style.qss +++ b/dist/qt_themes/default/style.qss @@ -52,30 +52,30 @@ QGroupBox#groupPlayer5Connected:checked, QGroupBox#groupPlayer6Connected:checked, QGroupBox#groupPlayer7Connected:checked, QGroupBox#groupPlayer8Connected:checked { - background-color: #f5f5f5; + background-color: #f5f5f5; } QWidget#topControllerApplet { - border-bottom: 1px solid #828790 + border-bottom: 1px solid #828790 } QWidget#bottomPerGameInput, QWidget#bottomControllerApplet { - border-top: 1px solid #828790 + border-top: 1px solid #828790 } QWidget#topPerGameInput, QWidget#middleControllerApplet { - background-color: #fff; + background-color: #fff; } QWidget#topPerGameInput QComboBox, QWidget#middleControllerApplet QComboBox { - width: 123px; + width: 123px; } QWidget#connectedControllers { - background: transparent; + background: transparent; } QWidget#playersSupported, @@ -86,8 +86,8 @@ QWidget#controllerSupported3, QWidget#controllerSupported4, QWidget#controllerSupported5, QWidget#controllerSupported6 { - border: none; - background: transparent; + border: none; + background: transparent; } QGroupBox#groupPlayer1Connected, @@ -98,11 +98,11 @@ QGroupBox#groupPlayer5Connected, QGroupBox#groupPlayer6Connected, QGroupBox#groupPlayer7Connected, QGroupBox#groupPlayer8Connected { - border: 1px solid #828790; - border-radius: 3px; - padding: 0px; - min-height: 98px; - max-height: 98px; + border: 1px solid #828790; + border-radius: 3px; + padding: 0px; + min-height: 98px; + max-height: 98px; } QGroupBox#groupPlayer1Connected:unchecked, @@ -113,7 +113,7 @@ QGroupBox#groupPlayer5Connected:unchecked, QGroupBox#groupPlayer6Connected:unchecked, QGroupBox#groupPlayer7Connected:unchecked, QGroupBox#groupPlayer8Connected:unchecked { - border: 1px solid #d9d9d9; + border: 1px solid #d9d9d9; } QGroupBox#groupPlayer1Connected::title, @@ -124,14 +124,14 @@ QGroupBox#groupPlayer5Connected::title, QGroupBox#groupPlayer6Connected::title, QGroupBox#groupPlayer7Connected::title, QGroupBox#groupPlayer8Connected::title { - subcontrol-origin: margin; - subcontrol-position: top left; - padding-left: 0px; - padding-right: 0px; - padding-top: 1px; - margin-left: 0px; - margin-right: -4px; - margin-bottom: 4px; + subcontrol-origin: margin; + subcontrol-position: top left; + padding-left: 0px; + padding-right: 0px; + padding-top: 1px; + margin-left: 0px; + margin-right: -4px; + margin-bottom: 4px; } QCheckBox#checkboxPlayer1Connected, @@ -142,7 +142,7 @@ QCheckBox#checkboxPlayer5Connected, QCheckBox#checkboxPlayer6Connected, QCheckBox#checkboxPlayer7Connected, QCheckBox#checkboxPlayer8Connected { - spacing: 0px; + spacing: 0px; } QWidget#Player1LEDs QCheckBox, @@ -153,7 +153,7 @@ QWidget#Player5LEDs QCheckBox, QWidget#Player6LEDs QCheckBox, QWidget#Player7LEDs QCheckBox, QWidget#Player8LEDs QCheckBox { - spacing: 0px; + spacing: 0px; } QWidget#Player1LEDs QCheckBox::indicator, @@ -164,9 +164,9 @@ QWidget#Player5LEDs QCheckBox::indicator, QWidget#Player6LEDs QCheckBox::indicator, QWidget#Player7LEDs QCheckBox::indicator, QWidget#Player8LEDs QCheckBox::indicator { - width: 6px; - height: 6px; - margin-left: 0px; + width: 6px; + height: 6px; + margin-left: 0px; } QWidget#bottomPerGameInput QCheckBox#checkboxPlayer1Connected::indicator, @@ -177,8 +177,8 @@ QWidget#bottomPerGameInput QCheckBox#checkboxPlayer5Connected::indicator, QWidget#bottomPerGameInput QCheckBox#checkboxPlayer6Connected::indicator, QWidget#bottomPerGameInput QCheckBox#checkboxPlayer7Connected::indicator, QWidget#bottomPerGameInput QCheckBox#checkboxPlayer8Connected::indicator { - width: 12px; - height: 12px; + width: 12px; + height: 12px; } QCheckBox#checkboxPlayer1Connected::indicator, @@ -189,8 +189,8 @@ QCheckBox#checkboxPlayer5Connected::indicator, QCheckBox#checkboxPlayer6Connected::indicator, QCheckBox#checkboxPlayer7Connected::indicator, QCheckBox#checkboxPlayer8Connected::indicator { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } QGroupBox#groupPlayer1Connected::indicator, @@ -201,8 +201,8 @@ QGroupBox#groupPlayer5Connected::indicator, QGroupBox#groupPlayer6Connected::indicator, QGroupBox#groupPlayer7Connected::indicator, QGroupBox#groupPlayer8Connected::indicator { - width: 16px; - height: 16px; + width: 16px; + height: 16px; } QWidget#Player1LEDs QCheckBox::indicator:checked, @@ -230,10 +230,10 @@ QCheckBox#checkboxPlayer6Connected::indicator:checked, QCheckBox#checkboxPlayer7Connected::indicator:checked, QCheckBox#checkboxPlayer8Connected::indicator:checked, QGroupBox#groupConnectedController::indicator:checked { - border-radius: 2px; - border: 1px solid #929192; - background: #39ff14; - image: none; + border-radius: 2px; + border: 1px solid #929192; + background: #39ff14; + image: none; } QWidget#Player1LEDs QCheckBox::indicator:unchecked, @@ -261,10 +261,10 @@ QCheckBox#checkboxPlayer6Connected::indicator:unchecked, QCheckBox#checkboxPlayer7Connected::indicator:unchecked, QCheckBox#checkboxPlayer8Connected::indicator:unchecked, QGroupBox#groupConnectedController::indicator:unchecked { - border-radius: 2px; - border: 1px solid #929192; - background: transparent; - image: none; + border-radius: 2px; + border: 1px solid #929192; + background: transparent; + image: none; } QWidget#controllerPlayer1, @@ -275,5 +275,5 @@ QWidget#controllerPlayer5, QWidget#controllerPlayer6, QWidget#controllerPlayer7, QWidget#controllerPlayer8 { - background: transparent; + background: transparent; } diff --git a/dist/qt_themes/qdarkstyle/style.qrc b/dist/qt_themes/qdarkstyle/style.qrc index ec07ba160..2b91204f3 100644 --- a/dist/qt_themes/qdarkstyle/style.qrc +++ b/dist/qt_themes/qdarkstyle/style.qrc @@ -52,6 +52,6 @@ rc/radio_unchecked.png - style.qss + style.qss diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss index 537558c1b..66026e8be 100644 --- a/dist/qt_themes/qdarkstyle/style.qss +++ b/dist/qt_themes/qdarkstyle/style.qss @@ -1314,9 +1314,9 @@ QGroupBox#vibrationGroup::indicator { QGroupBox#motionGroup::title, QGroupBox#vibrationGroup::title { - spacing: 2px; - padding-left: 1px; - padding-right: 1px; + spacing: 2px; + padding-left: 1px; + padding-right: 1px; } QWidget#bottomPerGameInput, @@ -1330,30 +1330,30 @@ QGroupBox#groupPlayer5Connected:checked, QGroupBox#groupPlayer6Connected:checked, QGroupBox#groupPlayer7Connected:checked, QGroupBox#groupPlayer8Connected:checked { - background-color: #232629; + background-color: #232629; } QWidget#topPerGameInput, QWidget#middleControllerApplet { - background-color: #31363b; + background-color: #31363b; } QWidget#topPerGameInput QComboBox, QWidget#middleControllerApplet QComboBox { - width: 119px; + width: 119px; } QRadioButton#radioDocked { - margin-left: -3px; + margin-left: -3px; } QRadioButton#radioUndocked { - margin-right: 5px; + margin-right: 5px; } QWidget#connectedControllers { - background: transparent; + background: transparent; } QWidget#playersSupported, @@ -1364,8 +1364,8 @@ QWidget#controllerSupported3, QWidget#controllerSupported4, QWidget#controllerSupported5, QWidget#controllerSupported6 { - border: none; - background: transparent; + border: none; + background: transparent; } QGroupBox#groupPlayer1Connected, @@ -1376,12 +1376,12 @@ QGroupBox#groupPlayer5Connected, QGroupBox#groupPlayer6Connected, QGroupBox#groupPlayer7Connected, QGroupBox#groupPlayer8Connected { - border: 1px solid #76797c; - border-radius: 3px; - padding: 0px; - min-height: 98px; - max-height: 98px; - margin-top: 0px; + border: 1px solid #76797c; + border-radius: 3px; + padding: 0px; + min-height: 98px; + max-height: 98px; + margin-top: 0px; } QGroupBox#groupPlayer1Connected:unchecked, @@ -1392,7 +1392,7 @@ QGroupBox#groupPlayer5Connected:unchecked, QGroupBox#groupPlayer6Connected:unchecked, QGroupBox#groupPlayer7Connected:unchecked, QGroupBox#groupPlayer8Connected:unchecked { - border: 1px solid #54575b; + border: 1px solid #54575b; } QGroupBox#groupPlayer1Connected::title, @@ -1403,14 +1403,14 @@ QGroupBox#groupPlayer5Connected::title, QGroupBox#groupPlayer6Connected::title, QGroupBox#groupPlayer7Connected::title, QGroupBox#groupPlayer8Connected::title { - subcontrol-origin: margin; - subcontrol-position: top left; - padding-left: 0px; - padding-right: 0px; - padding-top: 1px; - margin-left: -2px; - margin-right: -4px; - margin-bottom: 6px; + subcontrol-origin: margin; + subcontrol-position: top left; + padding-left: 0px; + padding-right: 0px; + padding-top: 1px; + margin-left: -2px; + margin-right: -4px; + margin-bottom: 6px; } QCheckBox#checkboxPlayer1Connected, @@ -1421,7 +1421,7 @@ QCheckBox#checkboxPlayer5Connected, QCheckBox#checkboxPlayer6Connected, QCheckBox#checkboxPlayer7Connected, QCheckBox#checkboxPlayer8Connected { - spacing: 0px; + spacing: 0px; } QWidget#Player1LEDs, @@ -1432,7 +1432,7 @@ QWidget#Player5LEDs, QWidget#Player6LEDs, QWidget#Player7LEDs, QWidget#Player8LEDs { - background: transparent; + background: transparent; } QWidget#Player1LEDs QCheckBox, @@ -1443,9 +1443,9 @@ QWidget#Player5LEDs QCheckBox, QWidget#Player6LEDs QCheckBox, QWidget#Player7LEDs QCheckBox, QWidget#Player8LEDs QCheckBox { - spacing: 0px; - margin-bottom: 0px; - margin-right: 0px; + spacing: 0px; + margin-bottom: 0px; + margin-right: 0px; } QWidget#Player1LEDs QCheckBox::indicator, @@ -1456,9 +1456,9 @@ QWidget#Player5LEDs QCheckBox::indicator, QWidget#Player6LEDs QCheckBox::indicator, QWidget#Player7LEDs QCheckBox::indicator, QWidget#Player8LEDs QCheckBox::indicator { - width: 6px; - height: 6px; - margin-left: 0px; + width: 6px; + height: 6px; + margin-left: 0px; } QWidget#bottomPerGameInput QCheckBox#checkboxPlayer1Connected::indicator, @@ -1469,8 +1469,8 @@ QWidget#bottomPerGameInput QCheckBox#checkboxPlayer5Connected::indicator, QWidget#bottomPerGameInput QCheckBox#checkboxPlayer6Connected::indicator, QWidget#bottomPerGameInput QCheckBox#checkboxPlayer7Connected::indicator, QWidget#bottomPerGameInput QCheckBox#checkboxPlayer8Connected::indicator { - width: 12px; - height: 12px; + width: 12px; + height: 12px; } QCheckBox#checkboxPlayer1Connected::indicator, @@ -1522,10 +1522,10 @@ QCheckBox#checkboxPlayer6Connected::indicator:checked, QCheckBox#checkboxPlayer7Connected::indicator:checked, QCheckBox#checkboxPlayer8Connected::indicator:checked, QGroupBox#groupConnectedController::indicator:checked { - border-radius: 2px; - border: 1px solid #929192; - background: #39ff14; - image: none; + border-radius: 2px; + border: 1px solid #929192; + background: #39ff14; + image: none; } QWidget#Player1LEDs QCheckBox::indicator:unchecked, @@ -1553,10 +1553,10 @@ QCheckBox#checkboxPlayer6Connected::indicator:unchecked, QCheckBox#checkboxPlayer7Connected::indicator:unchecked, QCheckBox#checkboxPlayer8Connected::indicator:unchecked, QGroupBox#groupConnectedController::indicator:unchecked { - border-radius: 2px; - border: 1px solid #929192; - background: transparent; - image: none; + border-radius: 2px; + border: 1px solid #929192; + background: transparent; + image: none; } QWidget#controllerPlayer1, @@ -1567,7 +1567,7 @@ QWidget#controllerPlayer5, QWidget#controllerPlayer6, QWidget#controllerPlayer7, QWidget#controllerPlayer8 { - background: transparent; + background: transparent; } /* touchscreen mapping widget */ diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc b/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc index 616aace73..579e73ece 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qrc @@ -221,6 +221,6 @@ rc/window_undock_pressed@2x.png - style.qss + style.qss diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss index 9f6a0ff1d..c6318ba4e 100644 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss @@ -235,19 +235,19 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox --------------------------------------------------------------------------- */ QGroupBox { - font-weight: bold; - border: 1px solid #32414B; - border-radius: 4px; - margin-top: 12px; - padding: 4px; + font-weight: bold; + border: 1px solid #32414B; + border-radius: 4px; + margin-top: 12px; + padding: 4px; } QGroupBox::title { - subcontrol-origin: margin; - subcontrol-position: top left; - padding-left: 3px; - padding-right: 5px; - padding-top: 4px; + subcontrol-origin: margin; + subcontrol-position: top left; + padding-left: 3px; + padding-right: 5px; + padding-top: 4px; } QGroupBox::indicator { -- cgit v1.2.3