Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ffc491546 | |||
| f5f30781ae | |||
| 1bd70d73c0 | |||
| eb149ec696 | |||
| 334ef2efdd | |||
| e7c174b426 | |||
| de79897f04 | |||
| efa0b7a056 | |||
| fc505110f1 | |||
| f0fac0c7fb | |||
| b8885aa03b | |||
| c024e5c69a | |||
| 4efaecf125 | |||
| 902bf6d37d | |||
| 2cd788b6ad | |||
| dd828607e0 | |||
| b798813eee | |||
| bb752df736 | |||
| 6fd3a1bf85 | |||
| 5bce81c3d6 | |||
| 3121acdf4e | |||
| ec8d72a567 | |||
| 67a8e73101 | |||
| f83c6e1e0c | |||
| 544fbd5c84 | |||
| da53bcee60 | |||
| e864aa25d5 |
@@ -0,0 +1,25 @@
|
||||
<RCC>
|
||||
<qresource prefix="controller">
|
||||
<file alias="dual_joycon">dual_joycon.png</file>
|
||||
<file alias="dual_joycon_dark">dual_joycon_dark.png</file>
|
||||
<file alias="dual_joycon_midnight">dual_joycon_midnight.png</file>
|
||||
<file alias="handheld">handheld.png</file>
|
||||
<file alias="handheld_dark">handheld_dark.png</file>
|
||||
<file alias="handheld_midnight">handheld_midnight.png</file>
|
||||
<file alias="pro_controller">pro_controller.png</file>
|
||||
<file alias="pro_controller_dark">pro_controller_dark.png</file>
|
||||
<file alias="pro_controller_midnight">pro_controller_midnight.png</file>
|
||||
<file alias="single_joycon_left">single_joycon_left.png</file>
|
||||
<file alias="single_joycon_left_dark">single_joycon_left_dark.png</file>
|
||||
<file alias="single_joycon_left_midnight">single_joycon_left_midnight.png</file>
|
||||
<file alias="single_joycon_right">single_joycon_right.png</file>
|
||||
<file alias="single_joycon_right_dark">single_joycon_right_dark.png</file>
|
||||
<file alias="single_joycon_right_midnight">single_joycon_right_midnight.png</file>
|
||||
<file alias="single_joycon_left_vertical">single_joycon_left_vertical.png</file>
|
||||
<file alias="single_joycon_left_vertical_dark">single_joycon_left_vertical_dark.png</file>
|
||||
<file alias="single_joycon_left_vertical_midnight">single_joycon_left_vertical_midnight.png</file>
|
||||
<file alias="single_joycon_right_vertical">single_joycon_right_vertical.png</file>
|
||||
<file alias="single_joycon_right_vertical_dark">single_joycon_right_vertical_dark.png</file>
|
||||
<file alias="single_joycon_right_vertical_midnight">single_joycon_right_vertical_midnight.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -5,6 +5,7 @@ Icon Name | License | Origin/Author
|
||||
qt_themes/default/icons/16x16/checked.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/16x16/failed.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
|
||||
qt_themes/default/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||
@@ -12,6 +13,7 @@ qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||
qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
|
||||
qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||
@@ -19,6 +21,7 @@ qt_themes/qdarkstyle/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||
qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/colorful/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/colorful/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
|
||||
qt_themes/colorful/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/colorful/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||
qt_themes/colorful/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||
|
||||
|
After Width: | Height: | Size: 362 B |
|
After Width: | Height: | Size: 362 B |
@@ -2,6 +2,7 @@
|
||||
<qresource prefix="icons/colorful_dark">
|
||||
<file alias="index.theme">icons/index.theme</file>
|
||||
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
|
||||
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
|
||||
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
|
||||
|
||||
|
After Width: | Height: | Size: 362 B |
|
After Width: | Height: | Size: 362 B |
@@ -2,6 +2,7 @@
|
||||
<qresource prefix="icons/colorful_midnight_blue">
|
||||
<file alias="index.theme">icons/index.theme</file>
|
||||
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
|
||||
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
|
||||
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<file alias="16x16/checked.png">icons/16x16/checked.png</file>
|
||||
<file alias="16x16/failed.png">icons/16x16/failed.png</file>
|
||||
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
|
||||
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
|
||||
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
|
||||
|
After Width: | Height: | Size: 349 B |
|
After Width: | Height: | Size: 349 B |
@@ -30,6 +30,66 @@ QPushButton#RendererStatusBarButton:checked {
|
||||
color: #e85c00;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:!checked{
|
||||
QPushButton#RendererStatusBarButton:!checked {
|
||||
color: #0066ff;
|
||||
}
|
||||
|
||||
QPushButton#buttonRefreshDevices {
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
max-width: 20px;
|
||||
max-height: 20px;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected,
|
||||
QCheckBox#checkboxPlayer2Connected,
|
||||
QCheckBox#checkboxPlayer3Connected,
|
||||
QCheckBox#checkboxPlayer4Connected,
|
||||
QCheckBox#checkboxPlayer5Connected,
|
||||
QCheckBox#checkboxPlayer6Connected,
|
||||
QCheckBox#checkboxPlayer7Connected,
|
||||
QCheckBox#checkboxPlayer8Connected {
|
||||
spacing: 0px;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected::indicator,
|
||||
QCheckBox#checkboxPlayer2Connected::indicator,
|
||||
QCheckBox#checkboxPlayer3Connected::indicator,
|
||||
QCheckBox#checkboxPlayer4Connected::indicator,
|
||||
QCheckBox#checkboxPlayer5Connected::indicator,
|
||||
QCheckBox#checkboxPlayer6Connected::indicator,
|
||||
QCheckBox#checkboxPlayer7Connected::indicator,
|
||||
QCheckBox#checkboxPlayer8Connected::indicator {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer2Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer3Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer4Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer5Connected::indicator:checked,
|
||||
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;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer2Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer3Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer4Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer5Connected::indicator:unchecked,
|
||||
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;
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 362 B |
|
After Width: | Height: | Size: 362 B |
@@ -2,6 +2,7 @@
|
||||
<qresource prefix="icons/qdarkstyle">
|
||||
<file alias="index.theme">icons/index.theme</file>
|
||||
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
|
||||
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
|
||||
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
|
||||
@@ -40,8 +40,8 @@ QCheckBox:disabled {
|
||||
|
||||
QCheckBox::indicator,
|
||||
QGroupBox::indicator {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
QGroupBox::indicator {
|
||||
@@ -1237,6 +1237,7 @@ QPlainTextEdit:disabled {
|
||||
background-color: #2b2e31;
|
||||
}
|
||||
|
||||
|
||||
QPushButton#TogglableStatusBarButton {
|
||||
min-width: 0px;
|
||||
color: #656565;
|
||||
@@ -1271,6 +1272,102 @@ QPushButton#RendererStatusBarButton:checked {
|
||||
color: #e85c00;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:!checked{
|
||||
color: #00ccdd;
|
||||
QPushButton#RendererStatusBarButton:!checked {
|
||||
color: #00ccdd;
|
||||
}
|
||||
|
||||
QPushButton#buttonRefreshDevices {
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
max-width: 24px;
|
||||
max-height: 24px;
|
||||
padding: 0px 0px;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected,
|
||||
QCheckBox#checkboxPlayer2Connected,
|
||||
QCheckBox#checkboxPlayer3Connected,
|
||||
QCheckBox#checkboxPlayer4Connected,
|
||||
QCheckBox#checkboxPlayer5Connected,
|
||||
QCheckBox#checkboxPlayer6Connected,
|
||||
QCheckBox#checkboxPlayer7Connected,
|
||||
QCheckBox#checkboxPlayer8Connected {
|
||||
spacing: 0px;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected::indicator,
|
||||
QCheckBox#checkboxPlayer2Connected::indicator,
|
||||
QCheckBox#checkboxPlayer3Connected::indicator,
|
||||
QCheckBox#checkboxPlayer4Connected::indicator,
|
||||
QCheckBox#checkboxPlayer5Connected::indicator,
|
||||
QCheckBox#checkboxPlayer6Connected::indicator,
|
||||
QCheckBox#checkboxPlayer7Connected::indicator,
|
||||
QCheckBox#checkboxPlayer8Connected::indicator {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer2Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer3Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer4Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer5Connected::indicator:checked,
|
||||
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;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer2Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer3Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer4Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer5Connected::indicator:unchecked,
|
||||
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;
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 362 B |
|
After Width: | Height: | Size: 362 B |
@@ -2,6 +2,7 @@
|
||||
<qresource prefix="icons/qdarkstyle_midnight_blue">
|
||||
<file alias="index.theme">icons/index.theme</file>
|
||||
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
|
||||
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
|
||||
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
|
||||
@@ -138,8 +138,6 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
QStatusBar {
|
||||
border: 1px solid #32414B;
|
||||
/* Fixes Spyder #9120, #9121 */
|
||||
background: #32414B;
|
||||
/* Fixes #205, white vertical borders separating items */
|
||||
}
|
||||
@@ -161,6 +159,7 @@ QStatusBar QToolTip {
|
||||
QStatusBar QLabel {
|
||||
/* Fixes Spyder #9120, #9121 */
|
||||
background: transparent;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* QCheckBox --------------------------------------------------------------
|
||||
@@ -236,21 +235,19 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
QGroupBox {
|
||||
font-weight: bold;
|
||||
border: 1px solid #32414B;
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
margin-top: 16px;
|
||||
font-weight: bold;
|
||||
border: 1px solid #32414B;
|
||||
border-radius: 4px;
|
||||
margin-top: 12px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top left;
|
||||
left: 3px;
|
||||
padding-left: 3px;
|
||||
padding-right: 5px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 16px;
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top left;
|
||||
padding-left: 3px;
|
||||
padding-right: 5px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
QGroupBox::indicator {
|
||||
@@ -367,28 +364,19 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar
|
||||
--------------------------------------------------------------------------- */
|
||||
QMenuBar {
|
||||
background-color: #32414B;
|
||||
padding: 2px;
|
||||
border: 1px solid #19232D;
|
||||
color: #F0F0F0;
|
||||
}
|
||||
|
||||
QMenuBar:focus {
|
||||
border: 1px solid #148CD2;
|
||||
}
|
||||
|
||||
QMenuBar::item {
|
||||
background: transparent;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
QMenuBar::item:selected {
|
||||
padding: 4px;
|
||||
background: transparent;
|
||||
border: 0px solid #32414B;
|
||||
}
|
||||
|
||||
QMenuBar::item:pressed {
|
||||
padding: 4px;
|
||||
border: 0px solid #32414B;
|
||||
background-color: #148CD2;
|
||||
color: #F0F0F0;
|
||||
@@ -396,6 +384,7 @@ QMenuBar::item:pressed {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
|
||||
/* QMenu ------------------------------------------------------------------
|
||||
|
||||
https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu
|
||||
@@ -482,7 +471,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
QAbstractItemView {
|
||||
alternate-background-color: #19232D;
|
||||
alternate-background-color: #1f2933;
|
||||
color: #F0F0F0;
|
||||
border: 1px solid #32414B;
|
||||
border-radius: 4px;
|
||||
@@ -501,13 +490,13 @@ QAbstractScrollArea {
|
||||
background-color: #19232D;
|
||||
border: 1px solid #32414B;
|
||||
border-radius: 4px;
|
||||
padding: 2px;
|
||||
/* fix #159 */
|
||||
min-height: 1.25em;
|
||||
/* fix #159 */
|
||||
color: #F0F0F0;
|
||||
}
|
||||
|
||||
|
||||
QAbstractScrollArea:disabled {
|
||||
color: #787878;
|
||||
}
|
||||
@@ -807,20 +796,22 @@ QAbstractSpinBox {
|
||||
}
|
||||
|
||||
QAbstractSpinBox:up-button {
|
||||
background-color: transparent #19232D;
|
||||
background-color: #505F69;
|
||||
subcontrol-origin: border;
|
||||
subcontrol-position: top right;
|
||||
border-left: 1px solid #32414B;
|
||||
border-bottom: 1px solid #32414B;
|
||||
border-top: 1px solid #32414B;
|
||||
border-right: 1px solid #32414B;
|
||||
border-top-right-radius: 4px;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
margin: 1px;
|
||||
margin: 0px;
|
||||
width: 12px;
|
||||
margin-bottom: -1px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off {
|
||||
image: url(":/qss_icons/rc/arrow_up_disabled.png");
|
||||
image: url(":/qss_icons/rc/up_arrow.png");
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
}
|
||||
@@ -830,20 +821,23 @@ QAbstractSpinBox::up-arrow:hover {
|
||||
}
|
||||
|
||||
QAbstractSpinBox:down-button {
|
||||
background-color: transparent #19232D;
|
||||
background-color: #505F69;
|
||||
subcontrol-origin: border;
|
||||
subcontrol-position: bottom right;
|
||||
border-left: 1px solid #32414B;
|
||||
border-right: 1px solid #32414B;
|
||||
border-bottom: 1px solid #32414B;
|
||||
border-top: 1px solid #32414B;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
margin: 1px;
|
||||
border-bottom-right-radius: 4px;
|
||||
margin: 0px;
|
||||
width: 12px;
|
||||
margin-top: -1px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off {
|
||||
image: url(":/qss_icons/rc/arrow_down_disabled.png");
|
||||
image: url(":/qss_icons/rc/down_arrow.png");
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
}
|
||||
@@ -1199,6 +1193,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
QComboBox {
|
||||
background-color: #0f1922;
|
||||
border: 1px solid #32414B;
|
||||
border-radius: 4px;
|
||||
selection-background-color: #1464A0;
|
||||
@@ -1216,7 +1211,7 @@ QComboBox {
|
||||
QComboBox QAbstractItemView {
|
||||
border: 1px solid #32414B;
|
||||
border-radius: 0;
|
||||
background-color: #19232D;
|
||||
background-color: #0f1922;
|
||||
selection-background-color: #1464A0;
|
||||
}
|
||||
|
||||
@@ -1285,7 +1280,12 @@ QComboBox::drop-down {
|
||||
}
|
||||
|
||||
QComboBox::down-arrow {
|
||||
image: url(":/qss_icons/rc/arrow_down_disabled.png");
|
||||
image: url(":/qss_icons/rc/down_arrow.png");
|
||||
background-color: #505F69;
|
||||
padding: 6px 2px;
|
||||
border: 1px solid #32414B;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
}
|
||||
@@ -1559,12 +1559,12 @@ QTabBar::tab:right:!selected {
|
||||
QTabBar::tab:top {
|
||||
background-color: #32414B;
|
||||
color: #F0F0F0;
|
||||
min-width: 36px;
|
||||
margin-left: 2px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
min-width: 5px;
|
||||
border-bottom: 3px solid #32414B;
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
@@ -1588,16 +1588,16 @@ QTabBar::tab:top:!selected:hover {
|
||||
|
||||
QTabBar::tab:bottom {
|
||||
color: #F0F0F0;
|
||||
min-width: 36px;
|
||||
border-top: 3px solid #32414B;
|
||||
background-color: #32414B;
|
||||
margin-left: 2px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
min-width: 5px;
|
||||
}
|
||||
|
||||
QTabBar::tab:bottom:selected {
|
||||
@@ -1752,21 +1752,6 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview
|
||||
https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
QTreeView:branch:selected, QTreeView:branch:hover {
|
||||
background: url(":/qss_icons/rc/transparent.png");
|
||||
}
|
||||
|
||||
QTreeView:branch:has-siblings:!adjoins-item {
|
||||
border-image: url(":/qss_icons/rc/branch_line.png") 0;
|
||||
}
|
||||
|
||||
QTreeView:branch:has-siblings:adjoins-item {
|
||||
border-image: url(":/qss_icons/rc/branch_more.png") 0;
|
||||
}
|
||||
|
||||
QTreeView:branch:!has-children:!has-siblings:adjoins-item {
|
||||
border-image: url(":/qss_icons/rc/branch_end.png") 0;
|
||||
}
|
||||
|
||||
QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings {
|
||||
border-image: none;
|
||||
@@ -1900,21 +1885,21 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
QHeaderView {
|
||||
background-color: #32414B;
|
||||
border: 0px transparent #32414B;
|
||||
background-color: #19232D;
|
||||
border: 0px transparent #19232D;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
QHeaderView:disabled {
|
||||
background-color: #32414B;
|
||||
border: 1px transparent #32414B;
|
||||
background-color: #19232D;
|
||||
border: 1px transparent #19232D;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
QHeaderView::section {
|
||||
background-color: #32414B;
|
||||
background-color: #19232D;
|
||||
color: #F0F0F0;
|
||||
padding: 2px;
|
||||
border-radius: 0px;
|
||||
@@ -1934,11 +1919,11 @@ QHeaderView::section:checked:disabled {
|
||||
QHeaderView::section::horizontal {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
border-left: 1px solid #19232D;
|
||||
border-left: 1px solid #32414B;
|
||||
}
|
||||
|
||||
QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one {
|
||||
border-left: 1px solid #32414B;
|
||||
border-left: 1px solid #19232D;
|
||||
}
|
||||
|
||||
QHeaderView::section::horizontal:disabled {
|
||||
@@ -1948,7 +1933,7 @@ QHeaderView::section::horizontal:disabled {
|
||||
QHeaderView::section::vertical {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
border-top: 1px solid #19232D;
|
||||
border-top: 1px solid #32414B;
|
||||
}
|
||||
|
||||
QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one {
|
||||
@@ -1962,7 +1947,7 @@ QHeaderView::section::vertical:disabled {
|
||||
QHeaderView::down-arrow {
|
||||
/* Those settings (border/width/height/background-color) solve bug */
|
||||
/* transparent arrow background and size */
|
||||
background-color: #32414B;
|
||||
background-color: #19232D;
|
||||
border: none;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
@@ -1972,7 +1957,7 @@ QHeaderView::down-arrow {
|
||||
}
|
||||
|
||||
QHeaderView::up-arrow {
|
||||
background-color: #32414B;
|
||||
background-color: #19232D;
|
||||
border: none;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
@@ -2172,3 +2157,132 @@ PlotWidget {
|
||||
/* Fix cut labels in plots #134 */
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
|
||||
QPushButton#TogglableStatusBarButton {
|
||||
min-width: 0px;
|
||||
color: #656565;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
padding: 0px 3px 0px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QPushButton#TogglableStatusBarButton:checked {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
QPushButton#TogglableStatusBarButton:hover {
|
||||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton {
|
||||
min-width: 0px;
|
||||
color: #656565;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
padding: 0px 3px 0px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:hover {
|
||||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:checked {
|
||||
color: #e85c00;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:!checked {
|
||||
color: #00ccdd;
|
||||
}
|
||||
|
||||
QPushButton#buttonRefreshDevices {
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
max-width: 20px;
|
||||
max-height: 20px;
|
||||
padding: 0px 0px;
|
||||
}
|
||||
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected,
|
||||
QCheckBox#checkboxPlayer2Connected,
|
||||
QCheckBox#checkboxPlayer3Connected,
|
||||
QCheckBox#checkboxPlayer4Connected,
|
||||
QCheckBox#checkboxPlayer5Connected,
|
||||
QCheckBox#checkboxPlayer6Connected,
|
||||
QCheckBox#checkboxPlayer7Connected,
|
||||
QCheckBox#checkboxPlayer8Connected {
|
||||
spacing: 0px;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected::indicator,
|
||||
QCheckBox#checkboxPlayer2Connected::indicator,
|
||||
QCheckBox#checkboxPlayer3Connected::indicator,
|
||||
QCheckBox#checkboxPlayer4Connected::indicator,
|
||||
QCheckBox#checkboxPlayer5Connected::indicator,
|
||||
QCheckBox#checkboxPlayer6Connected::indicator,
|
||||
QCheckBox#checkboxPlayer7Connected::indicator,
|
||||
QCheckBox#checkboxPlayer8Connected::indicator {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer2Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer3Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer4Connected::indicator:checked,
|
||||
QCheckBox#checkboxPlayer5Connected::indicator:checked,
|
||||
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;
|
||||
}
|
||||
|
||||
QCheckBox#checkboxPlayer1Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer2Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer3Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer4Connected::indicator:unchecked,
|
||||
QCheckBox#checkboxPlayer5Connected::indicator:unchecked,
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
|
||||
QSpinBox,
|
||||
QLineEdit,
|
||||
QTreeView#hotkey_list,
|
||||
QScrollArea#scrollArea QTreeView {
|
||||
background-color: #0f1922;
|
||||
}
|
||||
@@ -152,9 +152,11 @@ typedef uint16_t MicroProfileGroupId;
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#ifndef MICROPROFILE_API
|
||||
#define MICROPROFILE_API
|
||||
@@ -605,28 +607,45 @@ struct MicroProfileFrameState
|
||||
|
||||
struct MicroProfileThreadLog
|
||||
{
|
||||
MicroProfileLogEntry Log[MICROPROFILE_BUFFER_SIZE];
|
||||
std::array<MicroProfileLogEntry, MICROPROFILE_BUFFER_SIZE> Log{};
|
||||
|
||||
std::atomic<uint32_t> nPut;
|
||||
std::atomic<uint32_t> nGet;
|
||||
uint32_t nActive;
|
||||
uint32_t nGpu;
|
||||
ThreadIdType nThreadId;
|
||||
std::atomic<uint32_t> nPut{0};
|
||||
std::atomic<uint32_t> nGet{0};
|
||||
uint32_t nActive = 0;
|
||||
uint32_t nGpu = 0;
|
||||
ThreadIdType nThreadId{};
|
||||
|
||||
uint32_t nStack[MICROPROFILE_STACK_MAX];
|
||||
int64_t nChildTickStack[MICROPROFILE_STACK_MAX];
|
||||
uint32_t nStackPos;
|
||||
std::array<uint32_t, MICROPROFILE_STACK_MAX> nStack{};
|
||||
std::array<int64_t, MICROPROFILE_STACK_MAX> nChildTickStack{};
|
||||
uint32_t nStackPos = 0;
|
||||
|
||||
|
||||
uint8_t nGroupStackPos[MICROPROFILE_MAX_GROUPS];
|
||||
int64_t nGroupTicks[MICROPROFILE_MAX_GROUPS];
|
||||
int64_t nAggregateGroupTicks[MICROPROFILE_MAX_GROUPS];
|
||||
std::array<uint8_t, MICROPROFILE_MAX_GROUPS> nGroupStackPos{};
|
||||
std::array<int64_t, MICROPROFILE_MAX_GROUPS> nGroupTicks{};
|
||||
std::array<int64_t, MICROPROFILE_MAX_GROUPS> nAggregateGroupTicks{};
|
||||
enum
|
||||
{
|
||||
THREAD_MAX_LEN = 64,
|
||||
};
|
||||
char ThreadName[64];
|
||||
int nFreeListNext;
|
||||
char ThreadName[64]{};
|
||||
int nFreeListNext = 0;
|
||||
|
||||
void Reset() {
|
||||
Log.fill({});
|
||||
nPut = 0;
|
||||
nGet = 0;
|
||||
nActive = 0;
|
||||
nGpu = 0;
|
||||
nThreadId = {};
|
||||
nStack.fill(0);
|
||||
nChildTickStack.fill(0);
|
||||
nStackPos = 0;
|
||||
nGroupStackPos.fill(0);
|
||||
nGroupTicks.fill(0);
|
||||
nAggregateGroupTicks.fill(0);
|
||||
std::fill(std::begin(ThreadName), std::end(ThreadName), '\0');
|
||||
nFreeListNext = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#if MICROPROFILE_GPU_TIMERS_D3D11
|
||||
@@ -1151,6 +1170,7 @@ MicroProfileThreadLog* MicroProfileCreateThreadLog(const char* pName)
|
||||
MP_ASSERT(pLog->nPut.load() == 0);
|
||||
MP_ASSERT(pLog->nGet.load() == 0);
|
||||
S.nFreeListHead = S.Pool[S.nFreeListHead]->nFreeListNext;
|
||||
pLog->Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1158,7 +1178,6 @@ MicroProfileThreadLog* MicroProfileCreateThreadLog(const char* pName)
|
||||
S.nMemUsage += sizeof(MicroProfileThreadLog);
|
||||
S.Pool[S.nNumLogs++] = pLog;
|
||||
}
|
||||
memset(pLog, 0, sizeof(*pLog));
|
||||
int len = (int)strlen(pName);
|
||||
int maxlen = sizeof(pLog->ThreadName)-1;
|
||||
len = len < maxlen ? len : maxlen;
|
||||
@@ -1206,8 +1225,8 @@ void MicroProfileOnThreadExit()
|
||||
{
|
||||
S.Frames[i].nLogStart[nLogIndex] = 0;
|
||||
}
|
||||
memset(pLog->nGroupStackPos, 0, sizeof(pLog->nGroupStackPos));
|
||||
memset(pLog->nGroupTicks, 0, sizeof(pLog->nGroupTicks));
|
||||
pLog->nGroupStackPos.fill(0);
|
||||
pLog->nGroupTicks.fill(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -169,14 +169,13 @@ MICROPROFILEUI_API void MicroProfileCustomGroup(const char* pCustomName, uint32_
|
||||
MICROPROFILEUI_API void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup, const char* pTimer);
|
||||
|
||||
#ifdef MICROPROFILEUI_IMPL
|
||||
#ifdef _WIN32
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
MICROPROFILE_DEFINE(g_MicroProfileDetailed, "MicroProfile", "Detailed View", 0x8888000);
|
||||
MICROPROFILE_DEFINE(g_MicroProfileDrawGraph, "MicroProfile", "Draw Graph", 0xff44ee00);
|
||||
@@ -227,10 +226,10 @@ struct SOptionDesc
|
||||
uint8_t nIndex;
|
||||
bool bSelected;
|
||||
};
|
||||
static uint32_t g_MicroProfileAggregatePresets[] = {0, 10, 20, 30, 60, 120};
|
||||
static float g_MicroProfileReferenceTimePresets[] = {5.f, 10.f, 15.f,20.f, 33.33f, 66.66f, 100.f, 250.f, 500.f, 1000.f};
|
||||
static uint32_t g_MicroProfileOpacityPresets[] = {0x40, 0x80, 0xc0, 0xff};
|
||||
static const char* g_MicroProfilePresetNames[] =
|
||||
static const std::array<uint32_t, 6> g_MicroProfileAggregatePresets{0, 10, 20, 30, 60, 120};
|
||||
static const std::array<float, 10> g_MicroProfileReferenceTimePresets{5.f, 10.f, 15.f,20.f, 33.33f, 66.66f, 100.f, 250.f, 500.f, 1000.f};
|
||||
static const std::array<uint32_t, 4> g_MicroProfileOpacityPresets{0x40, 0x80, 0xc0, 0xff};
|
||||
static const std::array<const char*, 7> g_MicroProfilePresetNames
|
||||
{
|
||||
MICROPROFILE_DEFAULT_PRESET,
|
||||
"Render",
|
||||
@@ -243,8 +242,8 @@ static const char* g_MicroProfilePresetNames[] =
|
||||
|
||||
enum
|
||||
{
|
||||
MICROPROFILE_NUM_REFERENCE_PRESETS = sizeof(g_MicroProfileReferenceTimePresets)/sizeof(g_MicroProfileReferenceTimePresets[0]),
|
||||
MICROPROFILE_NUM_OPACITY_PRESETS = sizeof(g_MicroProfileOpacityPresets)/sizeof(g_MicroProfileOpacityPresets[0]),
|
||||
MICROPROFILE_NUM_REFERENCE_PRESETS = g_MicroProfileReferenceTimePresets.size(),
|
||||
MICROPROFILE_NUM_OPACITY_PRESETS = g_MicroProfileOpacityPresets.size(),
|
||||
#if MICROPROFILE_CONTEXT_SWITCH_TRACE
|
||||
MICROPROFILE_OPTION_SIZE = MICROPROFILE_NUM_REFERENCE_PRESETS + MICROPROFILE_NUM_OPACITY_PRESETS * 2 + 2 + 7,
|
||||
#else
|
||||
@@ -326,9 +325,9 @@ struct MicroProfileUI
|
||||
|
||||
MicroProfileUI g_MicroProfileUI;
|
||||
#define UI g_MicroProfileUI
|
||||
static uint32_t g_nMicroProfileBackColors[2] = { 0x474747, 0x313131 };
|
||||
static const std::array<uint32_t, 2> g_nMicroProfileBackColors{ 0x474747, 0x313131 };
|
||||
#define MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS 16
|
||||
static uint32_t g_nMicroProfileContextSwitchThreadColors[MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS] = //palette generated by http://tools.medialab.sciences-po.fr/iwanthue/index.php
|
||||
static const std::array<uint32_t, MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS> g_nMicroProfileContextSwitchThreadColors //palette generated by http://tools.medialab.sciences-po.fr/iwanthue/index.php
|
||||
{
|
||||
0x63607B,
|
||||
0x755E2B,
|
||||
@@ -356,7 +355,7 @@ void MicroProfileInitUI()
|
||||
{
|
||||
bInitialized = true;
|
||||
memset(&g_MicroProfileUI, 0, sizeof(g_MicroProfileUI));
|
||||
UI.nActiveMenu = (uint32_t)-1;
|
||||
UI.nActiveMenu = UINT32_MAX;
|
||||
UI.fDetailedOffsetTarget = UI.fDetailedOffset = 0.f;
|
||||
UI.fDetailedRangeTarget = UI.fDetailedRange = 50.f;
|
||||
|
||||
@@ -368,7 +367,7 @@ void MicroProfileInitUI()
|
||||
UI.nWidth = 100;
|
||||
UI.nHeight = 100;
|
||||
|
||||
UI.nCustomActive = (uint32_t)-1;
|
||||
UI.nCustomActive = UINT32_MAX;
|
||||
UI.nCustomTimerCount = 0;
|
||||
UI.nCustomCount = 0;
|
||||
|
||||
@@ -498,8 +497,8 @@ inline void MicroProfileDrawFloatWindow(uint32_t nX, uint32_t nY, const char** p
|
||||
{
|
||||
MicroProfileDrawBox(nX-MICROPROFILE_TEXT_WIDTH, nY, nX, nY + MICROPROFILE_TEXT_WIDTH, pColors[i]|0xff000000);
|
||||
}
|
||||
MicroProfileDrawText(nX + 1, nY + 1, (uint32_t)-1, ppStrings[i0], (uint32_t)strlen(ppStrings[i0]));
|
||||
MicroProfileDrawText(nX + nWidth - nStringLengths[i0+1] * (MICROPROFILE_TEXT_WIDTH+1), nY + 1, (uint32_t)-1, ppStrings[i0+1], (uint32_t)strlen(ppStrings[i0+1]));
|
||||
MicroProfileDrawText(nX + 1, nY + 1, UINT32_MAX, ppStrings[i0], (uint32_t)strlen(ppStrings[i0]));
|
||||
MicroProfileDrawText(nX + nWidth - nStringLengths[i0+1] * (MICROPROFILE_TEXT_WIDTH+1), nY + 1, UINT32_MAX, ppStrings[i0+1], (uint32_t)strlen(ppStrings[i0+1]));
|
||||
nY += (MICROPROFILE_TEXT_HEIGHT+1);
|
||||
}
|
||||
}
|
||||
@@ -522,7 +521,7 @@ inline void MicroProfileDrawTextBox(uint32_t nX, uint32_t nY, const char** ppStr
|
||||
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000);
|
||||
for(uint32_t i = 0; i < nNumStrings; ++i)
|
||||
{
|
||||
MicroProfileDrawText(nX + 1, nY + 1, (uint32_t)-1, ppStrings[i], (uint32_t)strlen(ppStrings[i]));
|
||||
MicroProfileDrawText(nX + 1, nY + 1, UINT32_MAX, ppStrings[i], (uint32_t)strlen(ppStrings[i]));
|
||||
nY += (MICROPROFILE_TEXT_HEIGHT+1);
|
||||
}
|
||||
}
|
||||
@@ -781,7 +780,7 @@ inline void MicroProfileDrawDetailedContextSwitchBars(uint32_t nY, uint32_t nThr
|
||||
{
|
||||
MicroProfile& S = *MicroProfileGet();
|
||||
int64_t nTickIn = -1;
|
||||
uint32_t nThreadBefore = -1;
|
||||
uint32_t nThreadBefore = UINT32_MAX;
|
||||
float fToMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu());
|
||||
float fMsToScreen = UI.nWidth / UI.fDetailedRange;
|
||||
float fMouseX = (float)UI.nMouseX;
|
||||
@@ -949,10 +948,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
|
||||
uint32_t nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadAfter;
|
||||
uint32_t nContextSwitchHoverThreadBefore = S.nContextSwitchHoverThreadBefore;
|
||||
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = -1;
|
||||
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = UINT32_MAX;
|
||||
|
||||
uint32_t nContextSwitchStart = -1;
|
||||
uint32_t nContextSwitchEnd = -1;
|
||||
uint32_t nContextSwitchStart = UINT32_MAX;
|
||||
uint32_t nContextSwitchEnd = UINT32_MAX;
|
||||
S.nContextSwitchHoverCpuNext = 0xff;
|
||||
S.nContextSwitchHoverTickIn = -1;
|
||||
S.nContextSwitchHoverTickOut = -1;
|
||||
@@ -1005,9 +1004,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
}while(pFrameLogFirst != pFrameFirst);
|
||||
|
||||
|
||||
if(nGet == (uint32_t)-1)
|
||||
if (nGet == UINT32_MAX) {
|
||||
continue;
|
||||
MP_ASSERT(nGet != (uint32_t)-1);
|
||||
}
|
||||
MP_ASSERT(nGet != UINT32_MAX);
|
||||
|
||||
nPut = pFrameLogLast->nLogStart[i];
|
||||
|
||||
@@ -1023,9 +1023,9 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
int64_t nBaseTicks = bGpu ? nBaseTicksGpu : nBaseTicksCpu;
|
||||
char ThreadName[MicroProfileThreadLog::THREAD_MAX_LEN + 16];
|
||||
uint64_t nThreadId = pLog->nThreadId;
|
||||
snprintf(ThreadName, sizeof(ThreadName)-1, "%04llx: %s", nThreadId, &pLog->ThreadName[0] );
|
||||
snprintf(ThreadName, sizeof(ThreadName)-1, "%04" PRIx64 ": %s", nThreadId, &pLog->ThreadName[0] );
|
||||
nY += 3;
|
||||
uint32_t nThreadColor = -1;
|
||||
uint32_t nThreadColor = UINT32_MAX;
|
||||
if(pLog->nThreadId == nContextSwitchHoverThreadAfter || pLog->nThreadId == nContextSwitchHoverThreadBefore)
|
||||
nThreadColor = UI.nHoverColorShared|0x906060;
|
||||
MicroProfileDrawText(0, nY, nThreadColor, &ThreadName[0], (uint32_t)strlen(&ThreadName[0]));
|
||||
@@ -1048,7 +1048,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
uint32_t nEnd = nRange[j][1];
|
||||
for(uint32_t k = nStart; k < nEnd; ++k)
|
||||
{
|
||||
MicroProfileLogEntry* pEntry = pLog->Log + k;
|
||||
MicroProfileLogEntry* pEntry = &pLog->Log[k];
|
||||
int nType = MicroProfileLogType(*pEntry);
|
||||
if(MP_LOG_ENTER == nType)
|
||||
{
|
||||
@@ -1066,7 +1066,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
continue;
|
||||
}
|
||||
|
||||
MicroProfileLogEntry* pEntryEnter = pLog->Log + nStack[nStackPos-1];
|
||||
MicroProfileLogEntry* pEntryEnter = &pLog->Log[nStack[nStackPos-1]];
|
||||
if(MicroProfileLogTimerIndex(*pEntryEnter) != MicroProfileLogTimerIndex(*pEntry))
|
||||
{
|
||||
//uprintf("mismatch %llx %llx\n", pEntryEnter->nToken, pEntry->nToken);
|
||||
@@ -1126,7 +1126,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
uint32_t nIntegerWidth = (uint32_t)(fXEnd - fXStart);
|
||||
if(nIntegerWidth)
|
||||
{
|
||||
if(bHover && UI.nActiveMenu == -1)
|
||||
if(bHover && UI.nActiveMenu == UINT32_MAX)
|
||||
{
|
||||
nHoverToken = MicroProfileLogTimerIndex(*pEntry);
|
||||
#if MICROPROFILE_DEBUG
|
||||
@@ -1146,7 +1146,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
int nCharacters = (nTextWidth - 2*MICROPROFILE_TEXT_WIDTH) / MICROPROFILE_TEXT_WIDTH;
|
||||
if(nCharacters>0)
|
||||
{
|
||||
MicroProfileDrawText(fXStartText+1, fYStart+1, -1, S.TimerInfo[nTimerIndex].pName, MicroProfileMin<uint32_t>(S.TimerInfo[nTimerIndex].nNameLen, nCharacters));
|
||||
MicroProfileDrawText(fXStartText + 1, fYStart + 1, UINT32_MAX, S.TimerInfo[nTimerIndex].pName, MicroProfileMin<uint32_t>(S.TimerInfo[nTimerIndex].nNameLen, nCharacters));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1158,7 +1158,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
int nLineX = (int)floor(fXAvg+0.5f);
|
||||
if(nLineX != (int)nLinesDrawn[nStackPos])
|
||||
{
|
||||
if(bHover && UI.nActiveMenu == -1)
|
||||
if(bHover && UI.nActiveMenu == UINT32_MAX)
|
||||
{
|
||||
nHoverToken = (uint32_t)MicroProfileLogTimerIndex(*pEntry);
|
||||
nHoverTime = MicroProfileLogTickDifference(nTickStart, nTickEnd);
|
||||
@@ -1235,9 +1235,9 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
// nThreadId is 32-bit on Windows
|
||||
int nStrLen = snprintf(ThreadName, sizeof(ThreadName)-1, "%04x: %s%s", nThreadId, cLocal, i < nNumThreadsBase ? &S.Pool[i]->ThreadName[0] : MICROPROFILE_THREAD_NAME_FROM_ID(nThreadId) );
|
||||
#else
|
||||
int nStrLen = snprintf(ThreadName, sizeof(ThreadName)-1, "%04llx: %s%s", nThreadId, cLocal, i < nNumThreadsBase ? &S.Pool[i]->ThreadName[0] : MICROPROFILE_THREAD_NAME_FROM_ID(nThreadId) );
|
||||
int nStrLen = snprintf(ThreadName, sizeof(ThreadName)-1, "%04" PRIx64 ": %s%s", nThreadId, cLocal, i < nNumThreadsBase ? &S.Pool[i]->ThreadName[0] : MICROPROFILE_THREAD_NAME_FROM_ID(nThreadId) );
|
||||
#endif
|
||||
uint32_t nThreadColor = -1;
|
||||
uint32_t nThreadColor = UINT32_MAX;
|
||||
if(nThreadId == nContextSwitchHoverThreadAfter || nThreadId == nContextSwitchHoverThreadBefore)
|
||||
nThreadColor = UI.nHoverColorShared|0x906060;
|
||||
MicroProfileDrawDetailedContextSwitchBars(nY+2, nThreadId, nContextSwitchStart, nContextSwitchEnd, nBaseTicksCpu, nBaseY);
|
||||
@@ -1249,9 +1249,6 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
|
||||
S.nContextSwitchHoverCpu = S.nContextSwitchHoverCpuNext;
|
||||
|
||||
|
||||
|
||||
|
||||
UI.pDisplayMouseOver = pMouseOverNext;
|
||||
|
||||
if(!S.nRunning)
|
||||
@@ -1286,10 +1283,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart);
|
||||
float fStartTextX = fXStart - fStartTextWidth - 2;
|
||||
MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
|
||||
MicroProfileDrawText(fStartTextX+1, nBaseY, (uint32_t)-1, sBuffer, nLenStart);
|
||||
MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart);
|
||||
uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd);
|
||||
MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
|
||||
MicroProfileDrawText(fXEnd+2, nBaseY+1, (uint32_t)-1, sBuffer, nLenEnd);
|
||||
MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd);
|
||||
|
||||
if(UI.nMouseRight)
|
||||
{
|
||||
@@ -1316,10 +1313,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart);
|
||||
float fStartTextX = fXStart - fStartTextWidth - 2;
|
||||
MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
|
||||
MicroProfileDrawText(fStartTextX+1, nBaseY, (uint32_t)-1, sBuffer, nLenStart);
|
||||
MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart);
|
||||
uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd);
|
||||
MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
|
||||
MicroProfileDrawText(fXEnd+2, nBaseY+1, (uint32_t)-1, sBuffer, nLenEnd);
|
||||
MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1365,7 +1362,7 @@ inline void MicroProfileDrawDetailedFrameHistory(uint32_t nWidth, uint32_t nHeig
|
||||
fBaseX = fXStart;
|
||||
uint32_t nColor = MICROPROFILE_FRAME_HISTORY_COLOR_CPU;
|
||||
if(nIndex == nSelectedFrame)
|
||||
nColor = (uint32_t)-1;
|
||||
nColor = UINT32_MAX;
|
||||
MicroProfileDrawBox(fXStart, nBaseY + fScale * nBarHeight, fXEnd, nBaseY+MICROPROFILE_FRAME_HISTORY_HEIGHT, nColor, MicroProfileBoxTypeBar);
|
||||
if(pNext->nFrameStartCpu > nCpuStart)
|
||||
{
|
||||
@@ -1387,7 +1384,7 @@ inline void MicroProfileDrawDetailedView(uint32_t nWidth, uint32_t nHeight)
|
||||
uint32_t nBaseY = MICROPROFILE_TEXT_HEIGHT + 1;
|
||||
|
||||
int nSelectedFrame = -1;
|
||||
if(UI.nMouseY > nBaseY && UI.nMouseY <= nBaseY + MICROPROFILE_FRAME_HISTORY_HEIGHT && UI.nActiveMenu == -1)
|
||||
if(UI.nMouseY > nBaseY && UI.nMouseY <= nBaseY + MICROPROFILE_FRAME_HISTORY_HEIGHT && UI.nActiveMenu == UINT32_MAX)
|
||||
{
|
||||
|
||||
nSelectedFrame = ((MICROPROFILE_NUM_FRAMES) * (UI.nWidth-UI.nMouseX) / UI.nWidth);
|
||||
@@ -1425,7 +1422,7 @@ inline void MicroProfileDrawHeader(int32_t nX, uint32_t nWidth, const char* pNam
|
||||
if(pName)
|
||||
{
|
||||
MicroProfileDrawBox(nX-8, MICROPROFILE_TEXT_HEIGHT + 2, nX + nWidth+5, MICROPROFILE_TEXT_HEIGHT + 2 + (MICROPROFILE_TEXT_HEIGHT+1), 0xff000000|g_nMicroProfileBackColors[1]);
|
||||
MicroProfileDrawText(nX, MICROPROFILE_TEXT_HEIGHT + 2, (uint32_t)-1, pName, (uint32_t)strlen(pName));
|
||||
MicroProfileDrawText(nX, MICROPROFILE_TEXT_HEIGHT + 2, UINT32_MAX, pName, (uint32_t)strlen(pName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1440,7 +1437,7 @@ inline void MicroProfileLoopActiveGroupsDraw(int32_t nX, int32_t nY, const char*
|
||||
uint32_t nCount = 0;
|
||||
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
|
||||
{
|
||||
uint64_t nMask = 1ll << j;
|
||||
uint64_t nMask = 1ULL << j;
|
||||
if(nMask & nGroup)
|
||||
{
|
||||
nY += MICROPROFILE_TEXT_HEIGHT + 1;
|
||||
@@ -1521,7 +1518,7 @@ inline void MicroProfileCalcTimers(float* pTimers, float* pAverage, float* pMax,
|
||||
}
|
||||
}
|
||||
}
|
||||
nMask <<= 1ll;
|
||||
nMask <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1543,7 +1540,7 @@ inline void MicroProfileDrawBarArrayCallback(uint32_t nTimer, uint32_t nIdx, uin
|
||||
snprintf(sBuffer, SBUF_MAX-1, "%5.2f", pTimers[nIdx]);
|
||||
if (!pTimers2)
|
||||
MicroProfileDrawBox(nX + nTextWidth, nY, nX + nTextWidth + fWidth * pTimers[nIdx+1], nY + nHeight, UI.nOpacityForeground|S.TimerInfo[nTimer].nColor, MicroProfileBoxTypeBar);
|
||||
MicroProfileDrawText(nX, nY, (uint32_t)-1, sBuffer, (uint32_t)strlen(sBuffer));
|
||||
MicroProfileDrawText(nX, nY, UINT32_MAX, sBuffer, (uint32_t)strlen(sBuffer));
|
||||
}
|
||||
|
||||
|
||||
@@ -1564,7 +1561,7 @@ inline void MicroProfileDrawBarCallCountCallback(uint32_t nTimer, uint32_t nIdx,
|
||||
MicroProfile& S = *MicroProfileGet();
|
||||
char sBuffer[SBUF_MAX];
|
||||
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5d", S.Frame[nTimer].nCount);//fix
|
||||
MicroProfileDrawText(nX, nY, (uint32_t)-1, sBuffer, nLen);
|
||||
MicroProfileDrawText(nX, nY, UINT32_MAX, sBuffer, nLen);
|
||||
}
|
||||
|
||||
inline uint32_t MicroProfileDrawBarCallCount(int32_t nX, int32_t nY, const char* pName)
|
||||
@@ -1588,7 +1585,7 @@ inline void MicroProfileDrawBarMetaAverageCallback(uint32_t nTimer, uint32_t nId
|
||||
float fRcpFrames = pArgs->fRcpFrames;
|
||||
char sBuffer[SBUF_MAX];
|
||||
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5.2f", pCounters[nTimer] * fRcpFrames);
|
||||
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, (uint32_t)-1, sBuffer, nLen);
|
||||
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, UINT32_MAX, sBuffer, nLen);
|
||||
}
|
||||
|
||||
inline uint32_t MicroProfileDrawBarMetaAverage(int32_t nX, int32_t nY, uint64_t* pCounters, const char* pName, uint32_t nTotalHeight)
|
||||
@@ -1609,8 +1606,8 @@ inline void MicroProfileDrawBarMetaCountCallback(uint32_t nTimer, uint32_t nIdx,
|
||||
{
|
||||
uint64_t* pCounters = (uint64_t*)pExtra;
|
||||
char sBuffer[SBUF_MAX];
|
||||
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5llu", pCounters[nTimer]);
|
||||
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, (uint32_t)-1, sBuffer, nLen);
|
||||
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5" PRIu64, pCounters[nTimer]);
|
||||
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, UINT32_MAX, sBuffer, nLen);
|
||||
}
|
||||
|
||||
inline uint32_t MicroProfileDrawBarMetaCount(int32_t nX, int32_t nY, uint64_t* pCounters, const char* pName, uint32_t nTotalHeight)
|
||||
@@ -1667,7 +1664,7 @@ bool MicroProfileDrawGraph(uint32_t nScreenWidth, uint32_t nScreenHeight)
|
||||
if(bMouseOver)
|
||||
{
|
||||
float fXAvg = fMouseXPrc * MICROPROFILE_GRAPH_WIDTH + nX;
|
||||
MicroProfileDrawLineVertical(fXAvg, nY, nY + MICROPROFILE_GRAPH_HEIGHT, (uint32_t)-1);
|
||||
MicroProfileDrawLineVertical(fXAvg, nY, nY + MICROPROFILE_GRAPH_HEIGHT, UINT32_MAX);
|
||||
}
|
||||
|
||||
|
||||
@@ -1706,7 +1703,7 @@ bool MicroProfileDrawGraph(uint32_t nScreenWidth, uint32_t nScreenHeight)
|
||||
|
||||
char buf[32];
|
||||
int nLen = snprintf(buf, sizeof(buf)-1, "%5.2fms", S.fReferenceTime);
|
||||
MicroProfileDrawText(nX+1, fY1 - (2+MICROPROFILE_TEXT_HEIGHT), (uint32_t)-1, buf, nLen);
|
||||
MicroProfileDrawText(nX+1, fY1 - (2+MICROPROFILE_TEXT_HEIGHT), UINT32_MAX, buf, nLen);
|
||||
}
|
||||
|
||||
|
||||
@@ -1782,7 +1779,7 @@ void MicroProfileDumpTimers()
|
||||
|
||||
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
|
||||
{
|
||||
uint64_t nMask = 1ll << j;
|
||||
uint64_t nMask = 1ULL << j;
|
||||
if(nMask & nActiveGroup)
|
||||
{
|
||||
MICROPROFILE_PRINTF("%s\n", S.GroupInfo[j].pName);
|
||||
@@ -1823,7 +1820,7 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh
|
||||
uint32_t nNumGroups = 0;
|
||||
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
|
||||
{
|
||||
if(nActiveGroup & (1ll << j))
|
||||
if(nActiveGroup & (1ULL << j))
|
||||
{
|
||||
nNumTimers += S.GroupInfo[j].nNumTimers;
|
||||
nNumGroups += 1;
|
||||
@@ -1878,7 +1875,7 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh
|
||||
for(uint32_t i = 0; i < nNumTimers+nNumGroups+1; ++i)
|
||||
{
|
||||
uint32_t nY0 = nY + i * (nHeight + 1);
|
||||
bool bInside = (UI.nActiveMenu == -1) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
|
||||
bool bInside = (UI.nActiveMenu == UINT32_MAX) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
|
||||
MicroProfileDrawBox(nX, nY0, nWidth+nX, nY0 + (nHeight+1)+1, UI.nOpacityBackground | (g_nMicroProfileBackColors[nColorIndex++ & 1] + ((bInside) ? 0x002c2c2c : 0)));
|
||||
}
|
||||
nX += 10;
|
||||
@@ -1927,22 +1924,22 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh
|
||||
nY = nHeight + 3 - UI.nOffsetY;
|
||||
for(uint32_t i = 0; i < nNumTimers+nNumGroups+1; ++i)
|
||||
{
|
||||
uint32_t nY0 = nY + i * (nHeight + 1);
|
||||
bool bInside = (UI.nActiveMenu == -1) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
|
||||
const uint32_t nY0 = nY + i * (nHeight + 1);
|
||||
const bool bInside = (UI.nActiveMenu == UINT32_MAX) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
|
||||
MicroProfileDrawBox(nX, nY0, nTimerWidth, nY0 + (nHeight+1)+1, 0xff0000000 | (g_nMicroProfileBackColors[nColorIndex++ & 1] + ((bInside) ? 0x002c2c2c : 0)));
|
||||
}
|
||||
nX += MicroProfileDrawBarLegend(nX, nY, nTotalHeight, nTimerWidth-5) + 1;
|
||||
|
||||
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
|
||||
{
|
||||
if(nActiveGroup & (1ll << j))
|
||||
if(nActiveGroup & (1ULL << j))
|
||||
{
|
||||
MicroProfileDrawText(nX, nY + (1+nHeight) * nLegendOffset, (uint32_t)-1, S.GroupInfo[j].pName, S.GroupInfo[j].nNameLen);
|
||||
MicroProfileDrawText(nX, nY + (1+nHeight) * nLegendOffset, UINT32_MAX, S.GroupInfo[j].pName, S.GroupInfo[j].nNameLen);
|
||||
nLegendOffset += S.GroupInfo[j].nNumTimers+1;
|
||||
}
|
||||
}
|
||||
MicroProfileDrawHeader(nX, nTimerWidth-5, "Group");
|
||||
MicroProfileDrawTextRight(nTimerWidth-3, MICROPROFILE_TEXT_HEIGHT + 2, (uint32_t)-1, "Timer", 5);
|
||||
MicroProfileDrawTextRight(nTimerWidth-3, MICROPROFILE_TEXT_HEIGHT + 2, UINT32_MAX, "Timer", 5);
|
||||
MicroProfileDrawLineVertical(nTimerWidth, 0, nTotalHeight+nY, UI.nOpacityBackground|g_nMicroProfileBackColors[0]|g_nMicroProfileBackColors[1]);
|
||||
MicroProfileDrawLineHorizontal(0, nWidth, 2*MICROPROFILE_TEXT_HEIGHT + 3, UI.nOpacityBackground|g_nMicroProfileBackColors[0]|g_nMicroProfileBackColors[1]);
|
||||
}
|
||||
@@ -2003,7 +2000,7 @@ inline const char* MicroProfileUIMenuGroups(int nIndex, bool* bSelected)
|
||||
}
|
||||
else
|
||||
{
|
||||
*bSelected = 0 != (S.nActiveGroupWanted & (1ll << Item.nIndex));
|
||||
*bSelected = 0 != (S.nActiveGroupWanted & (1ULL << Item.nIndex));
|
||||
snprintf(buffer, sizeof(buffer)-1, " %s", Item.pName);
|
||||
}
|
||||
return buffer;
|
||||
@@ -2015,16 +2012,18 @@ inline const char* MicroProfileUIMenuGroups(int nIndex, bool* bSelected)
|
||||
inline const char* MicroProfileUIMenuAggregate(int nIndex, bool* bSelected)
|
||||
{
|
||||
MicroProfile& S = *MicroProfileGet();
|
||||
if(nIndex < sizeof(g_MicroProfileAggregatePresets)/sizeof(g_MicroProfileAggregatePresets[0]))
|
||||
if(static_cast<uint32_t>(nIndex) < g_MicroProfileAggregatePresets.size())
|
||||
{
|
||||
int val = g_MicroProfileAggregatePresets[nIndex];
|
||||
*bSelected = (int)S.nAggregateFlip == val;
|
||||
if(0 == val)
|
||||
uint32_t val = g_MicroProfileAggregatePresets[nIndex];
|
||||
*bSelected = S.nAggregateFlip == val;
|
||||
if (0 == val)
|
||||
{
|
||||
return "Infinite";
|
||||
}
|
||||
else
|
||||
{
|
||||
static char buf[128];
|
||||
snprintf(buf, sizeof(buf)-1, "%7d", val);
|
||||
snprintf(buf, sizeof(buf)-1, "%7u", val);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
@@ -2098,11 +2097,13 @@ inline const char* MicroProfileUIMenuPreset(int nIndex, bool* bSelected)
|
||||
{
|
||||
static char buf[128];
|
||||
*bSelected = false;
|
||||
int nNumPresets = sizeof(g_MicroProfilePresetNames) / sizeof(g_MicroProfilePresetNames[0]);
|
||||
int nNumPresets = static_cast<int>(g_MicroProfilePresetNames.size());
|
||||
int nIndexSave = nIndex - nNumPresets - 1;
|
||||
if(nIndex == nNumPresets)
|
||||
if (nIndex == nNumPresets)
|
||||
{
|
||||
return "--";
|
||||
else if(nIndexSave >=0 && nIndexSave <nNumPresets)
|
||||
}
|
||||
else if(nIndexSave >=0 && nIndexSave < nNumPresets)
|
||||
{
|
||||
snprintf(buf, sizeof(buf)-1, "Save '%s'", g_MicroProfilePresetNames[nIndexSave]);
|
||||
return buf;
|
||||
@@ -2120,13 +2121,13 @@ inline const char* MicroProfileUIMenuPreset(int nIndex, bool* bSelected)
|
||||
|
||||
inline const char* MicroProfileUIMenuCustom(int nIndex, bool* bSelected)
|
||||
{
|
||||
if((uint32_t)-1 == UI.nCustomActive)
|
||||
if(UINT32_MAX == UI.nCustomActive)
|
||||
{
|
||||
*bSelected = nIndex == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*bSelected = nIndex-2 == UI.nCustomActive;
|
||||
*bSelected = nIndex-2 == static_cast<int>(UI.nCustomActive);
|
||||
}
|
||||
switch(nIndex)
|
||||
{
|
||||
@@ -2202,7 +2203,7 @@ inline void MicroProfileUIClickGroups(int nIndex)
|
||||
else
|
||||
{
|
||||
MP_ASSERT(Item.nIndex < S.nGroupCount);
|
||||
S.nActiveGroupWanted ^= (1ll << Item.nIndex);
|
||||
S.nActiveGroupWanted ^= (1ULL << Item.nIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2273,7 +2274,7 @@ inline void MicroProfileUIClickOptions(int nIndex)
|
||||
|
||||
inline void MicroProfileUIClickPreset(int nIndex)
|
||||
{
|
||||
int nNumPresets = sizeof(g_MicroProfilePresetNames) / sizeof(g_MicroProfilePresetNames[0]);
|
||||
int nNumPresets = static_cast<int>(g_MicroProfilePresetNames.size());
|
||||
int nIndexSave = nIndex - nNumPresets - 1;
|
||||
if(nIndexSave >= 0 && nIndexSave < nNumPresets)
|
||||
{
|
||||
@@ -2310,7 +2311,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
|
||||
uint32_t nX = 0;
|
||||
uint32_t nY = 0;
|
||||
bool bMouseOver = UI.nMouseY < MICROPROFILE_TEXT_HEIGHT + 1;
|
||||
|
||||
#define SBUF_SIZE 256
|
||||
char buffer[256];
|
||||
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + (MICROPROFILE_TEXT_HEIGHT+1)+1, 0xff000000|g_nMicroProfileBackColors[1]);
|
||||
@@ -2321,7 +2322,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
uint32_t nNumMenuItems = 0;
|
||||
|
||||
int nLen = snprintf(buffer, 127, "MicroProfile");
|
||||
MicroProfileDrawText(nX, nY, (uint32_t)-1, buffer, nLen);
|
||||
MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nLen);
|
||||
nX += (sizeof("MicroProfile")+2) * (MICROPROFILE_TEXT_WIDTH+1);
|
||||
pMenuText[nNumMenuItems++] = "Mode";
|
||||
pMenuText[nNumMenuItems++] = "Groups";
|
||||
@@ -2409,7 +2410,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
};
|
||||
|
||||
|
||||
uint32_t nSelectMenu = (uint32_t)-1;
|
||||
uint32_t nSelectMenu = UINT32_MAX;
|
||||
for(uint32_t i = 0; i < nNumMenuItems; ++i)
|
||||
{
|
||||
nMenuX[i] = nX;
|
||||
@@ -2419,17 +2420,17 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
{
|
||||
MicroProfileDrawBox(nX-1, nY, nX + nLen * (MICROPROFILE_TEXT_WIDTH+1), nY +(MICROPROFILE_TEXT_HEIGHT+1)+1, 0xff888888);
|
||||
nSelectMenu = i;
|
||||
if((UI.nMouseLeft || UI.nMouseRight) && i == (int)nPauseIndex)
|
||||
if((UI.nMouseLeft || UI.nMouseRight) && i == (uint32_t)nPauseIndex)
|
||||
{
|
||||
S.nToggleRunning = 1;
|
||||
}
|
||||
}
|
||||
MicroProfileDrawText(nX, nY, (uint32_t)-1, pMenuText[i], (uint32_t)strlen(pMenuText[i]));
|
||||
MicroProfileDrawText(nX, nY, UINT32_MAX, pMenuText[i], (uint32_t)strlen(pMenuText[i]));
|
||||
nX += (nLen+1) * (MICROPROFILE_TEXT_WIDTH+1);
|
||||
}
|
||||
uint32_t nMenu = nSelectMenu != (uint32_t)-1 ? nSelectMenu : UI.nActiveMenu;
|
||||
uint32_t nMenu = nSelectMenu != UINT32_MAX ? nSelectMenu : UI.nActiveMenu;
|
||||
UI.nActiveMenu = nMenu;
|
||||
if((uint32_t)-1 != nMenu)
|
||||
if(UINT32_MAX != nMenu)
|
||||
{
|
||||
nX = nMenuX[nMenu];
|
||||
nY += MICROPROFILE_TEXT_HEIGHT+1;
|
||||
@@ -2450,9 +2451,9 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
{
|
||||
UI.nActiveMenu = nMenu;
|
||||
}
|
||||
else if(nSelectMenu == (uint32_t)-1)
|
||||
else if(nSelectMenu == UINT32_MAX)
|
||||
{
|
||||
UI.nActiveMenu = (uint32_t)-1;
|
||||
UI.nActiveMenu = UINT32_MAX;
|
||||
}
|
||||
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000|g_nMicroProfileBackColors[1]);
|
||||
for(int i = 0; i < nNumLines; ++i)
|
||||
@@ -2461,7 +2462,6 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
const char* pString = CB(i, &bSelected);
|
||||
if(UI.nMouseY >= nY && UI.nMouseY < nY + MICROPROFILE_TEXT_HEIGHT + 1)
|
||||
{
|
||||
bMouseOver = true;
|
||||
if(UI.nMouseLeft || UI.nMouseRight)
|
||||
{
|
||||
CBClick[nMenu](i);
|
||||
@@ -2469,7 +2469,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + MICROPROFILE_TEXT_HEIGHT + 1, 0xff888888);
|
||||
}
|
||||
int nLen = snprintf(buffer, SBUF_SIZE-1, "%c %s", bSelected ? '*' : ' ' ,pString);
|
||||
MicroProfileDrawText(nX, nY, (uint32_t)-1, buffer, nLen);
|
||||
MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nLen);
|
||||
nY += MICROPROFILE_TEXT_HEIGHT+1;
|
||||
}
|
||||
}
|
||||
@@ -2484,7 +2484,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
float fMaxMs = fToMs * S.nFlipMaxDisplay;
|
||||
int nLen = snprintf(FrameTimeMessage, sizeof(FrameTimeMessage)-1, "Time[%6.2f] Avg[%6.2f] Max[%6.2f]", fMs, fAverageMs, fMaxMs);
|
||||
pMenuText[nNumMenuItems++] = &FrameTimeMessage[0];
|
||||
MicroProfileDrawText(nWidth - nLen * (MICROPROFILE_TEXT_WIDTH+1), 0, -1, FrameTimeMessage, nLen);
|
||||
MicroProfileDrawText(nWidth - nLen * (MICROPROFILE_TEXT_WIDTH+1), 0, UINT32_MAX, FrameTimeMessage, nLen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2538,7 +2538,7 @@ inline void MicroProfileMoveGraph()
|
||||
|
||||
inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
|
||||
{
|
||||
if((uint32_t)-1 != UI.nCustomActive)
|
||||
if(UINT32_MAX != UI.nCustomActive)
|
||||
{
|
||||
MicroProfile& S = *MicroProfileGet();
|
||||
MP_ASSERT(UI.nCustomActive < MICROPROFILE_CUSTOM_MAX);
|
||||
@@ -2571,8 +2571,8 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
|
||||
pColors[i] = S.TimerInfo[nTimerIndex].nColor;
|
||||
}
|
||||
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 3*MICROPROFILE_TEXT_WIDTH, nOffsetY, (uint32_t)-1, "Avg", sizeof("Avg")-1);
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 13*MICROPROFILE_TEXT_WIDTH, nOffsetY, (uint32_t)-1, "Max", sizeof("Max")-1);
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 3*MICROPROFILE_TEXT_WIDTH, nOffsetY, UINT32_MAX, "Avg", sizeof("Avg")-1);
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 13*MICROPROFILE_TEXT_WIDTH, nOffsetY, UINT32_MAX, "Max", sizeof("Max")-1);
|
||||
for(uint32_t i = 0; i < nCount; ++i)
|
||||
{
|
||||
nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT);
|
||||
@@ -2582,10 +2582,10 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
|
||||
int nSize;
|
||||
uint32_t nOffsetX = MICROPROFILE_CUSTOM_PADDING;
|
||||
nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2f", pTimeAvg[i]);
|
||||
MicroProfileDrawText(nOffsetX, nOffsetY, (uint32_t)-1, Buffer, nSize);
|
||||
MicroProfileDrawText(nOffsetX, nOffsetY, UINT32_MAX, Buffer, nSize);
|
||||
nOffsetX += (nSize+2) * (MICROPROFILE_TEXT_WIDTH+1);
|
||||
nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2f", pTimeMax[i]);
|
||||
MicroProfileDrawText(nOffsetX, nOffsetY, (uint32_t)-1, Buffer, nSize);
|
||||
MicroProfileDrawText(nOffsetX, nOffsetY, UINT32_MAX, Buffer, nSize);
|
||||
nOffsetX += (nSize+2) * (MICROPROFILE_TEXT_WIDTH+1);
|
||||
nSize = snprintf(Buffer, sizeof(Buffer)-1, "%s:%s", S.GroupInfo[nGroupIndex].pName, pTimerInfo->pName);
|
||||
MicroProfileDrawText(nOffsetX, nOffsetY, pTimerInfo->nColor, Buffer, nSize);
|
||||
@@ -2599,9 +2599,9 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
|
||||
nOffsetY = nOffsetYBase;
|
||||
float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? pTimeMax : pTimeAvg;
|
||||
const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? "Max" : "Avg";
|
||||
MicroProfileDrawText(nMaxOffsetX, nOffsetY, (uint32_t)-1, pString, static_cast<uint32_t>(strlen(pString)));
|
||||
MicroProfileDrawText(nMaxOffsetX, nOffsetY, UINT32_MAX, pString, static_cast<uint32_t>(strlen(pString)));
|
||||
int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference);
|
||||
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, (uint32_t)-1, Buffer, nSize);
|
||||
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, UINT32_MAX, Buffer, nSize);
|
||||
for(uint32_t i = 0; i < nCount; ++i)
|
||||
{
|
||||
nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT);
|
||||
@@ -2613,9 +2613,9 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
|
||||
{
|
||||
nOffsetY += 2*(1+MICROPROFILE_TEXT_HEIGHT);
|
||||
const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? "Max" : "Avg";
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING, nOffsetY, (uint32_t)-1, pString, static_cast<uint32_t>(strlen(pString)));
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING, nOffsetY, UINT32_MAX, pString, static_cast<uint32_t>(strlen(pString)));
|
||||
int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference);
|
||||
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, (uint32_t)-1, Buffer, nSize);
|
||||
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, UINT32_MAX, Buffer, nSize);
|
||||
nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT);
|
||||
float fPosX = MICROPROFILE_CUSTOM_PADDING;
|
||||
float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? pTimeMax : pTimeAvg;
|
||||
@@ -2668,7 +2668,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
|
||||
UI.nHoverTime = 0;
|
||||
UI.nHoverFrame = -1;
|
||||
if(S.nDisplay != MP_DRAW_DETAILED)
|
||||
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = -1;
|
||||
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = UINT32_MAX;
|
||||
MicroProfileMoveGraph();
|
||||
|
||||
|
||||
@@ -2798,13 +2798,13 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
|
||||
|
||||
|
||||
|
||||
if(UI.nActiveMenu == -1 && !bMouseOverGraph)
|
||||
if(UI.nActiveMenu == UINT32_MAX && !bMouseOverGraph)
|
||||
{
|
||||
if(UI.nHoverToken != MICROPROFILE_INVALID_TOKEN)
|
||||
{
|
||||
MicroProfileDrawFloatTooltip(UI.nMouseX, UI.nMouseY, UI.nHoverToken, UI.nHoverTime);
|
||||
}
|
||||
else if(S.nContextSwitchHoverThreadAfter != -1 && S.nContextSwitchHoverThreadBefore != -1)
|
||||
else if(S.nContextSwitchHoverThreadAfter != UINT32_MAX && S.nContextSwitchHoverThreadBefore != UINT32_MAX)
|
||||
{
|
||||
float fToMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu());
|
||||
MicroProfileStringArray ToolTip;
|
||||
@@ -2820,7 +2820,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
|
||||
MicroProfileStringArrayFormat(&ToolTip, "%6.2fms", fToMs * nDifference );
|
||||
MicroProfileStringArrayAddLiteral(&ToolTip, "CPU");
|
||||
MicroProfileStringArrayFormat(&ToolTip, "%d", S.nContextSwitchHoverCpu);
|
||||
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, -1);
|
||||
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, UINT32_MAX);
|
||||
|
||||
|
||||
}
|
||||
@@ -2858,7 +2858,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, -1);
|
||||
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, UINT32_MAX);
|
||||
}
|
||||
if(UI.nMouseLeft)
|
||||
{
|
||||
@@ -2883,7 +2883,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
|
||||
#endif
|
||||
m.unlock();
|
||||
}
|
||||
else if(UI.nCustomActive != (uint32_t)-1)
|
||||
else if(UI.nCustomActive != UINT32_MAX)
|
||||
{
|
||||
std::recursive_mutex& m = MicroProfileGetMutex();
|
||||
m.lock();
|
||||
@@ -3179,7 +3179,7 @@ void MicroProfileLoadPreset(const char* pSuffix)
|
||||
{
|
||||
if(0 == MP_STRCASECMP(pGroupName, S.GroupInfo[j].pName))
|
||||
{
|
||||
S.nActiveGroupWanted |= (1ll << j);
|
||||
S.nActiveGroupWanted |= (1ULL << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3212,7 +3212,7 @@ void MicroProfileLoadPreset(const char* pSuffix)
|
||||
uint64_t nGroupIndex = S.TimerInfo[j].nGroupIndex;
|
||||
if(0 == MP_STRCASECMP(pGraphName, S.TimerInfo[j].pName) && 0 == MP_STRCASECMP(pGraphGroupName, S.GroupInfo[nGroupIndex].pName))
|
||||
{
|
||||
MicroProfileToken nToken = MicroProfileMakeToken(1ll << nGroupIndex, (uint16_t)j);
|
||||
MicroProfileToken nToken = MicroProfileMakeToken(1ULL << nGroupIndex, (uint16_t)j);
|
||||
S.Graph[i].nToken = nToken; // note: group index is stored here but is checked without in MicroProfileToggleGraph()!
|
||||
S.TimerInfo[j].bGraph = true;
|
||||
if(nToken != nPrevToken)
|
||||
@@ -3235,7 +3235,7 @@ inline uint32_t MicroProfileCustomGroupFind(const char* pCustomName)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return (uint32_t)-1;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
inline uint32_t MicroProfileCustomGroup(const char* pCustomName)
|
||||
@@ -3251,7 +3251,7 @@ inline uint32_t MicroProfileCustomGroup(const char* pCustomName)
|
||||
uint32_t nIndex = UI.nCustomCount;
|
||||
UI.nCustomCount++;
|
||||
memset(&UI.Custom[nIndex], 0, sizeof(UI.Custom[nIndex]));
|
||||
uint32_t nLen = (uint32_t)strlen(pCustomName);
|
||||
size_t nLen = strlen(pCustomName);
|
||||
if(nLen > MICROPROFILE_NAME_MAX_LEN-1)
|
||||
nLen = MICROPROFILE_NAME_MAX_LEN-1;
|
||||
memcpy(&UI.Custom[nIndex].pName[0], pCustomName, nLen);
|
||||
@@ -3309,7 +3309,7 @@ inline void MicroProfileCustomGroupEnable(uint32_t nIndex)
|
||||
void MicroProfileCustomGroupToggle(const char* pCustomName)
|
||||
{
|
||||
uint32_t nIndex = MicroProfileCustomGroupFind(pCustomName);
|
||||
if(nIndex == (uint32_t)-1 || nIndex == UI.nCustomActive)
|
||||
if(nIndex == UINT32_MAX || nIndex == UI.nCustomActive)
|
||||
{
|
||||
MicroProfileCustomGroupDisable();
|
||||
}
|
||||
@@ -3328,13 +3328,13 @@ void MicroProfileCustomGroupDisable()
|
||||
{
|
||||
MicroProfile& S = *MicroProfileGet();
|
||||
S.nForceGroupUI = 0;
|
||||
UI.nCustomActive = (uint32_t)-1;
|
||||
UI.nCustomActive = UINT32_MAX;
|
||||
}
|
||||
|
||||
void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup, const char* pTimer)
|
||||
{
|
||||
uint32_t nIndex = MicroProfileCustomGroupFind(pCustomName);
|
||||
if((uint32_t)-1 == nIndex)
|
||||
if(UINT32_MAX == nIndex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -3344,7 +3344,7 @@ void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup
|
||||
MP_ASSERT(nToken != MICROPROFILE_INVALID_TOKEN); //Timer must be registered first.
|
||||
UI.Custom[nIndex].pTimers[nTimerIndex] = nToken;
|
||||
uint16_t nGroup = MicroProfileGetGroupIndex(nToken);
|
||||
UI.Custom[nIndex].nGroupMask |= (1ll << nGroup);
|
||||
UI.Custom[nIndex].nGroupMask |= (1ULL << nGroup);
|
||||
UI.Custom[nIndex].nNumTimers++;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "common/swap.h"
|
||||
#include "common/vector_math.h"
|
||||
|
||||
namespace Color {
|
||||
namespace Common::Color {
|
||||
|
||||
/// Convert a 1-bit color component to 8 bit
|
||||
[[nodiscard]] constexpr u8 Convert1To8(u8 value) {
|
||||
@@ -268,4 +268,4 @@ inline void EncodeX24S8(u8 stencil, u8* bytes) {
|
||||
bytes[3] = stencil;
|
||||
}
|
||||
|
||||
} // namespace Color
|
||||
} // namespace Common::Color
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
explicit ParamPackage(const std::string& serialized);
|
||||
ParamPackage(std::initializer_list<DataType::value_type> list);
|
||||
ParamPackage(const ParamPackage& other) = default;
|
||||
ParamPackage(ParamPackage&& other) = default;
|
||||
ParamPackage(ParamPackage&& other) noexcept = default;
|
||||
|
||||
ParamPackage& operator=(const ParamPackage& other) = default;
|
||||
ParamPackage& operator=(ParamPackage&& other) = default;
|
||||
|
||||
@@ -41,9 +41,9 @@ void CpuManager::Shutdown() {
|
||||
running_mode = false;
|
||||
Pause(false);
|
||||
if (is_multicore) {
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
core_data[core].host_thread->join();
|
||||
core_data[core].host_thread.reset();
|
||||
for (auto& data : core_data) {
|
||||
data.host_thread->join();
|
||||
data.host_thread.reset();
|
||||
}
|
||||
} else {
|
||||
core_data[0].host_thread->join();
|
||||
@@ -166,25 +166,23 @@ void CpuManager::MultiCorePause(bool paused) {
|
||||
bool all_not_barrier = false;
|
||||
while (!all_not_barrier) {
|
||||
all_not_barrier = true;
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
all_not_barrier &=
|
||||
!core_data[core].is_running.load() && core_data[core].initialized.load();
|
||||
for (const auto& data : core_data) {
|
||||
all_not_barrier &= !data.is_running.load() && data.initialized.load();
|
||||
}
|
||||
}
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
core_data[core].enter_barrier->Set();
|
||||
for (auto& data : core_data) {
|
||||
data.enter_barrier->Set();
|
||||
}
|
||||
if (paused_state.load()) {
|
||||
bool all_barrier = false;
|
||||
while (!all_barrier) {
|
||||
all_barrier = true;
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
all_barrier &=
|
||||
core_data[core].is_paused.load() && core_data[core].initialized.load();
|
||||
for (const auto& data : core_data) {
|
||||
all_barrier &= data.is_paused.load() && data.initialized.load();
|
||||
}
|
||||
}
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
core_data[core].exit_barrier->Set();
|
||||
for (auto& data : core_data) {
|
||||
data.exit_barrier->Set();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -192,9 +190,8 @@ void CpuManager::MultiCorePause(bool paused) {
|
||||
bool all_barrier = false;
|
||||
while (!all_barrier) {
|
||||
all_barrier = true;
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
all_barrier &=
|
||||
core_data[core].is_paused.load() && core_data[core].initialized.load();
|
||||
for (const auto& data : core_data) {
|
||||
all_barrier &= data.is_paused.load() && data.initialized.load();
|
||||
}
|
||||
}
|
||||
/// Don't release the barrier
|
||||
|
||||
@@ -257,8 +257,7 @@ std::vector<NcaID> PlaceholderCache::List() const {
|
||||
for (const auto& sdir : dir->GetSubdirectories()) {
|
||||
for (const auto& file : sdir->GetFiles()) {
|
||||
const auto name = file->GetName();
|
||||
if (name.length() == 36 && name[32] == '.' && name[33] == 'n' && name[34] == 'c' &&
|
||||
name[35] == 'a') {
|
||||
if (name.length() == 36 && name.ends_with(".nca")) {
|
||||
out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32)));
|
||||
}
|
||||
}
|
||||
@@ -621,25 +620,25 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
|
||||
|
||||
InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
|
||||
bool overwrite_if_exists, const VfsCopyFunction& copy) {
|
||||
CNMTHeader header{
|
||||
nca.GetTitleId(), // Title ID
|
||||
0, // Ignore/Default title version
|
||||
type, // Type
|
||||
{}, // Padding
|
||||
0x10, // Default table offset
|
||||
1, // 1 Content Entry
|
||||
0, // No Meta Entries
|
||||
{}, // Padding
|
||||
{}, // Reserved 1
|
||||
0, // Is committed
|
||||
0, // Required download system version
|
||||
{}, // Reserved 2
|
||||
const CNMTHeader header{
|
||||
.title_id = nca.GetTitleId(),
|
||||
.title_version = 0,
|
||||
.type = type,
|
||||
.reserved = {},
|
||||
.table_offset = 0x10,
|
||||
.number_content_entries = 1,
|
||||
.number_meta_entries = 0,
|
||||
.attributes = 0,
|
||||
.reserved2 = {},
|
||||
.is_committed = 0,
|
||||
.required_download_system_version = 0,
|
||||
.reserved3 = {},
|
||||
};
|
||||
OptionalHeader opt_header{0, 0};
|
||||
const OptionalHeader opt_header{0, 0};
|
||||
ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}};
|
||||
const auto& data = nca.GetBaseFile()->ReadBytes(0x100000);
|
||||
mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0);
|
||||
memcpy(&c_rec.nca_id, &c_rec.hash, 16);
|
||||
std::memcpy(&c_rec.nca_id, &c_rec.hash, 16);
|
||||
const CNMT new_cnmt(header, opt_header, {c_rec}, {});
|
||||
if (!RawInstallYuzuMeta(new_cnmt)) {
|
||||
return InstallResult::ErrorMetaFailed;
|
||||
|
||||
@@ -24,6 +24,7 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
|
||||
constexpr std::size_t NPAD_OFFSET = 0x9A00;
|
||||
constexpr u32 BATTERY_FULL = 2;
|
||||
constexpr u32 MAX_NPAD_ID = 7;
|
||||
constexpr std::size_t HANDHELD_INDEX = 8;
|
||||
constexpr std::array<u32, 10> npad_id_list{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN,
|
||||
};
|
||||
@@ -33,19 +34,41 @@ enum class JoystickId : std::size_t {
|
||||
Joystick_Right,
|
||||
};
|
||||
|
||||
static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type) {
|
||||
Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad(
|
||||
Settings::ControllerType type) {
|
||||
switch (type) {
|
||||
case Settings::ControllerType::ProController:
|
||||
return Controller_NPad::NPadControllerType::ProController;
|
||||
case Settings::ControllerType::DualJoycon:
|
||||
return Controller_NPad::NPadControllerType::JoyDual;
|
||||
return NPadControllerType::ProController;
|
||||
case Settings::ControllerType::DualJoyconDetached:
|
||||
return NPadControllerType::JoyDual;
|
||||
case Settings::ControllerType::LeftJoycon:
|
||||
return Controller_NPad::NPadControllerType::JoyLeft;
|
||||
return NPadControllerType::JoyLeft;
|
||||
case Settings::ControllerType::RightJoycon:
|
||||
return Controller_NPad::NPadControllerType::JoyRight;
|
||||
return NPadControllerType::JoyRight;
|
||||
case Settings::ControllerType::Handheld:
|
||||
return NPadControllerType::Handheld;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Controller_NPad::NPadControllerType::JoyDual;
|
||||
return NPadControllerType::ProController;
|
||||
}
|
||||
}
|
||||
|
||||
Settings::ControllerType Controller_NPad::MapNPadToSettingsType(
|
||||
Controller_NPad::NPadControllerType type) {
|
||||
switch (type) {
|
||||
case NPadControllerType::ProController:
|
||||
return Settings::ControllerType::ProController;
|
||||
case NPadControllerType::JoyDual:
|
||||
return Settings::ControllerType::DualJoyconDetached;
|
||||
case NPadControllerType::JoyLeft:
|
||||
return Settings::ControllerType::LeftJoycon;
|
||||
case NPadControllerType::JoyRight:
|
||||
return Settings::ControllerType::RightJoycon;
|
||||
case NPadControllerType::Handheld:
|
||||
return Settings::ControllerType::Handheld;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Settings::ControllerType::ProController;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,9 +83,9 @@ std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) {
|
||||
case 6:
|
||||
case 7:
|
||||
return npad_id;
|
||||
case 8:
|
||||
case HANDHELD_INDEX:
|
||||
case NPAD_HANDHELD:
|
||||
return 8;
|
||||
return HANDHELD_INDEX;
|
||||
case 9:
|
||||
case NPAD_UNKNOWN:
|
||||
return 9;
|
||||
@@ -83,7 +106,7 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) {
|
||||
case 6:
|
||||
case 7:
|
||||
return static_cast<u32>(index);
|
||||
case 8:
|
||||
case HANDHELD_INDEX:
|
||||
return NPAD_HANDHELD;
|
||||
case 9:
|
||||
return NPAD_UNKNOWN;
|
||||
@@ -96,25 +119,35 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) {
|
||||
Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {}
|
||||
Controller_NPad::~Controller_NPad() = default;
|
||||
|
||||
void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
|
||||
void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
|
||||
const auto controller_type = connected_controllers[controller_idx].type;
|
||||
auto& controller = shared_memory_entries[controller_idx];
|
||||
if (controller_type == NPadControllerType::None) {
|
||||
styleset_changed_events[controller_idx].writable->Signal();
|
||||
return;
|
||||
}
|
||||
controller.joy_styles.raw = 0; // Zero out
|
||||
controller.device_type.raw = 0;
|
||||
controller.properties.raw = 0;
|
||||
switch (controller_type) {
|
||||
case NPadControllerType::None:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case NPadControllerType::Handheld:
|
||||
controller.joy_styles.handheld.Assign(1);
|
||||
controller.device_type.handheld.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Dual;
|
||||
case NPadControllerType::ProController:
|
||||
controller.joy_styles.pro_controller.Assign(1);
|
||||
controller.device_type.pro_controller.Assign(1);
|
||||
controller.properties.is_vertical.Assign(1);
|
||||
controller.properties.use_plus.Assign(1);
|
||||
controller.properties.use_minus.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Single;
|
||||
break;
|
||||
case NPadControllerType::Handheld:
|
||||
controller.joy_styles.handheld.Assign(1);
|
||||
controller.device_type.handheld.Assign(1);
|
||||
controller.properties.is_vertical.Assign(1);
|
||||
controller.properties.use_plus.Assign(1);
|
||||
controller.properties.use_minus.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Dual;
|
||||
break;
|
||||
case NPadControllerType::JoyDual:
|
||||
controller.joy_styles.joycon_dual.Assign(1);
|
||||
@@ -144,14 +177,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
|
||||
controller.device_type.pokeball.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Single;
|
||||
break;
|
||||
case NPadControllerType::ProController:
|
||||
controller.joy_styles.pro_controller.Assign(1);
|
||||
controller.device_type.pro_controller.Assign(1);
|
||||
controller.properties.is_vertical.Assign(1);
|
||||
controller.properties.use_plus.Assign(1);
|
||||
controller.properties.use_minus.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Single;
|
||||
break;
|
||||
}
|
||||
|
||||
controller.single_color_error = ColorReadError::ReadOk;
|
||||
@@ -192,36 +217,25 @@ void Controller_NPad::OnInit() {
|
||||
style.pokeball.Assign(1);
|
||||
}
|
||||
|
||||
std::transform(
|
||||
Settings::values.players.begin(), Settings::values.players.end(),
|
||||
connected_controllers.begin(), [](const Settings::PlayerInput& player) {
|
||||
return ControllerHolder{MapSettingsTypeToNPad(player.type), player.connected};
|
||||
});
|
||||
|
||||
std::stable_partition(connected_controllers.begin(), connected_controllers.begin() + 8,
|
||||
[](const ControllerHolder& holder) { return holder.is_connected; });
|
||||
std::transform(Settings::values.players.begin(), Settings::values.players.end(),
|
||||
connected_controllers.begin(), [](const Settings::PlayerInput& player) {
|
||||
return ControllerHolder{MapSettingsTypeToNPad(player.controller_type),
|
||||
player.connected};
|
||||
});
|
||||
|
||||
// Account for handheld
|
||||
if (connected_controllers[8].is_connected)
|
||||
connected_controllers[8].type = NPadControllerType::Handheld;
|
||||
if (connected_controllers[HANDHELD_INDEX].is_connected) {
|
||||
connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld;
|
||||
}
|
||||
|
||||
supported_npad_id_types.resize(npad_id_list.size());
|
||||
std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
|
||||
npad_id_list.size() * sizeof(u32));
|
||||
|
||||
// Add a default dual joycon controller if none are present.
|
||||
if (std::none_of(connected_controllers.begin(), connected_controllers.end(),
|
||||
[](const ControllerHolder& controller) { return controller.is_connected; })) {
|
||||
supported_npad_id_types.resize(npad_id_list.size());
|
||||
std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
|
||||
npad_id_list.size() * sizeof(u32));
|
||||
AddNewController(NPadControllerType::JoyDual);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < connected_controllers.size(); ++i) {
|
||||
const auto& controller = connected_controllers[i];
|
||||
if (controller.is_connected) {
|
||||
AddNewControllerAt(controller.type, IndexToNPad(i));
|
||||
AddNewControllerAt(controller.type, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,8 +323,9 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
|
||||
|
||||
void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t data_len) {
|
||||
if (!IsControllerActivated())
|
||||
if (!IsControllerActivated()) {
|
||||
return;
|
||||
}
|
||||
for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
|
||||
auto& npad = shared_memory_entries[i];
|
||||
const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states,
|
||||
@@ -360,13 +375,25 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
|
||||
|
||||
libnx_entry.connection_status.raw = 0;
|
||||
libnx_entry.connection_status.IsConnected.Assign(1);
|
||||
|
||||
switch (controller_type) {
|
||||
case NPadControllerType::None:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case NPadControllerType::ProController:
|
||||
main_controller.connection_status.raw = 0;
|
||||
main_controller.connection_status.IsConnected.Assign(1);
|
||||
main_controller.connection_status.IsWired.Assign(1);
|
||||
main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
main_controller.pad.l_stick = pad_state.l_stick;
|
||||
main_controller.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsWired.Assign(1);
|
||||
break;
|
||||
case NPadControllerType::Handheld:
|
||||
handheld_entry.connection_status.raw = 0;
|
||||
handheld_entry.connection_status.IsConnected.Assign(1);
|
||||
handheld_entry.connection_status.IsWired.Assign(1);
|
||||
handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
@@ -375,57 +402,52 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
handheld_entry.pad.l_stick = pad_state.l_stick;
|
||||
handheld_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsWired.Assign(1);
|
||||
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsLeftJoyWired.Assign(1);
|
||||
libnx_entry.connection_status.IsRightJoyWired.Assign(1);
|
||||
break;
|
||||
case NPadControllerType::JoyDual:
|
||||
dual_entry.connection_status.raw = 0;
|
||||
|
||||
dual_entry.connection_status.IsConnected.Assign(1);
|
||||
dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
dual_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
dual_entry.connection_status.IsConnected.Assign(1);
|
||||
|
||||
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsConnected.Assign(1);
|
||||
|
||||
dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
dual_entry.pad.l_stick = pad_state.l_stick;
|
||||
dual_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
break;
|
||||
case NPadControllerType::JoyLeft:
|
||||
left_entry.connection_status.raw = 0;
|
||||
|
||||
left_entry.connection_status.IsConnected.Assign(1);
|
||||
left_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
left_entry.pad.l_stick = pad_state.l_stick;
|
||||
left_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
break;
|
||||
case NPadControllerType::JoyRight:
|
||||
right_entry.connection_status.raw = 0;
|
||||
|
||||
right_entry.connection_status.IsConnected.Assign(1);
|
||||
right_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
right_entry.pad.l_stick = pad_state.l_stick;
|
||||
right_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
break;
|
||||
case NPadControllerType::Pokeball:
|
||||
pokeball_entry.connection_status.raw = 0;
|
||||
|
||||
pokeball_entry.connection_status.IsConnected.Assign(1);
|
||||
pokeball_entry.connection_status.IsWired.Assign(1);
|
||||
|
||||
pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
pokeball_entry.pad.l_stick = pad_state.l_stick;
|
||||
pokeball_entry.pad.r_stick = pad_state.r_stick;
|
||||
break;
|
||||
case NPadControllerType::ProController:
|
||||
main_controller.connection_status.raw = 0;
|
||||
|
||||
main_controller.connection_status.IsConnected.Assign(1);
|
||||
main_controller.connection_status.IsWired.Assign(1);
|
||||
main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
main_controller.pad.l_stick = pad_state.l_stick;
|
||||
main_controller.pad.r_stick = pad_state.r_stick;
|
||||
break;
|
||||
}
|
||||
|
||||
// LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
|
||||
@@ -453,26 +475,6 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
|
||||
supported_npad_id_types.clear();
|
||||
supported_npad_id_types.resize(length / sizeof(u32));
|
||||
std::memcpy(supported_npad_id_types.data(), data, length);
|
||||
for (std::size_t i = 0; i < connected_controllers.size(); i++) {
|
||||
auto& controller = connected_controllers[i];
|
||||
if (!controller.is_connected) {
|
||||
continue;
|
||||
}
|
||||
const auto requested_controller =
|
||||
i <= MAX_NPAD_ID ? MapSettingsTypeToNPad(Settings::values.players[i].type)
|
||||
: NPadControllerType::Handheld;
|
||||
if (!IsControllerSupported(requested_controller)) {
|
||||
const auto is_handheld = requested_controller == NPadControllerType::Handheld;
|
||||
if (is_handheld) {
|
||||
controller.type = NPadControllerType::None;
|
||||
controller.is_connected = false;
|
||||
AddNewController(requested_controller);
|
||||
} else {
|
||||
controller.type = requested_controller;
|
||||
InitNewlyAddedControler(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
|
||||
@@ -504,7 +506,7 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
|
||||
const std::vector<Vibration>& vibrations) {
|
||||
LOG_DEBUG(Service_HID, "(STUBBED) called");
|
||||
|
||||
if (!can_controllers_vibrate) {
|
||||
if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
|
||||
return;
|
||||
}
|
||||
for (std::size_t i = 0; i < controller_ids.size(); i++) {
|
||||
@@ -517,8 +519,6 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
|
||||
}
|
||||
|
||||
std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
|
||||
// TODO(ogniK): Figure out the best time to signal this event. This event seems that it should
|
||||
// be signalled at least once, and signaled after a new controller is connected?
|
||||
const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
|
||||
return styleset_event.readable;
|
||||
}
|
||||
@@ -527,43 +527,43 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
|
||||
return last_processed_vibration;
|
||||
}
|
||||
|
||||
void Controller_NPad::AddNewController(NPadControllerType controller) {
|
||||
controller = DecideBestController(controller);
|
||||
if (controller == NPadControllerType::Handheld) {
|
||||
connected_controllers[8] = {controller, true};
|
||||
InitNewlyAddedControler(8);
|
||||
return;
|
||||
}
|
||||
const auto pos =
|
||||
std::find_if(connected_controllers.begin(), connected_controllers.end() - 2,
|
||||
[](const ControllerHolder& holder) { return !holder.is_connected; });
|
||||
if (pos == connected_controllers.end() - 2) {
|
||||
LOG_ERROR(Service_HID, "Cannot connect any more controllers!");
|
||||
return;
|
||||
}
|
||||
const auto controller_id = std::distance(connected_controllers.begin(), pos);
|
||||
connected_controllers[controller_id] = {controller, true};
|
||||
InitNewlyAddedControler(controller_id);
|
||||
void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {
|
||||
UpdateControllerAt(controller, npad_index, true);
|
||||
}
|
||||
|
||||
void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) {
|
||||
controller = DecideBestController(controller);
|
||||
if (controller == NPadControllerType::Handheld) {
|
||||
connected_controllers[NPadIdToIndex(NPAD_HANDHELD)] = {controller, true};
|
||||
InitNewlyAddedControler(NPadIdToIndex(NPAD_HANDHELD));
|
||||
void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index,
|
||||
bool connected) {
|
||||
if (!connected) {
|
||||
DisconnectNPad(IndexToNPad(npad_index));
|
||||
return;
|
||||
}
|
||||
|
||||
connected_controllers[NPadIdToIndex(npad_id)] = {controller, true};
|
||||
InitNewlyAddedControler(NPadIdToIndex(npad_id));
|
||||
}
|
||||
if (controller == NPadControllerType::Handheld) {
|
||||
Settings::values.players[HANDHELD_INDEX].controller_type =
|
||||
MapNPadToSettingsType(controller);
|
||||
Settings::values.players[HANDHELD_INDEX].connected = true;
|
||||
connected_controllers[HANDHELD_INDEX] = {controller, true};
|
||||
InitNewlyAddedController(HANDHELD_INDEX);
|
||||
return;
|
||||
}
|
||||
|
||||
void Controller_NPad::ConnectNPad(u32 npad_id) {
|
||||
connected_controllers[NPadIdToIndex(npad_id)].is_connected = true;
|
||||
Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller);
|
||||
Settings::values.players[npad_index].connected = true;
|
||||
connected_controllers[npad_index] = {controller, true};
|
||||
InitNewlyAddedController(npad_index);
|
||||
}
|
||||
|
||||
void Controller_NPad::DisconnectNPad(u32 npad_id) {
|
||||
connected_controllers[NPadIdToIndex(npad_id)].is_connected = false;
|
||||
const auto npad_index = NPadIdToIndex(npad_id);
|
||||
connected_controllers[npad_index].is_connected = false;
|
||||
Settings::values.players[npad_index].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();
|
||||
}
|
||||
|
||||
void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) {
|
||||
@@ -599,8 +599,8 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
|
||||
|
||||
std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type);
|
||||
|
||||
InitNewlyAddedControler(npad_index_1);
|
||||
InitNewlyAddedControler(npad_index_2);
|
||||
AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1);
|
||||
AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -614,11 +614,11 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
|
||||
case 0:
|
||||
return LedPattern{1, 0, 0, 0};
|
||||
case 1:
|
||||
return LedPattern{0, 1, 0, 0};
|
||||
return LedPattern{1, 1, 0, 0};
|
||||
case 2:
|
||||
return LedPattern{0, 0, 1, 0};
|
||||
return LedPattern{1, 1, 1, 0};
|
||||
case 3:
|
||||
return LedPattern{0, 0, 0, 1};
|
||||
return LedPattern{1, 1, 1, 1};
|
||||
case 4:
|
||||
return LedPattern{1, 0, 0, 1};
|
||||
case 5:
|
||||
@@ -628,7 +628,6 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
|
||||
case 7:
|
||||
return LedPattern{0, 1, 1, 0};
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id);
|
||||
return LedPattern{0, 0, 0, 0};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,10 +118,11 @@ public:
|
||||
std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
|
||||
Vibration GetLastVibration() const;
|
||||
|
||||
void AddNewController(NPadControllerType controller);
|
||||
void AddNewControllerAt(NPadControllerType controller, u32 npad_id);
|
||||
// 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 ConnectNPad(u32 npad_id);
|
||||
void DisconnectNPad(u32 npad_id);
|
||||
void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode);
|
||||
GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const;
|
||||
@@ -141,6 +142,8 @@ public:
|
||||
// Specifically for cheat engine and other features.
|
||||
u32 GetAndResetPressState();
|
||||
|
||||
static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type);
|
||||
static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type);
|
||||
static std::size_t NPadIdToIndex(u32 npad_id);
|
||||
static u32 IndexToNPad(std::size_t index);
|
||||
|
||||
@@ -309,7 +312,7 @@ private:
|
||||
bool is_connected;
|
||||
};
|
||||
|
||||
void InitNewlyAddedControler(std::size_t controller_idx);
|
||||
void InitNewlyAddedController(std::size_t controller_idx);
|
||||
bool IsControllerSupported(NPadControllerType controller) const;
|
||||
NPadControllerType DecideBestController(NPadControllerType priority) const;
|
||||
void RequestPadStateUpdate(u32 npad_id);
|
||||
|
||||
@@ -38,11 +38,9 @@
|
||||
namespace Service::HID {
|
||||
|
||||
// Updating period for each HID device.
|
||||
// TODO(ogniK): Find actual polling rate of hid
|
||||
constexpr auto pad_update_ns = std::chrono::nanoseconds{1000000000 / 66};
|
||||
[[maybe_unused]] constexpr auto accelerometer_update_ns =
|
||||
std::chrono::nanoseconds{1000000000 / 100};
|
||||
[[maybe_unused]] constexpr auto gyroscope_update_ticks = std::chrono::nanoseconds{1000000000 / 100};
|
||||
// HID is polled every 15ms, this value was derived from
|
||||
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet
|
||||
constexpr auto pad_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.6Hz)
|
||||
constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
|
||||
|
||||
IAppletResource::IAppletResource(Core::System& system)
|
||||
@@ -845,8 +843,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
|
||||
void Hid::PermitVibration(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto can_vibrate{rp.Pop<bool>()};
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.SetVibrationEnabled(can_vibrate);
|
||||
Settings::values.vibration_enabled = can_vibrate;
|
||||
|
||||
LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
|
||||
|
||||
@@ -859,8 +856,7 @@ void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad).IsVibrationEnabled());
|
||||
rb.Push(Settings::values.vibration_enabled);
|
||||
}
|
||||
|
||||
void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
@@ -13,56 +13,6 @@
|
||||
|
||||
namespace Settings {
|
||||
|
||||
namespace NativeButton {
|
||||
const std::array<const char*, NumButtons> mapping = {{
|
||||
"button_a",
|
||||
"button_b",
|
||||
"button_x",
|
||||
"button_y",
|
||||
"button_lstick",
|
||||
"button_rstick",
|
||||
"button_l",
|
||||
"button_r",
|
||||
"button_zl",
|
||||
"button_zr",
|
||||
"button_plus",
|
||||
"button_minus",
|
||||
"button_dleft",
|
||||
"button_dup",
|
||||
"button_dright",
|
||||
"button_ddown",
|
||||
"button_lstick_left",
|
||||
"button_lstick_up",
|
||||
"button_lstick_right",
|
||||
"button_lstick_down",
|
||||
"button_rstick_left",
|
||||
"button_rstick_up",
|
||||
"button_rstick_right",
|
||||
"button_rstick_down",
|
||||
"button_sl",
|
||||
"button_sr",
|
||||
"button_home",
|
||||
"button_screenshot",
|
||||
}};
|
||||
}
|
||||
|
||||
namespace NativeAnalog {
|
||||
const std::array<const char*, NumAnalogs> mapping = {{
|
||||
"lstick",
|
||||
"rstick",
|
||||
}};
|
||||
}
|
||||
|
||||
namespace NativeMouseButton {
|
||||
const std::array<const char*, NumMouseButtons> mapping = {{
|
||||
"left",
|
||||
"right",
|
||||
"middle",
|
||||
"forward",
|
||||
"back",
|
||||
}};
|
||||
}
|
||||
|
||||
Values values = {};
|
||||
bool configuring_global = true;
|
||||
|
||||
|
||||
@@ -12,340 +12,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
#include "input_common/settings.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
namespace NativeButton {
|
||||
enum Values {
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
LStick,
|
||||
RStick,
|
||||
L,
|
||||
R,
|
||||
ZL,
|
||||
ZR,
|
||||
Plus,
|
||||
Minus,
|
||||
|
||||
DLeft,
|
||||
DUp,
|
||||
DRight,
|
||||
DDown,
|
||||
|
||||
LStick_Left,
|
||||
LStick_Up,
|
||||
LStick_Right,
|
||||
LStick_Down,
|
||||
|
||||
RStick_Left,
|
||||
RStick_Up,
|
||||
RStick_Right,
|
||||
RStick_Down,
|
||||
|
||||
SL,
|
||||
SR,
|
||||
|
||||
Home,
|
||||
Screenshot,
|
||||
|
||||
NumButtons,
|
||||
};
|
||||
|
||||
constexpr int BUTTON_HID_BEGIN = A;
|
||||
constexpr int BUTTON_NS_BEGIN = Home;
|
||||
|
||||
constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN;
|
||||
constexpr int BUTTON_NS_END = NumButtons;
|
||||
|
||||
constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN;
|
||||
constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN;
|
||||
|
||||
extern const std::array<const char*, NumButtons> mapping;
|
||||
|
||||
} // namespace NativeButton
|
||||
|
||||
namespace NativeAnalog {
|
||||
enum Values {
|
||||
LStick,
|
||||
RStick,
|
||||
|
||||
NumAnalogs,
|
||||
};
|
||||
|
||||
constexpr int STICK_HID_BEGIN = LStick;
|
||||
constexpr int STICK_HID_END = NumAnalogs;
|
||||
constexpr int NUM_STICKS_HID = NumAnalogs;
|
||||
|
||||
extern const std::array<const char*, NumAnalogs> mapping;
|
||||
} // namespace NativeAnalog
|
||||
|
||||
namespace NativeMouseButton {
|
||||
enum Values {
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Forward,
|
||||
Back,
|
||||
|
||||
NumMouseButtons,
|
||||
};
|
||||
|
||||
constexpr int MOUSE_HID_BEGIN = Left;
|
||||
constexpr int MOUSE_HID_END = NumMouseButtons;
|
||||
constexpr int NUM_MOUSE_HID = NumMouseButtons;
|
||||
|
||||
extern const std::array<const char*, NumMouseButtons> mapping;
|
||||
} // namespace NativeMouseButton
|
||||
|
||||
namespace NativeKeyboard {
|
||||
enum Keys {
|
||||
None,
|
||||
Error,
|
||||
|
||||
A = 4,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
N1,
|
||||
N2,
|
||||
N3,
|
||||
N4,
|
||||
N5,
|
||||
N6,
|
||||
N7,
|
||||
N8,
|
||||
N9,
|
||||
N0,
|
||||
Enter,
|
||||
Escape,
|
||||
Backspace,
|
||||
Tab,
|
||||
Space,
|
||||
Minus,
|
||||
Equal,
|
||||
LeftBrace,
|
||||
RightBrace,
|
||||
Backslash,
|
||||
Tilde,
|
||||
Semicolon,
|
||||
Apostrophe,
|
||||
Grave,
|
||||
Comma,
|
||||
Dot,
|
||||
Slash,
|
||||
CapsLockKey,
|
||||
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
|
||||
SystemRequest,
|
||||
ScrollLockKey,
|
||||
Pause,
|
||||
Insert,
|
||||
Home,
|
||||
PageUp,
|
||||
Delete,
|
||||
End,
|
||||
PageDown,
|
||||
Right,
|
||||
Left,
|
||||
Down,
|
||||
Up,
|
||||
|
||||
NumLockKey,
|
||||
KPSlash,
|
||||
KPAsterisk,
|
||||
KPMinus,
|
||||
KPPlus,
|
||||
KPEnter,
|
||||
KP1,
|
||||
KP2,
|
||||
KP3,
|
||||
KP4,
|
||||
KP5,
|
||||
KP6,
|
||||
KP7,
|
||||
KP8,
|
||||
KP9,
|
||||
KP0,
|
||||
KPDot,
|
||||
|
||||
Key102,
|
||||
Compose,
|
||||
Power,
|
||||
KPEqual,
|
||||
|
||||
F13,
|
||||
F14,
|
||||
F15,
|
||||
F16,
|
||||
F17,
|
||||
F18,
|
||||
F19,
|
||||
F20,
|
||||
F21,
|
||||
F22,
|
||||
F23,
|
||||
F24,
|
||||
|
||||
Open,
|
||||
Help,
|
||||
Properties,
|
||||
Front,
|
||||
Stop,
|
||||
Repeat,
|
||||
Undo,
|
||||
Cut,
|
||||
Copy,
|
||||
Paste,
|
||||
Find,
|
||||
Mute,
|
||||
VolumeUp,
|
||||
VolumeDown,
|
||||
CapsLockActive,
|
||||
NumLockActive,
|
||||
ScrollLockActive,
|
||||
KPComma,
|
||||
|
||||
KPLeftParenthesis,
|
||||
KPRightParenthesis,
|
||||
|
||||
LeftControlKey = 0xE0,
|
||||
LeftShiftKey,
|
||||
LeftAltKey,
|
||||
LeftMetaKey,
|
||||
RightControlKey,
|
||||
RightShiftKey,
|
||||
RightAltKey,
|
||||
RightMetaKey,
|
||||
|
||||
MediaPlayPause,
|
||||
MediaStopCD,
|
||||
MediaPrevious,
|
||||
MediaNext,
|
||||
MediaEject,
|
||||
MediaVolumeUp,
|
||||
MediaVolumeDown,
|
||||
MediaMute,
|
||||
MediaWebsite,
|
||||
MediaBack,
|
||||
MediaForward,
|
||||
MediaStop,
|
||||
MediaFind,
|
||||
MediaScrollUp,
|
||||
MediaScrollDown,
|
||||
MediaEdit,
|
||||
MediaSleep,
|
||||
MediaCoffee,
|
||||
MediaRefresh,
|
||||
MediaCalculator,
|
||||
|
||||
NumKeyboardKeys,
|
||||
};
|
||||
|
||||
static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys.");
|
||||
|
||||
enum Modifiers {
|
||||
LeftControl,
|
||||
LeftShift,
|
||||
LeftAlt,
|
||||
LeftMeta,
|
||||
RightControl,
|
||||
RightShift,
|
||||
RightAlt,
|
||||
RightMeta,
|
||||
CapsLock,
|
||||
ScrollLock,
|
||||
NumLock,
|
||||
|
||||
NumKeyboardMods,
|
||||
};
|
||||
|
||||
constexpr int KEYBOARD_KEYS_HID_BEGIN = None;
|
||||
constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys;
|
||||
constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys;
|
||||
|
||||
constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl;
|
||||
constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods;
|
||||
constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
|
||||
|
||||
} // namespace NativeKeyboard
|
||||
|
||||
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
|
||||
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
|
||||
using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
|
||||
using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
|
||||
using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
|
||||
|
||||
constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
|
||||
constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
|
||||
constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6;
|
||||
constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E;
|
||||
|
||||
enum class ControllerType {
|
||||
ProController,
|
||||
DualJoycon,
|
||||
RightJoycon,
|
||||
LeftJoycon,
|
||||
};
|
||||
|
||||
struct PlayerInput {
|
||||
bool connected;
|
||||
ControllerType type;
|
||||
ButtonsRaw buttons;
|
||||
AnalogsRaw analogs;
|
||||
|
||||
u32 body_color_right;
|
||||
u32 button_color_right;
|
||||
u32 body_color_left;
|
||||
u32 button_color_left;
|
||||
};
|
||||
|
||||
struct TouchscreenInput {
|
||||
bool enabled;
|
||||
std::string device;
|
||||
|
||||
u32 finger;
|
||||
u32 diameter_x;
|
||||
u32 diameter_y;
|
||||
u32 rotation_angle;
|
||||
};
|
||||
|
||||
enum class RendererBackend {
|
||||
OpenGL = 0,
|
||||
Vulkan = 1,
|
||||
@@ -461,6 +131,8 @@ struct Values {
|
||||
// Controls
|
||||
std::array<PlayerInput, 10> players;
|
||||
|
||||
bool use_docked_mode;
|
||||
|
||||
bool mouse_enabled;
|
||||
std::string mouse_device;
|
||||
MouseButtonsRaw mouse_buttons;
|
||||
@@ -474,14 +146,15 @@ struct Values {
|
||||
AnalogsRaw debug_pad_analogs;
|
||||
|
||||
std::string motion_device;
|
||||
|
||||
bool vibration_enabled;
|
||||
|
||||
TouchscreenInput touchscreen;
|
||||
std::atomic_bool is_device_reload_pending{true};
|
||||
std::string udp_input_address;
|
||||
u16 udp_input_port;
|
||||
u8 udp_pad_index;
|
||||
|
||||
bool use_docked_mode;
|
||||
|
||||
// Data Storage
|
||||
bool use_virtual_sd;
|
||||
bool gamecard_inserted;
|
||||
|
||||
@@ -7,6 +7,8 @@ add_library(input_common STATIC
|
||||
main.h
|
||||
motion_emu.cpp
|
||||
motion_emu.h
|
||||
settings.cpp
|
||||
settings.h
|
||||
gcadapter/gc_adapter.cpp
|
||||
gcadapter/gc_adapter.h
|
||||
gcadapter/gc_poller.cpp
|
||||
|
||||
@@ -191,7 +191,7 @@ public:
|
||||
|
||||
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
|
||||
const auto [x, y] = GetStatus();
|
||||
const float directional_deadzone = 0.4f;
|
||||
const float directional_deadzone = 0.5f;
|
||||
switch (direction) {
|
||||
case Input::AnalogDirection::RIGHT:
|
||||
return x > directional_deadzone;
|
||||
@@ -232,7 +232,7 @@ std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::Param
|
||||
const int port = params.Get("port", 0);
|
||||
const int axis_x = params.Get("axis_x", 0);
|
||||
const int axis_y = params.Get("axis_y", 1);
|
||||
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f);
|
||||
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
|
||||
const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
|
||||
|
||||
return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range);
|
||||
|
||||
@@ -44,7 +44,6 @@ void Init() {
|
||||
#ifdef HAVE_SDL2
|
||||
sdl = SDL::Init();
|
||||
#endif
|
||||
|
||||
udp = CemuhookUDP::Init();
|
||||
}
|
||||
|
||||
@@ -103,6 +102,56 @@ std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left,
|
||||
return circle_pad_param.Serialize();
|
||||
}
|
||||
|
||||
std::vector<Common::ParamPackage> GetInputDevices() {
|
||||
std::vector<Common::ParamPackage> devices = {
|
||||
Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
|
||||
Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}},
|
||||
};
|
||||
#ifdef HAVE_SDL2
|
||||
auto sdl_devices = sdl->GetInputDevices();
|
||||
devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
|
||||
#endif
|
||||
auto udp_devices = udp->GetInputDevices();
|
||||
devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
|
||||
return devices;
|
||||
}
|
||||
|
||||
std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage> GetButtonMappingForDevice(
|
||||
const Common::ParamPackage& params) {
|
||||
std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage> mappings;
|
||||
if (!params.Has("class") || params.Get("class", "") == "any") {
|
||||
return {};
|
||||
}
|
||||
if (params.Get("class", "") == "key") {
|
||||
// TODO consider returning the SDL key codes for the default keybindings
|
||||
return {};
|
||||
}
|
||||
#ifdef HAVE_SDL2
|
||||
if (params.Get("class", "") == "sdl") {
|
||||
return sdl->GetButtonMappingForDevice(params);
|
||||
}
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage> GetAnalogMappingForDevice(
|
||||
const Common::ParamPackage& params) {
|
||||
std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage> mappings;
|
||||
if (!params.Has("class") || params.Get("class", "") == "any") {
|
||||
return {};
|
||||
}
|
||||
if (params.Get("class", "") == "key") {
|
||||
// TODO consider returning the SDL key codes for the default keybindings
|
||||
return {};
|
||||
}
|
||||
#ifdef HAVE_SDL2
|
||||
if (params.Get("class", "") == "sdl") {
|
||||
return sdl->GetAnalogMappingForDevice(params);
|
||||
}
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
namespace Polling {
|
||||
|
||||
std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type) {
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "input_common/gcadapter/gc_poller.h"
|
||||
#include "input_common/settings.h"
|
||||
|
||||
namespace Common {
|
||||
class ParamPackage;
|
||||
@@ -42,9 +44,27 @@ std::string GenerateKeyboardParam(int key_code);
|
||||
std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
|
||||
int key_modifier, float modifier_scale);
|
||||
|
||||
/**
|
||||
* Return a list of available input devices that this Factory can create a new device with.
|
||||
* Each returned Parampackage should have a `display` field used for display, a class field for
|
||||
* backends to determine if this backend is meant to service the request and any other information
|
||||
* needed to identify this in the backend later.
|
||||
*/
|
||||
std::vector<Common::ParamPackage> GetInputDevices();
|
||||
|
||||
/**
|
||||
* Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default
|
||||
* mapping for the device. This is currently only implemented for the sdl backend devices.
|
||||
*/
|
||||
using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>;
|
||||
using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>;
|
||||
|
||||
ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage&);
|
||||
AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&);
|
||||
|
||||
namespace Polling {
|
||||
|
||||
enum class DeviceType { Button, Analog };
|
||||
enum class DeviceType { Button, AnalogPreferred };
|
||||
|
||||
/**
|
||||
* A class that can be used to get inputs from an input device like controllers without having to
|
||||
@@ -54,7 +74,9 @@ class DevicePoller {
|
||||
public:
|
||||
virtual ~DevicePoller() = default;
|
||||
/// Setup and start polling for inputs, should be called before GetNextInput
|
||||
virtual void Start() = 0;
|
||||
/// If a device_id is provided, events should be filtered to only include events from this
|
||||
/// device id
|
||||
virtual void Start(const std::string& device_id = "") = 0;
|
||||
/// Stop polling
|
||||
virtual void Stop() = 0;
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "common/param_package.h"
|
||||
#include "input_common/main.h"
|
||||
|
||||
namespace InputCommon::Polling {
|
||||
@@ -22,14 +23,24 @@ public:
|
||||
/// Unregisters SDL device factories and shut them down.
|
||||
virtual ~State() = default;
|
||||
|
||||
virtual Pollers GetPollers(Polling::DeviceType type) = 0;
|
||||
virtual Pollers GetPollers(Polling::DeviceType type) {
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual std::vector<Common::ParamPackage> GetInputDevices() {
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage&) {
|
||||
return {};
|
||||
}
|
||||
virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
class NullState : public State {
|
||||
public:
|
||||
Pollers GetPollers(Polling::DeviceType type) override {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<State> Init();
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
@@ -23,7 +25,8 @@
|
||||
|
||||
namespace InputCommon::SDL {
|
||||
|
||||
static std::string GetGUID(SDL_Joystick* joystick) {
|
||||
namespace {
|
||||
std::string GetGUID(SDL_Joystick* joystick) {
|
||||
const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
|
||||
char guid_str[33];
|
||||
SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
|
||||
@@ -31,7 +34,8 @@ static std::string GetGUID(SDL_Joystick* joystick) {
|
||||
}
|
||||
|
||||
/// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice
|
||||
static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event);
|
||||
Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event);
|
||||
} // Anonymous namespace
|
||||
|
||||
static int SDLEventWatcher(void* user_data, SDL_Event* event) {
|
||||
auto* const sdl_state = static_cast<SDLState*>(user_data);
|
||||
@@ -48,8 +52,10 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) {
|
||||
|
||||
class SDLJoystick {
|
||||
public:
|
||||
SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick)
|
||||
: guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose} {}
|
||||
SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick,
|
||||
SDL_GameController* gamecontroller)
|
||||
: guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose},
|
||||
sdl_controller{gamecontroller, &SDL_GameControllerClose} {}
|
||||
|
||||
void SetButton(int button, bool value) {
|
||||
std::lock_guard lock{mutex};
|
||||
@@ -115,10 +121,15 @@ public:
|
||||
return sdl_joystick.get();
|
||||
}
|
||||
|
||||
void SetSDLJoystick(SDL_Joystick* joystick) {
|
||||
void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) {
|
||||
sdl_controller.reset(controller);
|
||||
sdl_joystick.reset(joystick);
|
||||
}
|
||||
|
||||
SDL_GameController* GetSDLGameController() const {
|
||||
return sdl_controller.get();
|
||||
}
|
||||
|
||||
private:
|
||||
struct State {
|
||||
std::unordered_map<int, bool> buttons;
|
||||
@@ -128,6 +139,7 @@ private:
|
||||
std::string guid;
|
||||
int port;
|
||||
std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
|
||||
std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
|
||||
mutable std::mutex mutex;
|
||||
};
|
||||
|
||||
@@ -136,18 +148,19 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& g
|
||||
const auto it = joystick_map.find(guid);
|
||||
if (it != joystick_map.end()) {
|
||||
while (it->second.size() <= static_cast<std::size_t>(port)) {
|
||||
auto joystick =
|
||||
std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), nullptr);
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()),
|
||||
nullptr, nullptr);
|
||||
it->second.emplace_back(std::move(joystick));
|
||||
}
|
||||
return it->second[port];
|
||||
}
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr);
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr);
|
||||
return joystick_map[guid].emplace_back(std::move(joystick));
|
||||
}
|
||||
|
||||
std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {
|
||||
auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);
|
||||
auto sdl_controller = SDL_GameControllerFromInstanceID(sdl_id);
|
||||
const std::string guid = GetGUID(sdl_joystick);
|
||||
|
||||
std::lock_guard lock{joystick_map_mutex};
|
||||
@@ -171,23 +184,27 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_
|
||||
});
|
||||
if (nullptr_it != map_it->second.end()) {
|
||||
// ... and map it
|
||||
(*nullptr_it)->SetSDLJoystick(sdl_joystick);
|
||||
(*nullptr_it)->SetSDLJoystick(sdl_joystick, sdl_controller);
|
||||
return *nullptr_it;
|
||||
}
|
||||
|
||||
// There is no SDLJoystick without a mapped SDL_Joystick
|
||||
// Create a new SDLJoystick
|
||||
const int port = static_cast<int>(map_it->second.size());
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick);
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_controller);
|
||||
return map_it->second.emplace_back(std::move(joystick));
|
||||
}
|
||||
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_controller);
|
||||
return joystick_map[guid].emplace_back(std::move(joystick));
|
||||
}
|
||||
|
||||
void SDLState::InitJoystick(int joystick_index) {
|
||||
SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index);
|
||||
SDL_GameController* sdl_gamecontroller = nullptr;
|
||||
if (SDL_IsGameController(joystick_index)) {
|
||||
sdl_gamecontroller = SDL_GameControllerOpen(joystick_index);
|
||||
}
|
||||
if (!sdl_joystick) {
|
||||
LOG_ERROR(Input, "failed to open joystick {}", joystick_index);
|
||||
return;
|
||||
@@ -196,7 +213,7 @@ void SDLState::InitJoystick(int joystick_index) {
|
||||
|
||||
std::lock_guard lock{joystick_map_mutex};
|
||||
if (joystick_map.find(guid) == joystick_map.end()) {
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller);
|
||||
joystick_map[guid].emplace_back(std::move(joystick));
|
||||
return;
|
||||
}
|
||||
@@ -205,11 +222,11 @@ void SDLState::InitJoystick(int joystick_index) {
|
||||
joystick_guid_list.begin(), joystick_guid_list.end(),
|
||||
[](const std::shared_ptr<SDLJoystick>& joystick) { return !joystick->GetSDLJoystick(); });
|
||||
if (it != joystick_guid_list.end()) {
|
||||
(*it)->SetSDLJoystick(sdl_joystick);
|
||||
(*it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller);
|
||||
return;
|
||||
}
|
||||
const int port = static_cast<int>(joystick_guid_list.size());
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick);
|
||||
auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller);
|
||||
joystick_guid_list.emplace_back(std::move(joystick));
|
||||
}
|
||||
|
||||
@@ -231,7 +248,7 @@ void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) {
|
||||
|
||||
// Destruct SDL_Joystick outside the lock guard because SDL can internally call the
|
||||
// event callback which locks the mutex again.
|
||||
joystick->SetSDLJoystick(nullptr);
|
||||
joystick->SetSDLJoystick(nullptr, nullptr);
|
||||
}
|
||||
|
||||
void SDLState::HandleGameControllerEvent(const SDL_Event& event) {
|
||||
@@ -346,7 +363,7 @@ public:
|
||||
|
||||
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
|
||||
const auto [x, y] = GetStatus();
|
||||
const float directional_deadzone = 0.4f;
|
||||
const float directional_deadzone = 0.5f;
|
||||
switch (direction) {
|
||||
case Input::AnalogDirection::RIGHT:
|
||||
return x > directional_deadzone;
|
||||
@@ -460,7 +477,7 @@ public:
|
||||
const int port = params.Get("port", 0);
|
||||
const int axis_x = params.Get("axis_x", 0);
|
||||
const int axis_y = params.Get("axis_y", 1);
|
||||
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f);
|
||||
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
|
||||
const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
|
||||
auto joystick = state.GetSDLJoystickByGUID(guid, port);
|
||||
|
||||
@@ -476,8 +493,10 @@ private:
|
||||
|
||||
SDLState::SDLState() {
|
||||
using namespace Input;
|
||||
RegisterFactory<ButtonDevice>("sdl", std::make_shared<SDLButtonFactory>(*this));
|
||||
RegisterFactory<AnalogDevice>("sdl", std::make_shared<SDLAnalogFactory>(*this));
|
||||
analog_factory = std::make_shared<SDLAnalogFactory>(*this);
|
||||
button_factory = std::make_shared<SDLButtonFactory>(*this);
|
||||
RegisterFactory<AnalogDevice>("sdl", analog_factory);
|
||||
RegisterFactory<ButtonDevice>("sdl", button_factory);
|
||||
|
||||
// If the frontend is going to manage the event loop, then we dont start one here
|
||||
start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK);
|
||||
@@ -485,6 +504,7 @@ SDLState::SDLState() {
|
||||
LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) {
|
||||
LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError());
|
||||
}
|
||||
@@ -497,7 +517,7 @@ SDLState::SDLState() {
|
||||
using namespace std::chrono_literals;
|
||||
while (initialized) {
|
||||
SDL_PumpEvents();
|
||||
std::this_thread::sleep_for(10ms);
|
||||
std::this_thread::sleep_for(5ms);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -523,65 +543,221 @@ SDLState::~SDLState() {
|
||||
}
|
||||
}
|
||||
|
||||
static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) {
|
||||
Common::ParamPackage params({{"engine", "sdl"}});
|
||||
std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
|
||||
std::scoped_lock lock(joystick_map_mutex);
|
||||
std::vector<Common::ParamPackage> devices;
|
||||
for (const auto& [key, value] : joystick_map) {
|
||||
for (const auto& joystick : value) {
|
||||
auto joy = joystick->GetSDLJoystick();
|
||||
if (auto controller = joystick->GetSDLGameController()) {
|
||||
std::string name =
|
||||
fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort());
|
||||
devices.emplace_back(Common::ParamPackage{
|
||||
{"class", "sdl"},
|
||||
{"display", std::move(name)},
|
||||
{"guid", joystick->GetGUID()},
|
||||
{"port", std::to_string(joystick->GetPort())},
|
||||
});
|
||||
} else if (joy) {
|
||||
std::string name = fmt::format("{} {}", SDL_JoystickName(joy), joystick->GetPort());
|
||||
devices.emplace_back(Common::ParamPackage{
|
||||
{"class", "sdl"},
|
||||
{"display", std::move(name)},
|
||||
{"guid", joystick->GetGUID()},
|
||||
{"port", std::to_string(joystick->GetPort())},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case SDL_JOYAXISMOTION: {
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
|
||||
params.Set("port", joystick->GetPort());
|
||||
params.Set("guid", joystick->GetGUID());
|
||||
params.Set("axis", event.jaxis.axis);
|
||||
if (event.jaxis.value > 0) {
|
||||
params.Set("direction", "+");
|
||||
params.Set("threshold", "0.5");
|
||||
} else {
|
||||
params.Set("direction", "-");
|
||||
params.Set("threshold", "-0.5");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_JOYBUTTONUP: {
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
|
||||
params.Set("port", joystick->GetPort());
|
||||
params.Set("guid", joystick->GetGUID());
|
||||
params.Set("button", event.jbutton.button);
|
||||
break;
|
||||
}
|
||||
case SDL_JOYHATMOTION: {
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
|
||||
params.Set("port", joystick->GetPort());
|
||||
params.Set("guid", joystick->GetGUID());
|
||||
params.Set("hat", event.jhat.hat);
|
||||
switch (event.jhat.value) {
|
||||
case SDL_HAT_UP:
|
||||
params.Set("direction", "up");
|
||||
break;
|
||||
case SDL_HAT_DOWN:
|
||||
params.Set("direction", "down");
|
||||
break;
|
||||
case SDL_HAT_LEFT:
|
||||
params.Set("direction", "left");
|
||||
break;
|
||||
case SDL_HAT_RIGHT:
|
||||
params.Set("direction", "right");
|
||||
break;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
break;
|
||||
}
|
||||
namespace {
|
||||
Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, u8 axis,
|
||||
float value = 0.1) {
|
||||
Common::ParamPackage params({{"engine", "sdl"}});
|
||||
params.Set("port", port);
|
||||
params.Set("guid", guid);
|
||||
params.Set("axis", axis);
|
||||
if (value > 0) {
|
||||
params.Set("direction", "+");
|
||||
params.Set("threshold", "0.5");
|
||||
} else {
|
||||
params.Set("direction", "-");
|
||||
params.Set("threshold", "-0.5");
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
namespace Polling {
|
||||
Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, u8 button) {
|
||||
Common::ParamPackage params({{"engine", "sdl"}});
|
||||
params.Set("port", port);
|
||||
params.Set("guid", guid);
|
||||
params.Set("button", button);
|
||||
return params;
|
||||
}
|
||||
|
||||
Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, u8 hat, u8 value) {
|
||||
Common::ParamPackage params({{"engine", "sdl"}});
|
||||
|
||||
params.Set("port", port);
|
||||
params.Set("guid", guid);
|
||||
params.Set("hat", hat);
|
||||
switch (value) {
|
||||
case SDL_HAT_UP:
|
||||
params.Set("direction", "up");
|
||||
break;
|
||||
case SDL_HAT_DOWN:
|
||||
params.Set("direction", "down");
|
||||
break;
|
||||
case SDL_HAT_LEFT:
|
||||
params.Set("direction", "left");
|
||||
break;
|
||||
case SDL_HAT_RIGHT:
|
||||
params.Set("direction", "right");
|
||||
break;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) {
|
||||
switch (event.type) {
|
||||
case SDL_JOYAXISMOTION: {
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
|
||||
return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
|
||||
event.jaxis.axis, event.jaxis.value);
|
||||
}
|
||||
case SDL_JOYBUTTONUP: {
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
|
||||
return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
|
||||
event.jbutton.button);
|
||||
}
|
||||
case SDL_JOYHATMOTION: {
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
|
||||
return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
|
||||
event.jhat.hat, event.jhat.value);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid,
|
||||
const SDL_GameControllerButtonBind& binding) {
|
||||
switch (binding.bindType) {
|
||||
case SDL_CONTROLLER_BINDTYPE_AXIS:
|
||||
return BuildAnalogParamPackageForButton(port, guid, binding.value.axis);
|
||||
case SDL_CONTROLLER_BINDTYPE_BUTTON:
|
||||
return BuildButtonParamPackageForButton(port, guid, binding.value.button);
|
||||
case SDL_CONTROLLER_BINDTYPE_HAT:
|
||||
return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat,
|
||||
binding.value.hat.hat_mask);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Common::ParamPackage BuildParamPackageForAnalog(int port, const std::string& guid, int axis_x,
|
||||
int axis_y) {
|
||||
Common::ParamPackage params;
|
||||
params.Set("engine", "sdl");
|
||||
params.Set("port", port);
|
||||
params.Set("guid", guid);
|
||||
params.Set("axis_x", axis_x);
|
||||
params.Set("axis_y", axis_y);
|
||||
return params;
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& params) {
|
||||
// This list is missing ZL/ZR since those are not considered buttons in SDL GameController.
|
||||
// We will add those afterwards
|
||||
// This list also excludes Screenshot since theres not really a mapping for that
|
||||
std::unordered_map<Settings::NativeButton::Values, SDL_GameControllerButton>
|
||||
switch_to_sdl_button = {
|
||||
{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B},
|
||||
{Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A},
|
||||
{Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y},
|
||||
{Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X},
|
||||
{Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK},
|
||||
{Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
|
||||
{Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
|
||||
{Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
|
||||
{Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START},
|
||||
{Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK},
|
||||
{Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT},
|
||||
{Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP},
|
||||
{Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
|
||||
{Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
|
||||
{Settings::NativeButton::SL, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
|
||||
{Settings::NativeButton::SR, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
|
||||
{Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE},
|
||||
};
|
||||
if (!params.Has("guid") || !params.Has("port")) {
|
||||
return {};
|
||||
}
|
||||
const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
|
||||
auto controller = joystick->GetSDLGameController();
|
||||
if (!controller) {
|
||||
return {};
|
||||
}
|
||||
|
||||
ButtonMapping mapping{};
|
||||
for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) {
|
||||
const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button);
|
||||
mapping[switch_button] =
|
||||
BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding);
|
||||
}
|
||||
|
||||
// Add the missing bindings for ZL/ZR
|
||||
std::unordered_map<Settings::NativeButton::Values, SDL_GameControllerAxis> switch_to_sdl_axis =
|
||||
{
|
||||
{Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT},
|
||||
{Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT},
|
||||
};
|
||||
for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) {
|
||||
const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis);
|
||||
mapping[switch_button] =
|
||||
BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding);
|
||||
}
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& params) {
|
||||
if (!params.Has("guid") || !params.Has("port")) {
|
||||
return {};
|
||||
}
|
||||
const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
|
||||
auto controller = joystick->GetSDLGameController();
|
||||
if (!controller) {
|
||||
return {};
|
||||
}
|
||||
|
||||
AnalogMapping mapping = {};
|
||||
const auto& binding_left_x =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
|
||||
const auto& binding_left_y =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
|
||||
mapping[Settings::NativeAnalog::LStick] =
|
||||
BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(),
|
||||
binding_left_x.value.axis, binding_left_y.value.axis);
|
||||
const auto& binding_right_x =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX);
|
||||
const auto& binding_right_y =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY);
|
||||
mapping[Settings::NativeAnalog::RStick] =
|
||||
BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(),
|
||||
binding_right_x.value.axis, binding_right_y.value.axis);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
namespace Polling {
|
||||
class SDLPoller : public InputCommon::Polling::DevicePoller {
|
||||
public:
|
||||
explicit SDLPoller(SDLState& state_) : state(state_) {}
|
||||
|
||||
void Start() override {
|
||||
void Start(const std::string& device_id) override {
|
||||
state.event_queue.Clear();
|
||||
state.polling = true;
|
||||
}
|
||||
@@ -601,71 +777,106 @@ public:
|
||||
Common::ParamPackage GetNextInput() override {
|
||||
SDL_Event event;
|
||||
while (state.event_queue.Pop(event)) {
|
||||
switch (event.type) {
|
||||
case SDL_JOYAXISMOTION:
|
||||
if (std::abs(event.jaxis.value / 32767.0) < 0.5) {
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_JOYHATMOTION:
|
||||
return SDLEventToButtonParamPackage(state, event);
|
||||
const auto package = FromEvent(event);
|
||||
if (package) {
|
||||
return *package;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
std::optional<Common::ParamPackage> FromEvent(const SDL_Event& event) {
|
||||
switch (event.type) {
|
||||
case SDL_JOYAXISMOTION:
|
||||
if (std::abs(event.jaxis.value / 32767.0) < 0.5) {
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_JOYHATMOTION:
|
||||
return {SDLEventToButtonParamPackage(state, event)};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
class SDLAnalogPoller final : public SDLPoller {
|
||||
/**
|
||||
* Attempts to match the press to a controller joy axis (left/right stick) and if a match
|
||||
* isn't found, checks if the event matches anything from SDLButtonPoller and uses that
|
||||
* instead
|
||||
*/
|
||||
class SDLAnalogPreferredPoller final : public SDLPoller {
|
||||
public:
|
||||
explicit SDLAnalogPoller(SDLState& state_) : SDLPoller(state_) {}
|
||||
|
||||
void Start() override {
|
||||
SDLPoller::Start();
|
||||
explicit SDLAnalogPreferredPoller(SDLState& state_)
|
||||
: SDLPoller(state_), button_poller(state_) {}
|
||||
|
||||
void Start(const std::string& device_id) override {
|
||||
SDLPoller::Start(device_id);
|
||||
// Load the game controller
|
||||
// Reset stored axes
|
||||
analog_x_axis = -1;
|
||||
analog_y_axis = -1;
|
||||
analog_axes_joystick = -1;
|
||||
}
|
||||
|
||||
Common::ParamPackage GetNextInput() override {
|
||||
SDL_Event event;
|
||||
while (state.event_queue.Pop(event)) {
|
||||
if (event.type != SDL_JOYAXISMOTION || std::abs(event.jaxis.value / 32767.0) < 0.5) {
|
||||
// Filter out axis events that are below a threshold
|
||||
if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) {
|
||||
continue;
|
||||
}
|
||||
// An analog device needs two axes, so we need to store the axis for later and wait for
|
||||
// a second SDL event. The axes also must be from the same joystick.
|
||||
const int axis = event.jaxis.axis;
|
||||
if (analog_x_axis == -1) {
|
||||
analog_x_axis = axis;
|
||||
analog_axes_joystick = event.jaxis.which;
|
||||
} else if (analog_y_axis == -1 && analog_x_axis != axis &&
|
||||
analog_axes_joystick == event.jaxis.which) {
|
||||
analog_y_axis = axis;
|
||||
// Simplify controller config by testing if game controller support is enabled.
|
||||
if (event.type == SDL_JOYAXISMOTION) {
|
||||
const auto axis = event.jaxis.axis;
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
|
||||
const auto controller = joystick->GetSDLGameController();
|
||||
if (controller) {
|
||||
const auto axis_left_x =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX)
|
||||
.value.axis;
|
||||
const auto axis_left_y =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY)
|
||||
.value.axis;
|
||||
const auto axis_right_x =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX)
|
||||
.value.axis;
|
||||
const auto axis_right_y =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY)
|
||||
.value.axis;
|
||||
|
||||
if (axis == axis_left_x || axis == axis_left_y) {
|
||||
analog_x_axis = axis_left_x;
|
||||
analog_y_axis = axis_left_y;
|
||||
break;
|
||||
} else if (axis == axis_right_x || axis == axis_right_y) {
|
||||
analog_x_axis = axis_right_x;
|
||||
analog_y_axis = axis_right_y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the press wasn't accepted as a joy axis, check for a button press
|
||||
auto button_press = button_poller.FromEvent(event);
|
||||
if (button_press) {
|
||||
return *button_press;
|
||||
}
|
||||
}
|
||||
Common::ParamPackage params;
|
||||
|
||||
if (analog_x_axis != -1 && analog_y_axis != -1) {
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
|
||||
params.Set("engine", "sdl");
|
||||
params.Set("port", joystick->GetPort());
|
||||
params.Set("guid", joystick->GetGUID());
|
||||
params.Set("axis_x", analog_x_axis);
|
||||
params.Set("axis_y", analog_y_axis);
|
||||
auto params = BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(),
|
||||
analog_x_axis, analog_y_axis);
|
||||
analog_x_axis = -1;
|
||||
analog_y_axis = -1;
|
||||
analog_axes_joystick = -1;
|
||||
return params;
|
||||
}
|
||||
return params;
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
int analog_x_axis = -1;
|
||||
int analog_y_axis = -1;
|
||||
SDL_JoystickID analog_axes_joystick = -1;
|
||||
SDLButtonPoller button_poller;
|
||||
};
|
||||
} // namespace Polling
|
||||
|
||||
@@ -673,8 +884,8 @@ SDLState::Pollers SDLState::GetPollers(InputCommon::Polling::DeviceType type) {
|
||||
Pollers pollers;
|
||||
|
||||
switch (type) {
|
||||
case InputCommon::Polling::DeviceType::Analog:
|
||||
pollers.emplace_back(std::make_unique<Polling::SDLAnalogPoller>(*this));
|
||||
case InputCommon::Polling::DeviceType::AnalogPreferred:
|
||||
pollers.emplace_back(std::make_unique<Polling::SDLAnalogPreferredPoller>(*this));
|
||||
break;
|
||||
case InputCommon::Polling::DeviceType::Button:
|
||||
pollers.emplace_back(std::make_unique<Polling::SDLButtonPoller>(*this));
|
||||
|
||||
@@ -50,6 +50,11 @@ public:
|
||||
std::atomic<bool> polling = false;
|
||||
Common::SPSCQueue<SDL_Event> event_queue;
|
||||
|
||||
std::vector<Common::ParamPackage> GetInputDevices() override;
|
||||
|
||||
ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;
|
||||
AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
|
||||
|
||||
private:
|
||||
void InitJoystick(int joystick_index);
|
||||
void CloseJoystick(SDL_Joystick* sdl_joystick);
|
||||
@@ -57,6 +62,9 @@ private:
|
||||
/// Needs to be called before SDL_QuitSubSystem.
|
||||
void CloseJoysticks();
|
||||
|
||||
// Set to true if SDL supports game controller subsystem
|
||||
bool has_gamecontroller = false;
|
||||
|
||||
/// Map of GUID of a list of corresponding virtual Joysticks
|
||||
std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
|
||||
std::mutex joystick_map_mutex;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "input_common/settings.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace NativeButton {
|
||||
const std::array<const char*, NumButtons> mapping = {{
|
||||
"button_a", "button_b", "button_x", "button_y", "button_lstick",
|
||||
"button_rstick", "button_l", "button_r", "button_zl", "button_zr",
|
||||
"button_plus", "button_minus", "button_dleft", "button_dup", "button_dright",
|
||||
"button_ddown", "button_sl", "button_sr", "button_home", "button_screenshot",
|
||||
}};
|
||||
}
|
||||
|
||||
namespace NativeAnalog {
|
||||
const std::array<const char*, NumAnalogs> mapping = {{
|
||||
"lstick",
|
||||
"rstick",
|
||||
}};
|
||||
}
|
||||
|
||||
namespace NativeMouseButton {
|
||||
const std::array<const char*, NumMouseButtons> mapping = {{
|
||||
"left",
|
||||
"right",
|
||||
"middle",
|
||||
"forward",
|
||||
"back",
|
||||
}};
|
||||
}
|
||||
} // namespace Settings
|
||||
@@ -0,0 +1,335 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace NativeButton {
|
||||
enum Values {
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
LStick,
|
||||
RStick,
|
||||
L,
|
||||
R,
|
||||
ZL,
|
||||
ZR,
|
||||
Plus,
|
||||
Minus,
|
||||
|
||||
DLeft,
|
||||
DUp,
|
||||
DRight,
|
||||
DDown,
|
||||
|
||||
SL,
|
||||
SR,
|
||||
|
||||
Home,
|
||||
Screenshot,
|
||||
|
||||
NumButtons,
|
||||
};
|
||||
|
||||
constexpr int BUTTON_HID_BEGIN = A;
|
||||
constexpr int BUTTON_NS_BEGIN = Home;
|
||||
|
||||
constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN;
|
||||
constexpr int BUTTON_NS_END = NumButtons;
|
||||
|
||||
constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN;
|
||||
constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN;
|
||||
|
||||
extern const std::array<const char*, NumButtons> mapping;
|
||||
|
||||
} // namespace NativeButton
|
||||
|
||||
namespace NativeAnalog {
|
||||
enum Values {
|
||||
LStick,
|
||||
RStick,
|
||||
|
||||
NumAnalogs,
|
||||
};
|
||||
|
||||
constexpr int STICK_HID_BEGIN = LStick;
|
||||
constexpr int STICK_HID_END = NumAnalogs;
|
||||
constexpr int NUM_STICKS_HID = NumAnalogs;
|
||||
|
||||
extern const std::array<const char*, NumAnalogs> mapping;
|
||||
} // namespace NativeAnalog
|
||||
|
||||
namespace NativeMouseButton {
|
||||
enum Values {
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Forward,
|
||||
Back,
|
||||
|
||||
NumMouseButtons,
|
||||
};
|
||||
|
||||
constexpr int MOUSE_HID_BEGIN = Left;
|
||||
constexpr int MOUSE_HID_END = NumMouseButtons;
|
||||
constexpr int NUM_MOUSE_HID = NumMouseButtons;
|
||||
|
||||
extern const std::array<const char*, NumMouseButtons> mapping;
|
||||
} // namespace NativeMouseButton
|
||||
|
||||
namespace NativeKeyboard {
|
||||
enum Keys {
|
||||
None,
|
||||
Error,
|
||||
|
||||
A = 4,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
N1,
|
||||
N2,
|
||||
N3,
|
||||
N4,
|
||||
N5,
|
||||
N6,
|
||||
N7,
|
||||
N8,
|
||||
N9,
|
||||
N0,
|
||||
Enter,
|
||||
Escape,
|
||||
Backspace,
|
||||
Tab,
|
||||
Space,
|
||||
Minus,
|
||||
Equal,
|
||||
LeftBrace,
|
||||
RightBrace,
|
||||
Backslash,
|
||||
Tilde,
|
||||
Semicolon,
|
||||
Apostrophe,
|
||||
Grave,
|
||||
Comma,
|
||||
Dot,
|
||||
Slash,
|
||||
CapsLockKey,
|
||||
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
|
||||
SystemRequest,
|
||||
ScrollLockKey,
|
||||
Pause,
|
||||
Insert,
|
||||
Home,
|
||||
PageUp,
|
||||
Delete,
|
||||
End,
|
||||
PageDown,
|
||||
Right,
|
||||
Left,
|
||||
Down,
|
||||
Up,
|
||||
|
||||
NumLockKey,
|
||||
KPSlash,
|
||||
KPAsterisk,
|
||||
KPMinus,
|
||||
KPPlus,
|
||||
KPEnter,
|
||||
KP1,
|
||||
KP2,
|
||||
KP3,
|
||||
KP4,
|
||||
KP5,
|
||||
KP6,
|
||||
KP7,
|
||||
KP8,
|
||||
KP9,
|
||||
KP0,
|
||||
KPDot,
|
||||
|
||||
Key102,
|
||||
Compose,
|
||||
Power,
|
||||
KPEqual,
|
||||
|
||||
F13,
|
||||
F14,
|
||||
F15,
|
||||
F16,
|
||||
F17,
|
||||
F18,
|
||||
F19,
|
||||
F20,
|
||||
F21,
|
||||
F22,
|
||||
F23,
|
||||
F24,
|
||||
|
||||
Open,
|
||||
Help,
|
||||
Properties,
|
||||
Front,
|
||||
Stop,
|
||||
Repeat,
|
||||
Undo,
|
||||
Cut,
|
||||
Copy,
|
||||
Paste,
|
||||
Find,
|
||||
Mute,
|
||||
VolumeUp,
|
||||
VolumeDown,
|
||||
CapsLockActive,
|
||||
NumLockActive,
|
||||
ScrollLockActive,
|
||||
KPComma,
|
||||
|
||||
KPLeftParenthesis,
|
||||
KPRightParenthesis,
|
||||
|
||||
LeftControlKey = 0xE0,
|
||||
LeftShiftKey,
|
||||
LeftAltKey,
|
||||
LeftMetaKey,
|
||||
RightControlKey,
|
||||
RightShiftKey,
|
||||
RightAltKey,
|
||||
RightMetaKey,
|
||||
|
||||
MediaPlayPause,
|
||||
MediaStopCD,
|
||||
MediaPrevious,
|
||||
MediaNext,
|
||||
MediaEject,
|
||||
MediaVolumeUp,
|
||||
MediaVolumeDown,
|
||||
MediaMute,
|
||||
MediaWebsite,
|
||||
MediaBack,
|
||||
MediaForward,
|
||||
MediaStop,
|
||||
MediaFind,
|
||||
MediaScrollUp,
|
||||
MediaScrollDown,
|
||||
MediaEdit,
|
||||
MediaSleep,
|
||||
MediaCoffee,
|
||||
MediaRefresh,
|
||||
MediaCalculator,
|
||||
|
||||
NumKeyboardKeys,
|
||||
};
|
||||
|
||||
static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys.");
|
||||
|
||||
enum Modifiers {
|
||||
LeftControl,
|
||||
LeftShift,
|
||||
LeftAlt,
|
||||
LeftMeta,
|
||||
RightControl,
|
||||
RightShift,
|
||||
RightAlt,
|
||||
RightMeta,
|
||||
CapsLock,
|
||||
ScrollLock,
|
||||
NumLock,
|
||||
|
||||
NumKeyboardMods,
|
||||
};
|
||||
|
||||
constexpr int KEYBOARD_KEYS_HID_BEGIN = None;
|
||||
constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys;
|
||||
constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys;
|
||||
|
||||
constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl;
|
||||
constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods;
|
||||
constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
|
||||
|
||||
} // namespace NativeKeyboard
|
||||
|
||||
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
|
||||
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
|
||||
using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
|
||||
using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
|
||||
using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
|
||||
|
||||
constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
|
||||
constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
|
||||
constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6;
|
||||
constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E;
|
||||
|
||||
enum class ControllerType {
|
||||
ProController,
|
||||
DualJoyconDetached,
|
||||
LeftJoycon,
|
||||
RightJoycon,
|
||||
Handheld,
|
||||
};
|
||||
|
||||
struct PlayerInput {
|
||||
bool connected;
|
||||
ControllerType controller_type;
|
||||
ButtonsRaw buttons;
|
||||
AnalogsRaw analogs;
|
||||
std::string lstick_mod;
|
||||
std::string rstick_mod;
|
||||
|
||||
u32 body_color_left;
|
||||
u32 body_color_right;
|
||||
u32 button_color_left;
|
||||
u32 button_color_right;
|
||||
};
|
||||
|
||||
struct TouchscreenInput {
|
||||
bool enabled;
|
||||
std::string device;
|
||||
|
||||
u32 finger;
|
||||
u32 diameter_x;
|
||||
u32 diameter_y;
|
||||
u32 rotation_angle;
|
||||
};
|
||||
} // namespace Settings
|
||||
@@ -77,10 +77,11 @@ State::State() {
|
||||
std::make_unique<Client>(status, Settings::values.udp_input_address,
|
||||
Settings::values.udp_input_port, Settings::values.udp_pad_index);
|
||||
|
||||
Input::RegisterFactory<Input::TouchDevice>("cemuhookudp",
|
||||
std::make_shared<UDPTouchFactory>(status));
|
||||
Input::RegisterFactory<Input::MotionDevice>("cemuhookudp",
|
||||
std::make_shared<UDPMotionFactory>(status));
|
||||
motion_factory = std::make_shared<UDPMotionFactory>(status);
|
||||
touch_factory = std::make_shared<UDPTouchFactory>(status);
|
||||
|
||||
Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", motion_factory);
|
||||
Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", touch_factory);
|
||||
}
|
||||
|
||||
State::~State() {
|
||||
@@ -88,6 +89,11 @@ State::~State() {
|
||||
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
|
||||
}
|
||||
|
||||
std::vector<Common::ParamPackage> State::GetInputDevices() const {
|
||||
// TODO support binding udp devices
|
||||
return {};
|
||||
}
|
||||
|
||||
void State::ReloadUDPClient() {
|
||||
client->ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port,
|
||||
Settings::values.udp_pad_index);
|
||||
|
||||
@@ -5,19 +5,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "common/param_package.h"
|
||||
|
||||
namespace InputCommon::CemuhookUDP {
|
||||
|
||||
class Client;
|
||||
class UDPMotionFactory;
|
||||
class UDPTouchFactory;
|
||||
|
||||
class State {
|
||||
public:
|
||||
State();
|
||||
~State();
|
||||
void ReloadUDPClient();
|
||||
std::vector<Common::ParamPackage> GetInputDevices() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Client> client;
|
||||
std::shared_ptr<UDPMotionFactory> motion_factory;
|
||||
std::shared_ptr<UDPTouchFactory> touch_factory;
|
||||
};
|
||||
|
||||
std::unique_ptr<State> Init();
|
||||
|
||||
@@ -10,7 +10,13 @@
|
||||
|
||||
namespace Tegra::Engines {
|
||||
|
||||
Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer) : rasterizer{rasterizer} {}
|
||||
Fermi2D::Fermi2D() = default;
|
||||
|
||||
Fermi2D::~Fermi2D() = default;
|
||||
|
||||
void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
|
||||
ASSERT_MSG(method < Regs::NUM_REGS,
|
||||
@@ -87,7 +93,7 @@ void Fermi2D::HandleSurfaceCopy() {
|
||||
copy_config.src_rect = src_rect;
|
||||
copy_config.dst_rect = dst_rect;
|
||||
|
||||
if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) {
|
||||
if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,11 @@ namespace Tegra::Engines {
|
||||
|
||||
class Fermi2D final : public EngineInterface {
|
||||
public:
|
||||
explicit Fermi2D(VideoCore::RasterizerInterface& rasterizer);
|
||||
~Fermi2D() = default;
|
||||
explicit Fermi2D();
|
||||
~Fermi2D();
|
||||
|
||||
/// Binds a rasterizer to this engine.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
/// Write the value to the register identified by method.
|
||||
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
|
||||
@@ -149,7 +152,7 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
VideoCore::RasterizerInterface* rasterizer;
|
||||
|
||||
/// Performs the copy from the source surface to the destination surface as configured in the
|
||||
/// registers.
|
||||
|
||||
@@ -16,14 +16,15 @@
|
||||
|
||||
namespace Tegra::Engines {
|
||||
|
||||
KeplerCompute::KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager)
|
||||
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, upload_state{
|
||||
memory_manager,
|
||||
regs.upload} {}
|
||||
KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_)
|
||||
: system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} {}
|
||||
|
||||
KeplerCompute::~KeplerCompute() = default;
|
||||
|
||||
void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
|
||||
ASSERT_MSG(method < Regs::NUM_REGS,
|
||||
"Invalid KeplerCompute register, increase the size of the Regs structure");
|
||||
@@ -104,11 +105,11 @@ SamplerDescriptor KeplerCompute::AccessSampler(u32 handle) const {
|
||||
}
|
||||
|
||||
VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
void KeplerCompute::ProcessLaunch() {
|
||||
@@ -119,7 +120,7 @@ void KeplerCompute::ProcessLaunch() {
|
||||
const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start;
|
||||
LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr);
|
||||
|
||||
rasterizer.DispatchCompute(code_addr);
|
||||
rasterizer->DispatchCompute(code_addr);
|
||||
}
|
||||
|
||||
Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {
|
||||
|
||||
@@ -42,10 +42,12 @@ namespace Tegra::Engines {
|
||||
|
||||
class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface {
|
||||
public:
|
||||
explicit KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager);
|
||||
explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager);
|
||||
~KeplerCompute();
|
||||
|
||||
/// Binds a rasterizer to this engine.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
static constexpr std::size_t NumConstBuffers = 8;
|
||||
|
||||
struct Regs {
|
||||
@@ -230,11 +232,6 @@ public:
|
||||
const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override;
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
MemoryManager& memory_manager;
|
||||
Upload::State upload_state;
|
||||
|
||||
void ProcessLaunch();
|
||||
|
||||
/// Retrieves information about a specific TIC entry from the TIC buffer.
|
||||
@@ -242,6 +239,11 @@ private:
|
||||
|
||||
/// Retrieves information about a specific TSC entry from the TSC buffer.
|
||||
Texture::TSCEntry GetTSCEntry(u32 tsc_index) const;
|
||||
|
||||
Core::System& system;
|
||||
MemoryManager& memory_manager;
|
||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||
Upload::State upload_state;
|
||||
};
|
||||
|
||||
#define ASSERT_REG_POSITION(field_name, position) \
|
||||
|
||||
@@ -22,14 +22,19 @@ using VideoCore::QueryType;
|
||||
/// First register id that is actually a Macro call.
|
||||
constexpr u32 MacroRegistersStart = 0xE00;
|
||||
|
||||
Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager)
|
||||
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager},
|
||||
macro_engine{GetMacroEngine(*this)}, upload_state{memory_manager, regs.upload} {
|
||||
Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
|
||||
: system{system_}, memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)},
|
||||
upload_state{memory_manager, regs.upload} {
|
||||
dirty.flags.flip();
|
||||
InitializeRegisterDefaults();
|
||||
}
|
||||
|
||||
Maxwell3D::~Maxwell3D() = default;
|
||||
|
||||
void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
void Maxwell3D::InitializeRegisterDefaults() {
|
||||
// Initializes registers to their default values - what games expect them to be at boot. This is
|
||||
// for certain registers that may not be explicitly set by games.
|
||||
@@ -192,7 +197,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
|
||||
|
||||
switch (method) {
|
||||
case MAXWELL3D_REG_INDEX(wait_for_idle): {
|
||||
rasterizer.WaitForIdle();
|
||||
rasterizer->WaitForIdle();
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(shadow_ram_control): {
|
||||
@@ -402,7 +407,7 @@ void Maxwell3D::FlushMMEInlineDraw() {
|
||||
|
||||
const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed;
|
||||
if (ShouldExecute()) {
|
||||
rasterizer.Draw(is_indexed, true);
|
||||
rasterizer->Draw(is_indexed, true);
|
||||
}
|
||||
|
||||
// TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
|
||||
@@ -465,7 +470,7 @@ void Maxwell3D::ProcessQueryGet() {
|
||||
switch (regs.query.query_get.operation) {
|
||||
case Regs::QueryOperation::Release:
|
||||
if (regs.query.query_get.fence == 1) {
|
||||
rasterizer.SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence);
|
||||
rasterizer->SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence);
|
||||
} else {
|
||||
StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0);
|
||||
}
|
||||
@@ -533,7 +538,7 @@ void Maxwell3D::ProcessQueryCondition() {
|
||||
void Maxwell3D::ProcessCounterReset() {
|
||||
switch (regs.counter_reset) {
|
||||
case Regs::CounterReset::SampleCnt:
|
||||
rasterizer.ResetCounter(QueryType::SamplesPassed);
|
||||
rasterizer->ResetCounter(QueryType::SamplesPassed);
|
||||
break;
|
||||
default:
|
||||
LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}",
|
||||
@@ -547,7 +552,7 @@ void Maxwell3D::ProcessSyncPoint() {
|
||||
const u32 increment = regs.sync_info.increment.Value();
|
||||
[[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
|
||||
if (increment) {
|
||||
rasterizer.SignalSyncPoint(sync_point);
|
||||
rasterizer->SignalSyncPoint(sync_point);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,7 +575,7 @@ void Maxwell3D::DrawArrays() {
|
||||
|
||||
const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
|
||||
if (ShouldExecute()) {
|
||||
rasterizer.Draw(is_indexed, false);
|
||||
rasterizer->Draw(is_indexed, false);
|
||||
}
|
||||
|
||||
// TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
|
||||
@@ -590,8 +595,8 @@ std::optional<u64> Maxwell3D::GetQueryResult() {
|
||||
return 0;
|
||||
case Regs::QuerySelect::SamplesPassed:
|
||||
// Deferred.
|
||||
rasterizer.Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
|
||||
system.GPU().GetTicks());
|
||||
rasterizer->Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
|
||||
system.GPU().GetTicks());
|
||||
return {};
|
||||
default:
|
||||
LOG_DEBUG(HW_GPU, "Unimplemented query select type {}",
|
||||
@@ -718,7 +723,7 @@ void Maxwell3D::ProcessClearBuffers() {
|
||||
regs.clear_buffers.R == regs.clear_buffers.B &&
|
||||
regs.clear_buffers.R == regs.clear_buffers.A);
|
||||
|
||||
rasterizer.Clear();
|
||||
rasterizer->Clear();
|
||||
}
|
||||
|
||||
u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const {
|
||||
@@ -752,11 +757,11 @@ SamplerDescriptor Maxwell3D::AccessSampler(u32 handle) const {
|
||||
}
|
||||
|
||||
VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
} // namespace Tegra::Engines
|
||||
|
||||
@@ -51,9 +51,11 @@ namespace Tegra::Engines {
|
||||
|
||||
class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface {
|
||||
public:
|
||||
explicit Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager);
|
||||
~Maxwell3D() = default;
|
||||
explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager);
|
||||
~Maxwell3D();
|
||||
|
||||
/// Binds a rasterizer to this engine.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
/// Register structure of the Maxwell3D engine.
|
||||
/// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
|
||||
@@ -1418,12 +1420,12 @@ public:
|
||||
return execute_on;
|
||||
}
|
||||
|
||||
VideoCore::RasterizerInterface& GetRasterizer() {
|
||||
return rasterizer;
|
||||
VideoCore::RasterizerInterface& Rasterizer() {
|
||||
return *rasterizer;
|
||||
}
|
||||
|
||||
const VideoCore::RasterizerInterface& GetRasterizer() const {
|
||||
return rasterizer;
|
||||
const VideoCore::RasterizerInterface& Rasterizer() const {
|
||||
return *rasterizer;
|
||||
}
|
||||
|
||||
/// Notify a memory write has happened.
|
||||
@@ -1460,11 +1462,10 @@ private:
|
||||
void InitializeRegisterDefaults();
|
||||
|
||||
Core::System& system;
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
|
||||
MemoryManager& memory_manager;
|
||||
|
||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||
|
||||
/// Start offsets of each macro in macro_memory
|
||||
std::array<u32, 0x80> macro_positions = {};
|
||||
|
||||
|
||||
@@ -27,21 +27,28 @@ namespace Tegra {
|
||||
|
||||
MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192));
|
||||
|
||||
GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async)
|
||||
: system{system}, renderer{std::move(renderer_)}, is_async{is_async} {
|
||||
auto& rasterizer{renderer->Rasterizer()};
|
||||
memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer);
|
||||
dma_pusher = std::make_unique<Tegra::DmaPusher>(system, *this);
|
||||
maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager);
|
||||
fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer);
|
||||
kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager);
|
||||
maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager);
|
||||
kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager);
|
||||
shader_notify = std::make_unique<VideoCore::ShaderNotify>();
|
||||
}
|
||||
GPU::GPU(Core::System& system_, bool is_async_)
|
||||
: system{system_}, dma_pusher{std::make_unique<Tegra::DmaPusher>(system, *this)},
|
||||
memory_manager{std::make_unique<Tegra::MemoryManager>(system)},
|
||||
maxwell_3d{std::make_unique<Engines::Maxwell3D>(system, *memory_manager)},
|
||||
fermi_2d{std::make_unique<Engines::Fermi2D>()},
|
||||
kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)},
|
||||
maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)},
|
||||
kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)},
|
||||
shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_} {}
|
||||
|
||||
GPU::~GPU() = default;
|
||||
|
||||
void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
|
||||
renderer = std::move(renderer_);
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer();
|
||||
memory_manager->BindRasterizer(rasterizer);
|
||||
maxwell_3d->BindRasterizer(rasterizer);
|
||||
fermi_2d->BindRasterizer(rasterizer);
|
||||
kepler_compute->BindRasterizer(rasterizer);
|
||||
}
|
||||
|
||||
Engines::Maxwell3D& GPU::Maxwell3D() {
|
||||
return *maxwell_3d;
|
||||
}
|
||||
|
||||
@@ -142,11 +142,6 @@ class MemoryManager;
|
||||
|
||||
class GPU {
|
||||
public:
|
||||
explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
bool is_async);
|
||||
|
||||
virtual ~GPU();
|
||||
|
||||
struct MethodCall {
|
||||
u32 method{};
|
||||
u32 argument{};
|
||||
@@ -162,6 +157,12 @@ public:
|
||||
method_count(method_count) {}
|
||||
};
|
||||
|
||||
explicit GPU(Core::System& system, bool is_async);
|
||||
virtual ~GPU();
|
||||
|
||||
/// Binds a renderer to the GPU.
|
||||
void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer);
|
||||
|
||||
/// Calls a GPU method.
|
||||
void CallMethod(const MethodCall& method_call);
|
||||
|
||||
@@ -345,8 +346,8 @@ private:
|
||||
bool ExecuteMethodOnEngine(u32 method);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
||||
Core::System& system;
|
||||
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
||||
|
||||
private:
|
||||
|
||||
@@ -10,16 +10,14 @@
|
||||
|
||||
namespace VideoCommon {
|
||||
|
||||
GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
|
||||
: GPU(system, std::move(renderer_), true), gpu_thread{system},
|
||||
cpu_context(renderer->GetRenderWindow().CreateSharedContext()),
|
||||
gpu_context(std::move(context)) {}
|
||||
GPUAsynch::GPUAsynch(Core::System& system) : GPU{system, true}, gpu_thread{system} {}
|
||||
|
||||
GPUAsynch::~GPUAsynch() = default;
|
||||
|
||||
void GPUAsynch::Start() {
|
||||
gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher);
|
||||
gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher);
|
||||
cpu_context = renderer->GetRenderWindow().CreateSharedContext();
|
||||
cpu_context->MakeCurrent();
|
||||
}
|
||||
|
||||
void GPUAsynch::ObtainContext() {
|
||||
|
||||
@@ -20,8 +20,7 @@ namespace VideoCommon {
|
||||
/// Implementation of GPU interface that runs the GPU asynchronously
|
||||
class GPUAsynch final : public Tegra::GPU {
|
||||
public:
|
||||
explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
|
||||
explicit GPUAsynch(Core::System& system);
|
||||
~GPUAsynch() override;
|
||||
|
||||
void Start() override;
|
||||
@@ -42,7 +41,6 @@ protected:
|
||||
private:
|
||||
GPUThread::ThreadManager gpu_thread;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
||||
@@ -7,20 +7,18 @@
|
||||
|
||||
namespace VideoCommon {
|
||||
|
||||
GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
|
||||
: GPU(system, std::move(renderer), false), context{std::move(context)} {}
|
||||
GPUSynch::GPUSynch(Core::System& system) : GPU{system, false} {}
|
||||
|
||||
GPUSynch::~GPUSynch() = default;
|
||||
|
||||
void GPUSynch::Start() {}
|
||||
|
||||
void GPUSynch::ObtainContext() {
|
||||
context->MakeCurrent();
|
||||
renderer->Context().MakeCurrent();
|
||||
}
|
||||
|
||||
void GPUSynch::ReleaseContext() {
|
||||
context->DoneCurrent();
|
||||
renderer->Context().DoneCurrent();
|
||||
}
|
||||
|
||||
void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {
|
||||
|
||||
@@ -19,8 +19,7 @@ namespace VideoCommon {
|
||||
/// Implementation of GPU interface that runs the GPU synchronously
|
||||
class GPUSynch final : public Tegra::GPU {
|
||||
public:
|
||||
explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
|
||||
explicit GPUSynch(Core::System& system);
|
||||
~GPUSynch() override;
|
||||
|
||||
void Start() override;
|
||||
@@ -36,9 +35,6 @@ public:
|
||||
protected:
|
||||
void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id,
|
||||
[[maybe_unused]] u32 value) const override {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
||||
@@ -24,7 +24,7 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||
maxwell3d.regs.index_array.first = parameters[4];
|
||||
|
||||
if (maxwell3d.ShouldExecute()) {
|
||||
maxwell3d.GetRasterizer().Draw(true, true);
|
||||
maxwell3d.Rasterizer().Draw(true, true);
|
||||
}
|
||||
maxwell3d.regs.index_array.count = 0;
|
||||
maxwell3d.mme_draw.instance_count = 0;
|
||||
@@ -42,7 +42,7 @@ void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||
maxwell3d.mme_draw.instance_count = count;
|
||||
|
||||
if (maxwell3d.ShouldExecute()) {
|
||||
maxwell3d.GetRasterizer().Draw(false, true);
|
||||
maxwell3d.Rasterizer().Draw(false, true);
|
||||
}
|
||||
maxwell3d.regs.vertex_buffer.count = 0;
|
||||
maxwell3d.mme_draw.instance_count = 0;
|
||||
@@ -65,7 +65,7 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||
maxwell3d.regs.draw.topology.Assign(
|
||||
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
|
||||
if (maxwell3d.ShouldExecute()) {
|
||||
maxwell3d.GetRasterizer().Draw(true, true);
|
||||
maxwell3d.Rasterizer().Draw(true, true);
|
||||
}
|
||||
maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
|
||||
maxwell3d.regs.index_array.count = 0;
|
||||
|
||||
@@ -14,11 +14,15 @@
|
||||
|
||||
namespace Tegra {
|
||||
|
||||
MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer)
|
||||
: system{system}, rasterizer{rasterizer}, page_table(page_table_size) {}
|
||||
MemoryManager::MemoryManager(Core::System& system_)
|
||||
: system{system_}, page_table(page_table_size) {}
|
||||
|
||||
MemoryManager::~MemoryManager() = default;
|
||||
|
||||
void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) {
|
||||
u64 remaining_size{size};
|
||||
for (u64 offset{}; offset < size; offset += page_size) {
|
||||
@@ -217,7 +221,7 @@ void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::siz
|
||||
|
||||
// Flush must happen on the rasterizer interface, such that memory is always synchronous
|
||||
// when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu.
|
||||
rasterizer.FlushRegion(src_addr, copy_amount);
|
||||
rasterizer->FlushRegion(src_addr, copy_amount);
|
||||
system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount);
|
||||
}
|
||||
|
||||
@@ -266,7 +270,7 @@ void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, s
|
||||
|
||||
// Invalidate must happen on the rasterizer interface, such that memory is always
|
||||
// synchronous when it is written (even when in asynchronous GPU mode).
|
||||
rasterizer.InvalidateRegion(dest_addr, copy_amount);
|
||||
rasterizer->InvalidateRegion(dest_addr, copy_amount);
|
||||
system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount);
|
||||
}
|
||||
|
||||
@@ -312,10 +316,10 @@ void MemoryManager::CopyBlockUnsafe(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_add
|
||||
WriteBlockUnsafe(gpu_dest_addr, tmp_buffer.data(), size);
|
||||
}
|
||||
|
||||
bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) {
|
||||
bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const {
|
||||
const auto cpu_addr{GpuToCpuAddress(gpu_addr)};
|
||||
if (!cpu_addr) {
|
||||
return {};
|
||||
return false;
|
||||
}
|
||||
const std::size_t page{(*cpu_addr & Core::Memory::PAGE_MASK) + size};
|
||||
return page <= Core::Memory::PAGE_SIZE;
|
||||
|
||||
@@ -68,9 +68,12 @@ static_assert(sizeof(PageEntry) == 4, "PageEntry is too large");
|
||||
|
||||
class MemoryManager final {
|
||||
public:
|
||||
explicit MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer);
|
||||
explicit MemoryManager(Core::System& system);
|
||||
~MemoryManager();
|
||||
|
||||
/// Binds a renderer to the memory manager.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
|
||||
|
||||
template <typename T>
|
||||
@@ -109,7 +112,7 @@ public:
|
||||
/**
|
||||
* IsGranularRange checks if a gpu region can be simply read with a pointer.
|
||||
*/
|
||||
bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size);
|
||||
bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const;
|
||||
|
||||
GPUVAddr Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size);
|
||||
GPUVAddr MapAllocate(VAddr cpu_addr, std::size_t size, std::size_t align);
|
||||
@@ -141,7 +144,7 @@ private:
|
||||
|
||||
Core::System& system;
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||
|
||||
std::vector<PageEntry> page_table;
|
||||
};
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
RendererBase::RendererBase(Core::Frontend::EmuWindow& window) : render_window{window} {
|
||||
RendererBase::RendererBase(Core::Frontend::EmuWindow& window_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
||||
: render_window{window_}, context{std::move(context_)} {
|
||||
RefreshBaseSettings();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
namespace Core::Frontend {
|
||||
class EmuWindow;
|
||||
}
|
||||
class GraphicsContext;
|
||||
} // namespace Core::Frontend
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
@@ -25,14 +26,15 @@ struct RendererSettings {
|
||||
|
||||
// Screenshot
|
||||
std::atomic<bool> screenshot_requested{false};
|
||||
void* screenshot_bits;
|
||||
void* screenshot_bits{};
|
||||
std::function<void()> screenshot_complete_callback;
|
||||
Layout::FramebufferLayout screenshot_framebuffer_layout;
|
||||
};
|
||||
|
||||
class RendererBase : NonCopyable {
|
||||
public:
|
||||
explicit RendererBase(Core::Frontend::EmuWindow& window);
|
||||
explicit RendererBase(Core::Frontend::EmuWindow& window,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context);
|
||||
virtual ~RendererBase();
|
||||
|
||||
/// Initialize the renderer
|
||||
@@ -68,6 +70,14 @@ public:
|
||||
return *rasterizer;
|
||||
}
|
||||
|
||||
Core::Frontend::GraphicsContext& Context() {
|
||||
return *context;
|
||||
}
|
||||
|
||||
const Core::Frontend::GraphicsContext& Context() const {
|
||||
return *context;
|
||||
}
|
||||
|
||||
Core::Frontend::EmuWindow& GetRenderWindow() {
|
||||
return render_window;
|
||||
}
|
||||
@@ -94,6 +104,7 @@ public:
|
||||
protected:
|
||||
Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
|
||||
std::unique_ptr<RasterizerInterface> rasterizer;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context;
|
||||
f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
|
||||
int m_current_frame = 0; ///< Current frame, should be set by the renderer
|
||||
|
||||
|
||||
@@ -313,10 +313,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context)
|
||||
: RendererBase{emu_window}, emu_window{emu_window}, system{system}, context{context},
|
||||
program_manager{device}, has_debug_tool{HasDebugTool()} {}
|
||||
RendererOpenGL::RendererOpenGL(Core::System& system_, Core::Frontend::EmuWindow& emu_window_,
|
||||
Tegra::GPU& gpu_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
||||
: RendererBase{emu_window_, std::move(context_)}, system{system_},
|
||||
emu_window{emu_window_}, gpu{gpu_}, program_manager{device}, has_debug_tool{HasDebugTool()} {}
|
||||
|
||||
RendererOpenGL::~RendererOpenGL() = default;
|
||||
|
||||
@@ -384,7 +385,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||
if (has_debug_tool) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
Present(0);
|
||||
context.SwapBuffers();
|
||||
context->SwapBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,8 +56,9 @@ class FrameMailbox;
|
||||
|
||||
class RendererOpenGL final : public VideoCore::RendererBase {
|
||||
public:
|
||||
explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context);
|
||||
explicit RendererOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
|
||||
Tegra::GPU& gpu,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context);
|
||||
~RendererOpenGL() override;
|
||||
|
||||
bool Init() override;
|
||||
@@ -93,9 +94,9 @@ private:
|
||||
|
||||
bool Present(int timeout_ms);
|
||||
|
||||
Core::Frontend::EmuWindow& emu_window;
|
||||
Core::System& system;
|
||||
Core::Frontend::GraphicsContext& context;
|
||||
Core::Frontend::EmuWindow& emu_window;
|
||||
Tegra::GPU& gpu;
|
||||
const Device device;
|
||||
|
||||
StateTracker state_tracker{system};
|
||||
@@ -120,7 +121,7 @@ private:
|
||||
std::vector<u8> gl_framebuffer_data;
|
||||
|
||||
/// Used for transforming the framebuffer orientation
|
||||
Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags;
|
||||
Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags{};
|
||||
Common::Rectangle<int> framebuffer_crop_rect;
|
||||
|
||||
/// Frame presentation mailbox
|
||||
|
||||
@@ -237,8 +237,10 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system)
|
||||
: RendererBase(window), system{system} {}
|
||||
RendererVulkan::RendererVulkan(Core::System& system_, Core::Frontend::EmuWindow& emu_window,
|
||||
Tegra::GPU& gpu_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context)
|
||||
: RendererBase{emu_window, std::move(context)}, system{system_}, gpu{gpu_} {}
|
||||
|
||||
RendererVulkan::~RendererVulkan() {
|
||||
ShutDown();
|
||||
|
||||
@@ -38,7 +38,9 @@ struct VKScreenInfo {
|
||||
|
||||
class RendererVulkan final : public VideoCore::RendererBase {
|
||||
public:
|
||||
explicit RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system);
|
||||
explicit RendererVulkan(Core::System& system, Core::Frontend::EmuWindow& emu_window,
|
||||
Tegra::GPU& gpu,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context);
|
||||
~RendererVulkan() override;
|
||||
|
||||
bool Init() override;
|
||||
@@ -58,6 +60,7 @@ private:
|
||||
void Report() const;
|
||||
|
||||
Core::System& system;
|
||||
Tegra::GPU& gpu;
|
||||
|
||||
Common::DynamicLibrary library;
|
||||
vk::InstanceDispatch dld;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/settings.h"
|
||||
@@ -16,37 +17,46 @@
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
namespace {
|
||||
std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window,
|
||||
Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context) {
|
||||
|
||||
std::unique_ptr<VideoCore::RendererBase> CreateRenderer(
|
||||
Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context) {
|
||||
switch (Settings::values.renderer_backend.GetValue()) {
|
||||
case Settings::RendererBackend::OpenGL:
|
||||
return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context);
|
||||
return std::make_unique<OpenGL::RendererOpenGL>(system, emu_window, gpu,
|
||||
std::move(context));
|
||||
#ifdef HAS_VULKAN
|
||||
case Settings::RendererBackend::Vulkan:
|
||||
return std::make_unique<Vulkan::RendererVulkan>(emu_window, system);
|
||||
return std::make_unique<Vulkan::RendererVulkan>(system, emu_window, gpu,
|
||||
std::move(context));
|
||||
#endif
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) {
|
||||
std::unique_ptr<Tegra::GPU> gpu;
|
||||
if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
|
||||
gpu = std::make_unique<VideoCommon::GPUAsynch>(system);
|
||||
} else {
|
||||
gpu = std::make_unique<VideoCommon::GPUSynch>(system);
|
||||
}
|
||||
|
||||
auto context = emu_window.CreateSharedContext();
|
||||
const auto scope = context->Acquire();
|
||||
auto renderer = CreateRenderer(emu_window, system, *context);
|
||||
|
||||
auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context));
|
||||
if (!renderer->Init()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
|
||||
return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer),
|
||||
std::move(context));
|
||||
}
|
||||
return std::make_unique<VideoCommon::GPUSynch>(system, std::move(renderer), std::move(context));
|
||||
gpu->BindRenderer(std::move(renderer));
|
||||
return gpu;
|
||||
}
|
||||
|
||||
u16 GetResolutionScaleFactor(const RendererBase& renderer) {
|
||||
|
||||
@@ -39,6 +39,9 @@ add_executable(yuzu
|
||||
configuration/configure_debug.cpp
|
||||
configuration/configure_debug.h
|
||||
configuration/configure_debug.ui
|
||||
configuration/configure_debug_controller.cpp
|
||||
configuration/configure_debug_controller.h
|
||||
configuration/configure_debug_controller.ui
|
||||
configuration/configure_dialog.cpp
|
||||
configuration/configure_dialog.h
|
||||
configuration/configure_filesystem.cpp
|
||||
@@ -62,9 +65,9 @@ add_executable(yuzu
|
||||
configuration/configure_input_player.cpp
|
||||
configuration/configure_input_player.h
|
||||
configuration/configure_input_player.ui
|
||||
configuration/configure_input_simple.cpp
|
||||
configuration/configure_input_simple.h
|
||||
configuration/configure_input_simple.ui
|
||||
configuration/configure_input_advanced.cpp
|
||||
configuration/configure_input_advanced.h
|
||||
configuration/configure_input_advanced.ui
|
||||
configuration/configure_mouse_advanced.cpp
|
||||
configuration/configure_mouse_advanced.h
|
||||
configuration/configure_mouse_advanced.ui
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <QKeySequence>
|
||||
#include <QSettings>
|
||||
#include "common/file_util.h"
|
||||
#include "configure_input_simple.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "core/hle/service/hid/controllers/npad.h"
|
||||
#include "input_common/main.h"
|
||||
@@ -32,29 +31,29 @@ Config::~Config() {
|
||||
}
|
||||
|
||||
const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = {
|
||||
Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q,
|
||||
Qt::Key_W, Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T,
|
||||
Qt::Key_H, Qt::Key_G, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_Down, Qt::Key_J,
|
||||
Qt::Key_I, Qt::Key_L, Qt::Key_K, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V,
|
||||
Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q,
|
||||
Qt::Key_W, Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T,
|
||||
Qt::Key_H, Qt::Key_G, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V,
|
||||
};
|
||||
|
||||
const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{
|
||||
const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{
|
||||
{
|
||||
Qt::Key_Up,
|
||||
Qt::Key_Down,
|
||||
Qt::Key_Left,
|
||||
Qt::Key_Right,
|
||||
Qt::Key_E,
|
||||
},
|
||||
{
|
||||
Qt::Key_I,
|
||||
Qt::Key_K,
|
||||
Qt::Key_J,
|
||||
Qt::Key_L,
|
||||
Qt::Key_R,
|
||||
},
|
||||
}};
|
||||
|
||||
const int Config::default_lstick_mod = Qt::Key_E;
|
||||
const int Config::default_rstick_mod = Qt::Key_R;
|
||||
|
||||
const std::array<int, Settings::NativeMouseButton::NumMouseButtons> Config::default_mouse_buttons =
|
||||
{
|
||||
Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal,
|
||||
@@ -243,10 +242,10 @@ void Config::ReadPlayerValues() {
|
||||
player.connected =
|
||||
ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool();
|
||||
|
||||
player.type = static_cast<Settings::ControllerType>(
|
||||
player.controller_type = static_cast<Settings::ControllerType>(
|
||||
qt_config
|
||||
->value(QStringLiteral("player_%1_type").arg(p),
|
||||
static_cast<u8>(Settings::ControllerType::DualJoycon))
|
||||
static_cast<u8>(Settings::ControllerType::ProController))
|
||||
.toUInt());
|
||||
|
||||
player.body_color_left = qt_config
|
||||
@@ -300,12 +299,6 @@ void Config::ReadPlayerValues() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stable_partition(
|
||||
Settings::values.players.begin(),
|
||||
Settings::values.players.begin() +
|
||||
Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD),
|
||||
[](const auto& player) { return player.connected; });
|
||||
}
|
||||
|
||||
void Config::ReadDebugValues() {
|
||||
@@ -397,13 +390,6 @@ void Config::ReadTouchscreenValues() {
|
||||
ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt();
|
||||
}
|
||||
|
||||
void Config::ApplyDefaultProfileIfInputInvalid() {
|
||||
if (!std::any_of(Settings::values.players.begin(), Settings::values.players.end(),
|
||||
[](const Settings::PlayerInput& in) { return in.connected; })) {
|
||||
ApplyInputProfileConfiguration(UISettings::values.profile_index);
|
||||
}
|
||||
}
|
||||
|
||||
void Config::ReadAudioValues() {
|
||||
qt_config->beginGroup(QStringLiteral("Audio"));
|
||||
|
||||
@@ -433,6 +419,8 @@ void Config::ReadControlValues() {
|
||||
ReadMouseValues();
|
||||
ReadTouchscreenValues();
|
||||
|
||||
Settings::values.vibration_enabled =
|
||||
ReadSetting(QStringLiteral("vibration_enabled"), true).toBool();
|
||||
Settings::values.motion_device =
|
||||
ReadSetting(QStringLiteral("motion_device"),
|
||||
QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01"))
|
||||
@@ -501,7 +489,7 @@ void Config::ReadDataStorageValues() {
|
||||
Settings::values.gamecard_current_game =
|
||||
ReadSetting(QStringLiteral("gamecard_current_game"), false).toBool();
|
||||
Settings::values.gamecard_path =
|
||||
ReadSetting(QStringLiteral("gamecard_path"), QStringLiteral("")).toString().toStdString();
|
||||
ReadSetting(QStringLiteral("gamecard_path"), QString{}).toString().toStdString();
|
||||
|
||||
qt_config->endGroup();
|
||||
}
|
||||
@@ -515,7 +503,7 @@ void Config::ReadDebuggingValues() {
|
||||
Settings::values.use_gdbstub = ReadSetting(QStringLiteral("use_gdbstub"), false).toBool();
|
||||
Settings::values.gdbstub_port = ReadSetting(QStringLiteral("gdbstub_port"), 24689).toInt();
|
||||
Settings::values.program_args =
|
||||
ReadSetting(QStringLiteral("program_args"), QStringLiteral("")).toString().toStdString();
|
||||
ReadSetting(QStringLiteral("program_args"), QString{}).toString().toStdString();
|
||||
Settings::values.dump_exefs = ReadSetting(QStringLiteral("dump_exefs"), false).toBool();
|
||||
Settings::values.dump_nso = ReadSetting(QStringLiteral("dump_nso"), false).toBool();
|
||||
Settings::values.reporting_services =
|
||||
@@ -548,8 +536,7 @@ void Config::ReadDisabledAddOnValues() {
|
||||
const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled"));
|
||||
for (int j = 0; j < d_size; ++j) {
|
||||
qt_config->setArrayIndex(j);
|
||||
out.push_back(
|
||||
ReadSetting(QStringLiteral("d"), QStringLiteral("")).toString().toStdString());
|
||||
out.push_back(ReadSetting(QStringLiteral("d"), QString{}).toString().toStdString());
|
||||
}
|
||||
qt_config->endArray();
|
||||
Settings::values.disabled_addons.insert_or_assign(title_id, out);
|
||||
@@ -788,14 +775,11 @@ void Config::ReadUIValues() {
|
||||
UISettings::values.first_start = ReadSetting(QStringLiteral("firstStart"), true).toBool();
|
||||
UISettings::values.callout_flags = ReadSetting(QStringLiteral("calloutFlags"), 0).toUInt();
|
||||
UISettings::values.show_console = ReadSetting(QStringLiteral("showConsole"), false).toBool();
|
||||
UISettings::values.profile_index = ReadSetting(QStringLiteral("profileIndex"), 0).toUInt();
|
||||
UISettings::values.pause_when_in_background =
|
||||
ReadSetting(QStringLiteral("pauseWhenInBackground"), false).toBool();
|
||||
UISettings::values.hide_mouse =
|
||||
ReadSetting(QStringLiteral("hideInactiveMouse"), false).toBool();
|
||||
|
||||
ApplyDefaultProfileIfInputInvalid();
|
||||
|
||||
qt_config->endGroup();
|
||||
}
|
||||
|
||||
@@ -869,8 +853,9 @@ void Config::SavePlayerValues() {
|
||||
const auto& player = Settings::values.players[p];
|
||||
|
||||
WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false);
|
||||
WriteSetting(QStringLiteral("player_%1_type").arg(p), static_cast<u8>(player.type),
|
||||
static_cast<u8>(Settings::ControllerType::DualJoycon));
|
||||
WriteSetting(QStringLiteral("player_%1_type").arg(p),
|
||||
static_cast<u8>(player.controller_type),
|
||||
static_cast<u8>(Settings::ControllerType::ProController));
|
||||
|
||||
WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left,
|
||||
Settings::JOYCON_BODY_NEON_BLUE);
|
||||
@@ -990,6 +975,7 @@ void Config::SaveControlValues() {
|
||||
SaveMouseValues();
|
||||
SaveTouchscreenValues();
|
||||
|
||||
WriteSetting(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, true);
|
||||
WriteSetting(QStringLiteral("motion_device"),
|
||||
QString::fromStdString(Settings::values.motion_device),
|
||||
QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01"));
|
||||
@@ -1036,7 +1022,7 @@ void Config::SaveDataStorageValues() {
|
||||
WriteSetting(QStringLiteral("gamecard_current_game"), Settings::values.gamecard_current_game,
|
||||
false);
|
||||
WriteSetting(QStringLiteral("gamecard_path"),
|
||||
QString::fromStdString(Settings::values.gamecard_path), QStringLiteral(""));
|
||||
QString::fromStdString(Settings::values.gamecard_path), QString{});
|
||||
|
||||
qt_config->endGroup();
|
||||
}
|
||||
@@ -1049,7 +1035,7 @@ void Config::SaveDebuggingValues() {
|
||||
WriteSetting(QStringLiteral("use_gdbstub"), Settings::values.use_gdbstub, false);
|
||||
WriteSetting(QStringLiteral("gdbstub_port"), Settings::values.gdbstub_port, 24689);
|
||||
WriteSetting(QStringLiteral("program_args"),
|
||||
QString::fromStdString(Settings::values.program_args), QStringLiteral(""));
|
||||
QString::fromStdString(Settings::values.program_args), QString{});
|
||||
WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false);
|
||||
WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false);
|
||||
WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false);
|
||||
@@ -1076,8 +1062,7 @@ void Config::SaveDisabledAddOnValues() {
|
||||
qt_config->beginWriteArray(QStringLiteral("disabled"));
|
||||
for (std::size_t j = 0; j < elem.second.size(); ++j) {
|
||||
qt_config->setArrayIndex(static_cast<int>(j));
|
||||
WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]),
|
||||
QStringLiteral(""));
|
||||
WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]), QString{});
|
||||
}
|
||||
qt_config->endArray();
|
||||
++i;
|
||||
@@ -1266,7 +1251,6 @@ void Config::SaveUIValues() {
|
||||
WriteSetting(QStringLiteral("firstStart"), UISettings::values.first_start, true);
|
||||
WriteSetting(QStringLiteral("calloutFlags"), UISettings::values.callout_flags, 0);
|
||||
WriteSetting(QStringLiteral("showConsole"), UISettings::values.show_console, false);
|
||||
WriteSetting(QStringLiteral("profileIndex"), UISettings::values.profile_index, 0);
|
||||
WriteSetting(QStringLiteral("pauseWhenInBackground"),
|
||||
UISettings::values.pause_when_in_background, false);
|
||||
WriteSetting(QStringLiteral("hideInactiveMouse"), UISettings::values.hide_mouse, false);
|
||||
|
||||
@@ -23,7 +23,9 @@ public:
|
||||
void Save();
|
||||
|
||||
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
|
||||
static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs;
|
||||
static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs;
|
||||
static const int default_lstick_mod;
|
||||
static const int default_rstick_mod;
|
||||
static const std::array<int, Settings::NativeMouseButton::NumMouseButtons>
|
||||
default_mouse_buttons;
|
||||
static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys;
|
||||
@@ -37,7 +39,6 @@ private:
|
||||
void ReadKeyboardValues();
|
||||
void ReadMouseValues();
|
||||
void ReadTouchscreenValues();
|
||||
void ApplyDefaultProfileIfInputInvalid();
|
||||
|
||||
// Read functions bases off the respective config section names.
|
||||
void ReadAudioValues();
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>382</width>
|
||||
<width>650</width>
|
||||
<height>650</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -26,13 +26,13 @@
|
||||
<widget class="QListWidget" name="selectorList">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<width>120</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
@@ -44,76 +44,121 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="ConfigureGeneral" name="generalTab">
|
||||
<property name="accessibleName">
|
||||
<string>General</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>General</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureUi" name="uiTab">
|
||||
<property name="accessibleName">
|
||||
<string>UI</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Game List</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureSystem" name="systemTab">
|
||||
<property name="accessibleName">
|
||||
<string>System</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>System</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureProfileManager" name="profileManagerTab">
|
||||
<property name="accessibleName">
|
||||
<string>Profiles</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Profiles</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureFilesystem" name="filesystemTab">
|
||||
<property name="accessibleName">
|
||||
<string>Filesystem</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Filesystem</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureInputSimple" name="inputTab">
|
||||
<widget class="ConfigureInput" name="inputTab">
|
||||
<property name="accessibleName">
|
||||
<string>Controls</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Input</string>
|
||||
<string>Controls</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureHotkeys" name="hotkeysTab">
|
||||
<property name="accessibleName">
|
||||
<string>Hotkeys</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Hotkeys</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureCpu" name="cpuTab">
|
||||
<property name="accessibleName">
|
||||
<string>CPU</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>CPU</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureCpuDebug" name="cpuDebugTab">
|
||||
<property name="accessibleName">
|
||||
<string>Debug</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Debug</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureGraphics" name="graphicsTab">
|
||||
<property name="accessibleName">
|
||||
<string>Graphics</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Graphics</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureGraphicsAdvanced" name="graphicsAdvancedTab">
|
||||
<property name="accessibleName">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>GraphicsAdvanced</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureAudio" name="audioTab">
|
||||
<property name="accessibleName">
|
||||
<string>Audio</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Audio</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureDebug" name="debugTab">
|
||||
<property name="accessibleName">
|
||||
<string>Debug</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Debug</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureWeb" name="webTab">
|
||||
<property name="accessibleName">
|
||||
<string>Web</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Web</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="ConfigureService" name="serviceTab">
|
||||
<property name="accessibleName">
|
||||
<string>Services</string>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Services</string>
|
||||
</attribute>
|
||||
@@ -205,9 +250,9 @@
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ConfigureInputSimple</class>
|
||||
<class>ConfigureInput</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>configuration/configure_input_simple.h</header>
|
||||
<header>configuration/configure_input.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "ui_configure_debug_controller.h"
|
||||
#include "yuzu/configuration/configure_debug_controller.h"
|
||||
|
||||
ConfigureDebugController::ConfigureDebugController(QWidget* parent)
|
||||
: QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()),
|
||||
debug_controller(new ConfigureInputPlayer(this, 9, nullptr, true)) {
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->controllerLayout->addWidget(debug_controller);
|
||||
|
||||
connect(ui->clear_all_button, &QPushButton::clicked, this,
|
||||
[this] { debug_controller->ClearAll(); });
|
||||
connect(ui->restore_defaults_button, &QPushButton::clicked, this,
|
||||
[this] { debug_controller->RestoreDefaults(); });
|
||||
|
||||
RetranslateUI();
|
||||
}
|
||||
|
||||
ConfigureDebugController::~ConfigureDebugController() = default;
|
||||
|
||||
void ConfigureDebugController::ApplyConfiguration() {
|
||||
debug_controller->ApplyConfiguration();
|
||||
}
|
||||
|
||||
void ConfigureDebugController::changeEvent(QEvent* event) {
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
RetranslateUI();
|
||||
}
|
||||
|
||||
QDialog::changeEvent(event);
|
||||
}
|
||||
|
||||
void ConfigureDebugController::RetranslateUI() {
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <QDialog>
|
||||
#include "yuzu/configuration/configure_input_player.h"
|
||||
|
||||
class QPushButton;
|
||||
|
||||
namespace Ui {
|
||||
class ConfigureDebugController;
|
||||
}
|
||||
|
||||
class ConfigureDebugController : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureDebugController(QWidget* parent);
|
||||
~ConfigureDebugController() override;
|
||||
|
||||
void ApplyConfiguration();
|
||||
|
||||
private:
|
||||
void changeEvent(QEvent* event) override;
|
||||
void RetranslateUI();
|
||||
|
||||
std::unique_ptr<Ui::ConfigureDebugController> ui;
|
||||
|
||||
ConfigureInputPlayer* debug_controller;
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ConfigureDebugController</class>
|
||||
<widget class="QDialog" name="ConfigureDebugController">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>780</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure Debug Controller</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="controllerLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="clear_all_button">
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="restore_defaults_button">
|
||||
<property name="text">
|
||||
<string>Defaults</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ConfigureDebugController</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>140</x>
|
||||
<y>318</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>140</x>
|
||||
<y>169</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ConfigureDebugController</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>140</x>
|
||||
<y>318</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>140</x>
|
||||
<y>169</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -80,12 +80,12 @@ Q_DECLARE_METATYPE(QList<QWidget*>);
|
||||
|
||||
void ConfigureDialog::PopulateSelectionList() {
|
||||
const std::array<std::pair<QString, QList<QWidget*>>, 6> items{
|
||||
{{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->uiTab}},
|
||||
{{tr("General"), {ui->generalTab, ui->hotkeysTab, ui->uiTab, ui->webTab, ui->debugTab}},
|
||||
{tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}},
|
||||
{tr("CPU"), {ui->cpuTab, ui->cpuDebugTab}},
|
||||
{tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}},
|
||||
{tr("Audio"), {ui->audioTab}},
|
||||
{tr("Controls"), {ui->inputTab, ui->hotkeysTab}}},
|
||||
{tr("Controls"), ui->inputTab->GetSubTabs()}},
|
||||
};
|
||||
|
||||
[[maybe_unused]] const QSignalBlocker blocker(ui->selectorList);
|
||||
@@ -117,7 +117,7 @@ void ConfigureDialog::UpdateVisibleTabs() {
|
||||
{ui->generalTab, tr("General")},
|
||||
{ui->systemTab, tr("System")},
|
||||
{ui->profileManagerTab, tr("Profiles")},
|
||||
{ui->inputTab, tr("Input")},
|
||||
{ui->inputTab, tr("Controls")},
|
||||
{ui->hotkeysTab, tr("Hotkeys")},
|
||||
{ui->cpuTab, tr("CPU")},
|
||||
{ui->cpuDebugTab, tr("Debug")},
|
||||
@@ -138,6 +138,6 @@ void ConfigureDialog::UpdateVisibleTabs() {
|
||||
const QList<QWidget*> tabs = qvariant_cast<QList<QWidget*>>(items[0]->data(Qt::UserRole));
|
||||
|
||||
for (const auto tab : tabs) {
|
||||
ui->tabWidget->addTab(tab, widgets.at(tab));
|
||||
ui->tabWidget->addTab(tab, tab->accessibleName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,18 +8,32 @@
|
||||
#include <QSignalBlocker>
|
||||
#include <QTimer>
|
||||
|
||||
#include "configuration/configure_touchscreen_advanced.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applet_ae.h"
|
||||
#include "core/hle/service/am/applet_oe.h"
|
||||
#include "core/hle/service/hid/controllers/npad.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "ui_configure_input.h"
|
||||
#include "ui_configure_input_advanced.h"
|
||||
#include "ui_configure_input_player.h"
|
||||
#include "yuzu/configuration/configure_debug_controller.h"
|
||||
#include "yuzu/configuration/configure_input.h"
|
||||
#include "yuzu/configuration/configure_input_advanced.h"
|
||||
#include "yuzu/configuration/configure_input_player.h"
|
||||
#include "yuzu/configuration/configure_mouse_advanced.h"
|
||||
#include "yuzu/configuration/configure_touchscreen_advanced.h"
|
||||
|
||||
namespace {
|
||||
template <typename Dialog, typename... Args>
|
||||
void CallConfigureDialog(ConfigureInput& parent, Args&&... args) {
|
||||
Dialog dialog(&parent, std::forward<Args>(args)...);
|
||||
|
||||
const auto res = dialog.exec();
|
||||
if (res == QDialog::Accepted) {
|
||||
dialog.ApplyConfiguration();
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
void OnDockedModeChanged(bool last_state, bool new_state) {
|
||||
if (last_state == new_state) {
|
||||
@@ -48,97 +62,94 @@ void OnDockedModeChanged(bool last_state, bool new_state) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename Dialog, typename... Args>
|
||||
void CallConfigureDialog(ConfigureInput& parent, Args&&... args) {
|
||||
parent.ApplyConfiguration();
|
||||
Dialog dialog(&parent, std::forward<Args>(args)...);
|
||||
|
||||
const auto res = dialog.exec();
|
||||
if (res == QDialog::Accepted) {
|
||||
dialog.ApplyConfiguration();
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
ConfigureInput::ConfigureInput(QWidget* parent)
|
||||
: QDialog(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
|
||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
|
||||
ui->setupUi(this);
|
||||
|
||||
players_controller = {
|
||||
ui->player1_combobox, ui->player2_combobox, ui->player3_combobox, ui->player4_combobox,
|
||||
ui->player5_combobox, ui->player6_combobox, ui->player7_combobox, ui->player8_combobox,
|
||||
player_controllers = {
|
||||
new ConfigureInputPlayer(this, 0, ui->consoleInputSettings),
|
||||
new ConfigureInputPlayer(this, 1, ui->consoleInputSettings),
|
||||
new ConfigureInputPlayer(this, 2, ui->consoleInputSettings),
|
||||
new ConfigureInputPlayer(this, 3, ui->consoleInputSettings),
|
||||
new ConfigureInputPlayer(this, 4, ui->consoleInputSettings),
|
||||
new ConfigureInputPlayer(this, 5, ui->consoleInputSettings),
|
||||
new ConfigureInputPlayer(this, 6, ui->consoleInputSettings),
|
||||
new ConfigureInputPlayer(this, 7, ui->consoleInputSettings),
|
||||
};
|
||||
|
||||
players_configure = {
|
||||
ui->player1_configure, ui->player2_configure, ui->player3_configure, ui->player4_configure,
|
||||
ui->player5_configure, ui->player6_configure, ui->player7_configure, ui->player8_configure,
|
||||
player_tabs = {
|
||||
ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4,
|
||||
ui->tabPlayer5, ui->tabPlayer6, ui->tabPlayer7, ui->tabPlayer8,
|
||||
};
|
||||
|
||||
player_connected = {
|
||||
ui->checkboxPlayer1Connected, ui->checkboxPlayer2Connected, ui->checkboxPlayer3Connected,
|
||||
ui->checkboxPlayer4Connected, ui->checkboxPlayer5Connected, ui->checkboxPlayer6Connected,
|
||||
ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected,
|
||||
};
|
||||
|
||||
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]);
|
||||
connect(player_controllers[i], &ConfigureInputPlayer::Connected, [&, i](bool is_connected) {
|
||||
if (is_connected) {
|
||||
for (std::size_t index = 0; index <= i; ++index) {
|
||||
player_connected[index]->setChecked(is_connected);
|
||||
}
|
||||
} else {
|
||||
for (std::size_t index = i; index < player_tabs.size(); ++index) {
|
||||
player_connected[index]->setChecked(is_connected);
|
||||
}
|
||||
}
|
||||
});
|
||||
connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices,
|
||||
[this] { UpdateAllInputDevices(); });
|
||||
connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) {
|
||||
player_controllers[i]->ConnectPlayer(state == Qt::Checked);
|
||||
});
|
||||
}
|
||||
// Only the first player can choose handheld mode so connect the signal just to player 1
|
||||
connect(player_controllers[0], &ConfigureInputPlayer::HandheldStateChanged,
|
||||
[this](bool is_handheld) { UpdateDockedState(is_handheld); });
|
||||
|
||||
advanced = new ConfigureInputAdvanced(this);
|
||||
ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced));
|
||||
ui->tabAdvanced->layout()->addWidget(advanced);
|
||||
connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog,
|
||||
[this] { CallConfigureDialog<ConfigureDebugController>(*this); });
|
||||
connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog,
|
||||
[this] { CallConfigureDialog<ConfigureMouseAdvanced>(*this); });
|
||||
connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog,
|
||||
[this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); });
|
||||
|
||||
connect(ui->buttonClearAll, &QPushButton::clicked, [this] { ClearAll(); });
|
||||
connect(ui->buttonRestoreDefaults, &QPushButton::clicked, [this] { RestoreDefaults(); });
|
||||
|
||||
RetranslateUI();
|
||||
LoadConfiguration();
|
||||
UpdateUIEnabled();
|
||||
|
||||
connect(ui->restore_defaults_button, &QPushButton::clicked, this,
|
||||
&ConfigureInput::RestoreDefaults);
|
||||
|
||||
for (auto* enabled : players_controller) {
|
||||
connect(enabled, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&ConfigureInput::UpdateUIEnabled);
|
||||
}
|
||||
connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled);
|
||||
connect(ui->handheld_connected, &QCheckBox::stateChanged, this,
|
||||
&ConfigureInput::UpdateUIEnabled);
|
||||
connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled);
|
||||
connect(ui->keyboard_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled);
|
||||
connect(ui->debug_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled);
|
||||
connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this,
|
||||
&ConfigureInput::UpdateUIEnabled);
|
||||
|
||||
for (std::size_t i = 0; i < players_configure.size(); ++i) {
|
||||
connect(players_configure[i], &QPushButton::clicked, this,
|
||||
[this, i] { CallConfigureDialog<ConfigureInputPlayer>(*this, i, false); });
|
||||
}
|
||||
|
||||
connect(ui->handheld_configure, &QPushButton::clicked, this,
|
||||
[this] { CallConfigureDialog<ConfigureInputPlayer>(*this, 8, false); });
|
||||
|
||||
connect(ui->debug_configure, &QPushButton::clicked, this,
|
||||
[this] { CallConfigureDialog<ConfigureInputPlayer>(*this, 9, true); });
|
||||
|
||||
connect(ui->mouse_advanced, &QPushButton::clicked, this,
|
||||
[this] { CallConfigureDialog<ConfigureMouseAdvanced>(*this); });
|
||||
|
||||
connect(ui->touchscreen_advanced, &QPushButton::clicked, this,
|
||||
[this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); });
|
||||
}
|
||||
|
||||
ConfigureInput::~ConfigureInput() = default;
|
||||
|
||||
QList<QWidget*> ConfigureInput::GetSubTabs() const {
|
||||
return {
|
||||
ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4, ui->tabPlayer5,
|
||||
ui->tabPlayer6, ui->tabPlayer7, ui->tabPlayer8, ui->tabAdvanced,
|
||||
};
|
||||
}
|
||||
|
||||
void ConfigureInput::ApplyConfiguration() {
|
||||
for (std::size_t i = 0; i < players_controller.size(); ++i) {
|
||||
const auto controller_type_index = players_controller[i]->currentIndex();
|
||||
|
||||
Settings::values.players[i].connected = controller_type_index != 0;
|
||||
|
||||
if (controller_type_index > 0) {
|
||||
Settings::values.players[i].type =
|
||||
static_cast<Settings::ControllerType>(controller_type_index - 1);
|
||||
} else {
|
||||
Settings::values.players[i].type = Settings::ControllerType::DualJoycon;
|
||||
}
|
||||
for (auto controller : player_controllers) {
|
||||
controller->ApplyConfiguration();
|
||||
}
|
||||
|
||||
advanced->ApplyConfiguration();
|
||||
|
||||
const bool pre_docked_mode = Settings::values.use_docked_mode;
|
||||
Settings::values.use_docked_mode = ui->use_docked_mode->isChecked();
|
||||
Settings::values.use_docked_mode = ui->radioDocked->isChecked();
|
||||
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode);
|
||||
Settings::values
|
||||
.players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)]
|
||||
.connected = ui->handheld_connected->isChecked();
|
||||
Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked();
|
||||
Settings::values.mouse_enabled = ui->mouse_enabled->isChecked();
|
||||
Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked();
|
||||
Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked();
|
||||
|
||||
Settings::values.vibration_enabled = ui->vibrationGroup->isChecked();
|
||||
}
|
||||
|
||||
void ConfigureInput::changeEvent(QEvent* event) {
|
||||
@@ -146,94 +157,63 @@ void ConfigureInput::changeEvent(QEvent* event) {
|
||||
RetranslateUI();
|
||||
}
|
||||
|
||||
QDialog::changeEvent(event);
|
||||
QWidget::changeEvent(event);
|
||||
}
|
||||
|
||||
void ConfigureInput::RetranslateUI() {
|
||||
ui->retranslateUi(this);
|
||||
RetranslateControllerComboBoxes();
|
||||
}
|
||||
|
||||
void ConfigureInput::RetranslateControllerComboBoxes() {
|
||||
for (auto* controller_box : players_controller) {
|
||||
[[maybe_unused]] const QSignalBlocker blocker(controller_box);
|
||||
|
||||
controller_box->clear();
|
||||
controller_box->addItems({tr("None"), tr("Pro Controller"), tr("Dual Joycons"),
|
||||
tr("Single Right Joycon"), tr("Single Left Joycon")});
|
||||
}
|
||||
|
||||
LoadPlayerControllerIndices();
|
||||
}
|
||||
|
||||
void ConfigureInput::UpdateUIEnabled() {
|
||||
bool hit_disabled = false;
|
||||
for (auto* player : players_controller) {
|
||||
player->setDisabled(hit_disabled);
|
||||
if (hit_disabled) {
|
||||
player->setCurrentIndex(0);
|
||||
}
|
||||
if (!hit_disabled && player->currentIndex() == 0) {
|
||||
hit_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < players_controller.size(); ++i) {
|
||||
players_configure[i]->setEnabled(players_controller[i]->currentIndex() != 0);
|
||||
}
|
||||
|
||||
ui->handheld_connected->setChecked(ui->handheld_connected->isChecked() &&
|
||||
!ui->use_docked_mode->isChecked());
|
||||
ui->handheld_connected->setEnabled(!ui->use_docked_mode->isChecked());
|
||||
ui->handheld_configure->setEnabled(ui->handheld_connected->isChecked() &&
|
||||
!ui->use_docked_mode->isChecked());
|
||||
ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked());
|
||||
ui->debug_configure->setEnabled(ui->debug_enabled->isChecked());
|
||||
ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked());
|
||||
}
|
||||
|
||||
void ConfigureInput::LoadConfiguration() {
|
||||
std::stable_partition(
|
||||
Settings::values.players.begin(),
|
||||
Settings::values.players.begin() +
|
||||
Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD),
|
||||
[](const auto& player) { return player.connected; });
|
||||
|
||||
LoadPlayerControllerIndices();
|
||||
UpdateDockedState(Settings::values.players[0].controller_type ==
|
||||
Settings::ControllerType::Handheld);
|
||||
|
||||
ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
|
||||
ui->handheld_connected->setChecked(
|
||||
Settings::values
|
||||
.players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)]
|
||||
.connected);
|
||||
ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled);
|
||||
ui->mouse_enabled->setChecked(Settings::values.mouse_enabled);
|
||||
ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled);
|
||||
ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled);
|
||||
|
||||
UpdateUIEnabled();
|
||||
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled);
|
||||
}
|
||||
|
||||
void ConfigureInput::LoadPlayerControllerIndices() {
|
||||
for (std::size_t i = 0; i < players_controller.size(); ++i) {
|
||||
const auto connected = Settings::values.players[i].connected;
|
||||
players_controller[i]->setCurrentIndex(
|
||||
connected ? static_cast<u8>(Settings::values.players[i].type) + 1 : 0);
|
||||
for (std::size_t i = 0; i < player_connected.size(); ++i) {
|
||||
const auto connected = Settings::values.players[i].connected ||
|
||||
(i == 0 && Settings::values.players[8].connected);
|
||||
player_connected[i]->setChecked(connected);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureInput::ClearAll() {
|
||||
// We don't have a good way to know what tab is active, but we can find out by getting the
|
||||
// parent of the consoleInputSettings
|
||||
auto* player_tab = static_cast<ConfigureInputPlayer*>(ui->consoleInputSettings->parent());
|
||||
player_tab->ClearAll();
|
||||
}
|
||||
|
||||
void ConfigureInput::RestoreDefaults() {
|
||||
players_controller[0]->setCurrentIndex(2);
|
||||
// We don't have a good way to know what tab is active, but we can find out by getting the
|
||||
// parent of the consoleInputSettings
|
||||
auto* player_tab = static_cast<ConfigureInputPlayer*>(ui->consoleInputSettings->parent());
|
||||
player_tab->RestoreDefaults();
|
||||
|
||||
for (std::size_t i = 1; i < players_controller.size(); ++i) {
|
||||
players_controller[i]->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
ui->use_docked_mode->setCheckState(Qt::Unchecked);
|
||||
ui->handheld_connected->setCheckState(Qt::Unchecked);
|
||||
ui->mouse_enabled->setCheckState(Qt::Unchecked);
|
||||
ui->keyboard_enabled->setCheckState(Qt::Unchecked);
|
||||
ui->debug_enabled->setCheckState(Qt::Unchecked);
|
||||
ui->touchscreen_enabled->setCheckState(Qt::Checked);
|
||||
UpdateUIEnabled();
|
||||
ui->radioDocked->setChecked(true);
|
||||
ui->radioUndocked->setChecked(false);
|
||||
ui->vibrationGroup->setChecked(true);
|
||||
}
|
||||
|
||||
void ConfigureInput::UpdateDockedState(bool is_handheld) {
|
||||
// If the controller type is handheld only, disallow changing docked mode
|
||||
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)
|
||||
if (is_handheld) {
|
||||
ui->radioUndocked->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureInput::UpdateAllInputDevices() {
|
||||
for (const auto& player : player_controllers) {
|
||||
player->UpdateInputDevices();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,12 @@
|
||||
#include <QDialog>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "yuzu/configuration/configure_input_advanced.h"
|
||||
#include "yuzu/configuration/configure_input_player.h"
|
||||
|
||||
#include "ui_configure_input.h"
|
||||
|
||||
class QPushButton;
|
||||
class QCheckBox;
|
||||
class QString;
|
||||
class QTimer;
|
||||
|
||||
@@ -22,22 +25,25 @@ class ConfigureInput;
|
||||
|
||||
void OnDockedModeChanged(bool last_state, bool new_state);
|
||||
|
||||
class ConfigureInput : public QDialog {
|
||||
class ConfigureInput : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureInput(QWidget* parent = nullptr);
|
||||
~ConfigureInput() override;
|
||||
|
||||
/// Save all button configurations to settings file
|
||||
/// Save all button configurations to settings file.
|
||||
void ApplyConfiguration();
|
||||
|
||||
QList<QWidget*> GetSubTabs() const;
|
||||
|
||||
private:
|
||||
void changeEvent(QEvent* event) override;
|
||||
void RetranslateUI();
|
||||
void RetranslateControllerComboBoxes();
|
||||
void ClearAll();
|
||||
|
||||
void UpdateUIEnabled();
|
||||
void UpdateDockedState(bool is_handheld);
|
||||
void UpdateAllInputDevices();
|
||||
|
||||
/// Load configuration settings.
|
||||
void LoadConfiguration();
|
||||
@@ -48,6 +54,8 @@ private:
|
||||
|
||||
std::unique_ptr<Ui::ConfigureInput> ui;
|
||||
|
||||
std::array<QComboBox*, 8> players_controller;
|
||||
std::array<QPushButton*, 8> players_configure;
|
||||
std::array<ConfigureInputPlayer*, 8> player_controllers;
|
||||
std::array<QWidget*, 8> player_tabs;
|
||||
std::array<QCheckBox*, 8> player_connected;
|
||||
ConfigureInputAdvanced* advanced;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <QColorDialog>
|
||||
#include "core/core.h"
|
||||
#include "core/settings.h"
|
||||
#include "ui_configure_input_advanced.h"
|
||||
#include "yuzu/configuration/configure_input_advanced.h"
|
||||
|
||||
ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)
|
||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInputAdvanced>()) {
|
||||
ui->setupUi(this);
|
||||
|
||||
controllers_color_buttons = {{
|
||||
{
|
||||
ui->player1_left_body_button,
|
||||
ui->player1_left_buttons_button,
|
||||
ui->player1_right_body_button,
|
||||
ui->player1_right_buttons_button,
|
||||
},
|
||||
{
|
||||
ui->player2_left_body_button,
|
||||
ui->player2_left_buttons_button,
|
||||
ui->player2_right_body_button,
|
||||
ui->player2_right_buttons_button,
|
||||
},
|
||||
{
|
||||
ui->player3_left_body_button,
|
||||
ui->player3_left_buttons_button,
|
||||
ui->player3_right_body_button,
|
||||
ui->player3_right_buttons_button,
|
||||
},
|
||||
{
|
||||
ui->player4_left_body_button,
|
||||
ui->player4_left_buttons_button,
|
||||
ui->player4_right_body_button,
|
||||
ui->player4_right_buttons_button,
|
||||
},
|
||||
{
|
||||
ui->player5_left_body_button,
|
||||
ui->player5_left_buttons_button,
|
||||
ui->player5_right_body_button,
|
||||
ui->player5_right_buttons_button,
|
||||
},
|
||||
{
|
||||
ui->player6_left_body_button,
|
||||
ui->player6_left_buttons_button,
|
||||
ui->player6_right_body_button,
|
||||
ui->player6_right_buttons_button,
|
||||
},
|
||||
{
|
||||
ui->player7_left_body_button,
|
||||
ui->player7_left_buttons_button,
|
||||
ui->player7_right_body_button,
|
||||
ui->player7_right_buttons_button,
|
||||
},
|
||||
{
|
||||
ui->player8_left_body_button,
|
||||
ui->player8_left_buttons_button,
|
||||
ui->player8_right_body_button,
|
||||
ui->player8_right_buttons_button,
|
||||
},
|
||||
}};
|
||||
|
||||
for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) {
|
||||
auto& color_buttons = controllers_color_buttons[player_idx];
|
||||
for (std::size_t button_idx = 0; button_idx < color_buttons.size(); ++button_idx) {
|
||||
connect(color_buttons[button_idx], &QPushButton::clicked, this,
|
||||
[this, player_idx, button_idx] {
|
||||
OnControllerButtonClick(static_cast<int>(player_idx),
|
||||
static_cast<int>(button_idx));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
connect(ui->mouse_enabled, &QCheckBox::stateChanged, this,
|
||||
&ConfigureInputAdvanced::UpdateUIEnabled);
|
||||
connect(ui->debug_enabled, &QCheckBox::stateChanged, this,
|
||||
&ConfigureInputAdvanced::UpdateUIEnabled);
|
||||
connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this,
|
||||
&ConfigureInputAdvanced::UpdateUIEnabled);
|
||||
|
||||
connect(ui->debug_configure, &QPushButton::clicked, this,
|
||||
[this] { CallDebugControllerDialog(); });
|
||||
connect(ui->mouse_advanced, &QPushButton::clicked, this, [this] { CallMouseConfigDialog(); });
|
||||
connect(ui->touchscreen_advanced, &QPushButton::clicked, this,
|
||||
[this] { CallTouchscreenConfigDialog(); });
|
||||
|
||||
LoadConfiguration();
|
||||
}
|
||||
|
||||
ConfigureInputAdvanced::~ConfigureInputAdvanced() = default;
|
||||
|
||||
void ConfigureInputAdvanced::OnControllerButtonClick(int player_idx, int button_idx) {
|
||||
const QColor new_bg_color = QColorDialog::getColor(controllers_colors[player_idx][button_idx]);
|
||||
if (!new_bg_color.isValid()) {
|
||||
return;
|
||||
}
|
||||
controllers_colors[player_idx][button_idx] = new_bg_color;
|
||||
controllers_color_buttons[player_idx][button_idx]->setStyleSheet(
|
||||
QStringLiteral("background-color: %1; min-width: 55px;")
|
||||
.arg(controllers_colors[player_idx][button_idx].name()));
|
||||
}
|
||||
|
||||
void ConfigureInputAdvanced::ApplyConfiguration() {
|
||||
for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) {
|
||||
auto& player = Settings::values.players[player_idx];
|
||||
std::array<u32, 4> colors{};
|
||||
std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(),
|
||||
colors.begin(), [](QColor color) { return color.rgb(); });
|
||||
|
||||
player.body_color_left = colors[0];
|
||||
player.button_color_left = colors[1];
|
||||
player.body_color_right = colors[2];
|
||||
player.button_color_right = colors[3];
|
||||
}
|
||||
|
||||
Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked();
|
||||
Settings::values.mouse_enabled = ui->mouse_enabled->isChecked();
|
||||
Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked();
|
||||
Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked();
|
||||
}
|
||||
|
||||
void ConfigureInputAdvanced::LoadConfiguration() {
|
||||
for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) {
|
||||
auto& player = Settings::values.players[player_idx];
|
||||
std::array<u32, 4> colors = {
|
||||
player.body_color_left,
|
||||
player.button_color_left,
|
||||
player.body_color_right,
|
||||
player.button_color_right,
|
||||
};
|
||||
|
||||
std::transform(colors.begin(), colors.end(), controllers_colors[player_idx].begin(),
|
||||
[](u32 rgb) { return QColor::fromRgb(rgb); });
|
||||
|
||||
for (std::size_t button_idx = 0; button_idx < colors.size(); ++button_idx) {
|
||||
controllers_color_buttons[player_idx][button_idx]->setStyleSheet(
|
||||
QStringLiteral("background-color: %1; min-width: 55px;")
|
||||
.arg(controllers_colors[player_idx][button_idx].name()));
|
||||
}
|
||||
}
|
||||
|
||||
ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled);
|
||||
ui->mouse_enabled->setChecked(Settings::values.mouse_enabled);
|
||||
ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled);
|
||||
ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled);
|
||||
|
||||
UpdateUIEnabled();
|
||||
}
|
||||
|
||||
void ConfigureInputAdvanced::changeEvent(QEvent* event) {
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
RetranslateUI();
|
||||
}
|
||||
|
||||
QWidget::changeEvent(event);
|
||||
}
|
||||
|
||||
void ConfigureInputAdvanced::RetranslateUI() {
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
|
||||
void ConfigureInputAdvanced::UpdateUIEnabled() {
|
||||
ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked());
|
||||
ui->debug_configure->setEnabled(ui->debug_enabled->isChecked());
|
||||
ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked());
|
||||
}
|
||||
@@ -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 <array>
|
||||
#include <memory>
|
||||
#include <QWidget>
|
||||
|
||||
class QColor;
|
||||
class QPushButton;
|
||||
|
||||
namespace Ui {
|
||||
class ConfigureInputAdvanced;
|
||||
}
|
||||
|
||||
class ConfigureInputAdvanced : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureInputAdvanced(QWidget* parent = nullptr);
|
||||
~ConfigureInputAdvanced() override;
|
||||
|
||||
void ApplyConfiguration();
|
||||
|
||||
signals:
|
||||
void CallDebugControllerDialog();
|
||||
void CallMouseConfigDialog();
|
||||
void CallTouchscreenConfigDialog();
|
||||
|
||||
private:
|
||||
void changeEvent(QEvent* event) override;
|
||||
void RetranslateUI();
|
||||
void UpdateUIEnabled();
|
||||
|
||||
void OnControllerButtonClick(int player_idx, int button_idx);
|
||||
|
||||
void LoadConfiguration();
|
||||
|
||||
std::unique_ptr<Ui::ConfigureInputAdvanced> ui;
|
||||
|
||||
std::array<std::array<QColor, 4>, 8> controllers_colors;
|
||||
std::array<std::array<QPushButton*, 4>, 8> controllers_color_buttons;
|
||||
};
|
||||