diff options
Diffstat (limited to '')
23 files changed, 1227 insertions, 2333 deletions
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 2b670ddfd..2c70d0548 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -11,7 +11,6 @@ #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/hid/controllers/npad.h" #include "input_common/main.h" -#include "input_common/udp/client.h" #include "yuzu/configuration/config.h" namespace FS = Common::FS; @@ -61,162 +60,6 @@ const std::array<int, 2> Config::default_stick_mod = { 0, }; -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, -}; - -const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> Config::default_keyboard_keys = { - 0, - 0, - 0, - 0, - Qt::Key_A, - Qt::Key_B, - Qt::Key_C, - Qt::Key_D, - Qt::Key_E, - Qt::Key_F, - Qt::Key_G, - Qt::Key_H, - Qt::Key_I, - Qt::Key_J, - Qt::Key_K, - Qt::Key_L, - Qt::Key_M, - Qt::Key_N, - Qt::Key_O, - Qt::Key_P, - Qt::Key_Q, - Qt::Key_R, - Qt::Key_S, - Qt::Key_T, - Qt::Key_U, - Qt::Key_V, - Qt::Key_W, - Qt::Key_X, - Qt::Key_Y, - Qt::Key_Z, - Qt::Key_1, - Qt::Key_2, - Qt::Key_3, - Qt::Key_4, - Qt::Key_5, - Qt::Key_6, - Qt::Key_7, - Qt::Key_8, - Qt::Key_9, - Qt::Key_0, - Qt::Key_Enter, - Qt::Key_Escape, - Qt::Key_Backspace, - Qt::Key_Tab, - Qt::Key_Space, - Qt::Key_Minus, - Qt::Key_Equal, - Qt::Key_BracketLeft, - Qt::Key_BracketRight, - Qt::Key_Backslash, - Qt::Key_Dead_Tilde, - Qt::Key_Semicolon, - Qt::Key_Apostrophe, - Qt::Key_Dead_Grave, - Qt::Key_Comma, - Qt::Key_Period, - Qt::Key_Slash, - Qt::Key_CapsLock, - - Qt::Key_F1, - Qt::Key_F2, - Qt::Key_F3, - Qt::Key_F4, - Qt::Key_F5, - Qt::Key_F6, - Qt::Key_F7, - Qt::Key_F8, - Qt::Key_F9, - Qt::Key_F10, - Qt::Key_F11, - Qt::Key_F12, - - Qt::Key_SysReq, - Qt::Key_ScrollLock, - Qt::Key_Pause, - Qt::Key_Insert, - Qt::Key_Home, - Qt::Key_PageUp, - Qt::Key_Delete, - Qt::Key_End, - Qt::Key_PageDown, - Qt::Key_Right, - Qt::Key_Left, - Qt::Key_Down, - Qt::Key_Up, - - Qt::Key_NumLock, - Qt::Key_Slash, - Qt::Key_Asterisk, - Qt::Key_Minus, - Qt::Key_Plus, - Qt::Key_Enter, - Qt::Key_1, - Qt::Key_2, - Qt::Key_3, - Qt::Key_4, - Qt::Key_5, - Qt::Key_6, - Qt::Key_7, - Qt::Key_8, - Qt::Key_9, - Qt::Key_0, - Qt::Key_Period, - - 0, - 0, - Qt::Key_PowerOff, - Qt::Key_Equal, - - Qt::Key_F13, - Qt::Key_F14, - Qt::Key_F15, - Qt::Key_F16, - Qt::Key_F17, - Qt::Key_F18, - Qt::Key_F19, - Qt::Key_F20, - Qt::Key_F21, - Qt::Key_F22, - Qt::Key_F23, - Qt::Key_F24, - - Qt::Key_Open, - Qt::Key_Help, - Qt::Key_Menu, - 0, - Qt::Key_Stop, - Qt::Key_AudioRepeat, - Qt::Key_Undo, - Qt::Key_Cut, - Qt::Key_Copy, - Qt::Key_Paste, - Qt::Key_Find, - Qt::Key_VolumeMute, - Qt::Key_VolumeUp, - Qt::Key_VolumeDown, - Qt::Key_CapsLock, - Qt::Key_NumLock, - Qt::Key_ScrollLock, - Qt::Key_Comma, - - Qt::Key_ParenLeft, - Qt::Key_ParenRight, -}; - -const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default_keyboard_mods = { - Qt::Key_Control, Qt::Key_Shift, Qt::Key_Alt, Qt::Key_ApplicationLeft, - Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight, -}; - // This shouldn't have anything except static initializers (no functions). So // QKeySequence(...).toString() is NOT ALLOWED HERE. // This must be in alphabetical order according to action name as it must have the same order as @@ -430,18 +273,6 @@ void Config::ReadPlayerValue(std::size_t player_index) { } } - for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) { - auto& player_vibrations = player.vibrations[i]; - - player_vibrations = - qt_config - ->value(QStringLiteral("%1").arg(player_prefix) + - QString::fromUtf8(Settings::NativeVibration::mapping[i]), - QString{}) - .toString() - .toStdString(); - } - for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); auto& player_motions = player.motions[i]; @@ -496,35 +327,10 @@ void Config::ReadDebugValues() { void Config::ReadKeyboardValues() { ReadBasicSetting(Settings::values.keyboard_enabled); - - std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(), - Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); - std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), - Settings::values.keyboard_keys.begin() + - Settings::NativeKeyboard::LeftControlKey, - InputCommon::GenerateKeyboardParam); - std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), - Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam); } void Config::ReadMouseValues() { ReadBasicSetting(Settings::values.mouse_enabled); - - for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - const std::string default_param = - InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); - auto& mouse_buttons = Settings::values.mouse_buttons[i]; - - mouse_buttons = qt_config - ->value(QStringLiteral("mouse_") + - QString::fromUtf8(Settings::NativeMouseButton::mapping[i]), - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (mouse_buttons.empty()) { - mouse_buttons = default_param; - } - } } void Config::ReadTouchscreenValues() { @@ -574,7 +380,6 @@ void Config::ReadControlValues() { ReadBasicSetting(Settings::values.tas_enable); ReadBasicSetting(Settings::values.tas_loop); - ReadBasicSetting(Settings::values.tas_swap_controllers); ReadBasicSetting(Settings::values.pause_tas_on_load); ReadGlobalSetting(Settings::values.use_docked_mode); @@ -625,13 +430,12 @@ void Config::ReadMotionTouchValues() { } qt_config->endArray(); - ReadBasicSetting(Settings::values.motion_device); ReadBasicSetting(Settings::values.touch_device); - ReadBasicSetting(Settings::values.use_touch_from_button); ReadBasicSetting(Settings::values.touch_from_button_map_index); Settings::values.touch_from_button_map_index = std::clamp( Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); ReadBasicSetting(Settings::values.udp_input_servers); + ReadBasicSetting(Settings::values.enable_udp_controller); } void Config::ReadCoreValues() { @@ -1075,11 +879,6 @@ void Config::SavePlayerValue(std::size_t player_index) { QString::fromStdString(player.analogs[i]), QString::fromStdString(default_param)); } - for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) { - WriteSetting(QStringLiteral("%1").arg(player_prefix) + - QString::fromStdString(Settings::NativeVibration::mapping[i]), - QString::fromStdString(player.vibrations[i]), QString{}); - } for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); WriteSetting(QStringLiteral("%1").arg(player_prefix) + @@ -1111,15 +910,6 @@ void Config::SaveDebugValues() { void Config::SaveMouseValues() { WriteBasicSetting(Settings::values.mouse_enabled); - - for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - const std::string default_param = - InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); - WriteSetting(QStringLiteral("mouse_") + - QString::fromStdString(Settings::NativeMouseButton::mapping[i]), - QString::fromStdString(Settings::values.mouse_buttons[i]), - QString::fromStdString(default_param)); - } } void Config::SaveTouchscreenValues() { @@ -1133,11 +923,10 @@ void Config::SaveTouchscreenValues() { } void Config::SaveMotionTouchValues() { - WriteBasicSetting(Settings::values.motion_device); WriteBasicSetting(Settings::values.touch_device); - WriteBasicSetting(Settings::values.use_touch_from_button); WriteBasicSetting(Settings::values.touch_from_button_map_index); WriteBasicSetting(Settings::values.udp_input_servers); + WriteBasicSetting(Settings::values.enable_udp_controller); qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { @@ -1210,7 +999,6 @@ void Config::SaveControlValues() { WriteBasicSetting(Settings::values.tas_enable); WriteBasicSetting(Settings::values.tas_loop); - WriteBasicSetting(Settings::values.tas_swap_controllers); WriteBasicSetting(Settings::values.pause_tas_on_load); qt_config->endGroup(); diff --git a/src/yuzu/configuration/configure_debug_controller.cpp b/src/yuzu/configuration/configure_debug_controller.cpp index 31ec48384..9a8de92a1 100644 --- a/src/yuzu/configuration/configure_debug_controller.cpp +++ b/src/yuzu/configuration/configure_debug_controller.cpp @@ -2,17 +2,18 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/core.h" +#include "core/hid/hid_core.h" #include "ui_configure_debug_controller.h" #include "yuzu/configuration/configure_debug_controller.h" #include "yuzu/configuration/configure_input_player.h" ConfigureDebugController::ConfigureDebugController(QWidget* parent, InputCommon::InputSubsystem* input_subsystem, - InputProfiles* profiles, Core::System& system) + InputProfiles* profiles, + Core::HID::HIDCore& hid_core, bool is_powered_on) : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()), - debug_controller( - new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, system, true)) { + debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, + hid_core, is_powered_on, true)) { ui->setupUi(this); ui->controllerLayout->addWidget(debug_controller); diff --git a/src/yuzu/configuration/configure_debug_controller.h b/src/yuzu/configuration/configure_debug_controller.h index 6e17c5aa0..d716edbc2 100644 --- a/src/yuzu/configuration/configure_debug_controller.h +++ b/src/yuzu/configuration/configure_debug_controller.h @@ -13,8 +13,8 @@ class ConfigureInputPlayer; class InputProfiles; -namespace Core { -class System; +namespace Core::HID { +class HIDCore; } namespace InputCommon { @@ -30,7 +30,8 @@ class ConfigureDebugController : public QDialog { public: explicit ConfigureDebugController(QWidget* parent, InputCommon::InputSubsystem* input_subsystem, - InputProfiles* profiles, Core::System& system); + InputProfiles* profiles, Core::HID::HIDCore& hid_core, + bool is_powered_on); ~ConfigureDebugController() override; void ApplyConfiguration(); diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 1599299db..d53179dbb 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -10,6 +10,8 @@ #include <QTimer> #include "core/core.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_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" @@ -22,7 +24,6 @@ #include "yuzu/configuration/configure_input_advanced.h" #include "yuzu/configuration/configure_input_player.h" #include "yuzu/configuration/configure_motion_touch.h" -#include "yuzu/configuration/configure_mouse_advanced.h" #include "yuzu/configuration/configure_touchscreen_advanced.h" #include "yuzu/configuration/configure_vibration.h" #include "yuzu/configuration/input_profiles.h" @@ -75,23 +76,25 @@ ConfigureInput::~ConfigureInput() = default; void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, std::size_t max_players) { + const bool is_powered_on = system.IsPoweredOn(); + auto& hid_core = system.HIDCore(); player_controllers = { new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem, profiles.get(), - system), + hid_core, is_powered_on), new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem, profiles.get(), - system), + hid_core, is_powered_on), new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem, profiles.get(), - system), + hid_core, is_powered_on), new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem, profiles.get(), - system), + hid_core, is_powered_on), new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem, profiles.get(), - system), + hid_core, is_powered_on), new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem, profiles.get(), - system), + hid_core, is_powered_on), new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem, profiles.get(), - system), + hid_core, is_powered_on), new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem, profiles.get(), - system), + hid_core, is_powered_on), }; player_tabs = { @@ -114,6 +117,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, 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) { + // Ensures that the controllers are always connected in sequential order if (is_connected) { for (std::size_t index = 0; index <= i; ++index) { player_connected[index]->setChecked(is_connected); @@ -146,13 +150,12 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, advanced = new ConfigureInputAdvanced(this); ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); ui->tabAdvanced->layout()->addWidget(advanced); - connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] { - CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem, profiles.get(), - system); - }); - connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] { - CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem); - }); + + connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, + [this, input_subsystem, &hid_core, is_powered_on] { + CallConfigureDialog<ConfigureDebugController>( + *this, input_subsystem, profiles.get(), hid_core, is_powered_on); + }); connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog, [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); }); connect(advanced, &ConfigureInputAdvanced::CallMotionTouchConfigDialog, @@ -184,22 +187,8 @@ QList<QWidget*> ConfigureInput::GetSubTabs() const { void ConfigureInput::ApplyConfiguration() { for (auto* controller : player_controllers) { controller->ApplyConfiguration(); - controller->TryDisconnectSelectedController(); - } - - // This emulates a delay between disconnecting and reconnecting controllers as some games - // do not respond to a change in controller type if it was instantaneous. - using namespace std::chrono_literals; - std::this_thread::sleep_for(150ms); - - for (auto* controller : player_controllers) { - controller->TryConnectSelectedController(); } - // This emulates a delay between disconnecting and reconnecting controllers as some games - // do not respond to a change in controller type if it was instantaneous. - std::this_thread::sleep_for(150ms); - advanced->ApplyConfiguration(); const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue(); @@ -223,8 +212,10 @@ void ConfigureInput::RetranslateUI() { } void ConfigureInput::LoadConfiguration() { + const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + LoadPlayerControllerIndices(); - UpdateDockedState(Settings::values.players.GetValue()[8].connected); + UpdateDockedState(handheld->IsConnected()); ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue()); ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue()); @@ -232,9 +223,16 @@ void ConfigureInput::LoadConfiguration() { void ConfigureInput::LoadPlayerControllerIndices() { for (std::size_t i = 0; i < player_connected.size(); ++i) { - const auto connected = Settings::values.players.GetValue()[i].connected || - (i == 0 && Settings::values.players.GetValue()[8].connected); - player_connected[i]->setChecked(connected); + if (i == 0) { + auto* handheld = + system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + if (handheld->IsConnected()) { + player_connected[i]->setChecked(true); + continue; + } + } + const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(i); + player_connected[i]->setChecked(controller->IsConnected()); } } diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index b30f09013..65c8e59ac 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -82,7 +82,6 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) 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(); }); connect(ui->buttonMotionTouch, &QPushButton::clicked, this, @@ -131,6 +130,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() { static_cast<float>(ui->mouse_panning_sensitivity->value()); Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); Settings::values.enable_raw_input = ui->enable_raw_input->isChecked(); + Settings::values.enable_udp_controller = ui->enable_udp_controller->isChecked(); } void ConfigureInputAdvanced::LoadConfiguration() { @@ -161,6 +161,7 @@ void ConfigureInputAdvanced::LoadConfiguration() { ui->mouse_panning_sensitivity->setValue(Settings::values.mouse_panning_sensitivity.GetValue()); ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); ui->enable_raw_input->setChecked(Settings::values.enable_raw_input.GetValue()); + ui->enable_udp_controller->setChecked(Settings::values.enable_udp_controller.GetValue()); UpdateUIEnabled(); } @@ -178,7 +179,8 @@ void ConfigureInputAdvanced::RetranslateUI() { } 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()); + ui->mouse_panning->setEnabled(!ui->mouse_enabled->isChecked()); + ui->mouse_panning_sensitivity->setEnabled(!ui->mouse_enabled->isChecked()); } diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui index 9095206a0..df0e4d602 100644 --- a/src/yuzu/configuration/configure_input_advanced.ui +++ b/src/yuzu/configuration/configure_input_advanced.ui @@ -2528,11 +2528,11 @@ <number>0</number> </property> <item> - <widget class="QGroupBox" name="gridGroupBox_3"> + <widget class="QGroupBox" name="emulatedDevicesGroupBox"> <property name="title"> - <string>Other</string> + <string>Emulated Devices</string> </property> - <layout class="QGridLayout" name="gridLayout_3"> + <layout class="QGridLayout" name="emulatedDevicesGridLayout"> <item row="0" column="0"> <widget class="QCheckBox" name="keyboard_enabled"> <property name="minimumSize"> @@ -2547,7 +2547,7 @@ </widget> </item> <item row="1" column="0"> - <widget class="QCheckBox" name="emulate_analog_keyboard"> + <widget class="QCheckBox" name="mouse_enabled"> <property name="minimumSize"> <size> <width>0</width> @@ -2555,53 +2555,18 @@ </size> </property> <property name="text"> - <string>Emulate Analog with Keyboard Input</string> + <string>Mouse</string> </property> </widget> </item> <item row="2" column="0"> - <widget class="QCheckBox" name="mouse_panning"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>23</height> - </size> - </property> + <widget class="QCheckBox" name="touchscreen_enabled"> <property name="text"> - <string>Enable mouse panning</string> + <string>Touchscreen</string> </property> </widget> </item> - <item row="2" column="2"> - <widget class="QSpinBox" name="mouse_panning_sensitivity"> - <property name="toolTip"> - <string>Mouse sensitivity</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - <property name="suffix"> - <string>%</string> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="value"> - <number>100</number> - </property> - </widget> - </item> - <item row="6" column="2"> - <widget class="QPushButton" name="touchscreen_advanced"> - <property name="text"> - <string>Advanced</string> - </property> - </widget> - </item> - <item row="3" column="1"> + <item row="2" column="1"> <spacer name="horizontalSpacer_8"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -2617,80 +2582,130 @@ </property> </spacer> </item> - <item row="3" column="2"> - <widget class="QPushButton" name="mouse_advanced"> - <property name="text"> - <string>Advanced</string> - </property> - </widget> - </item> - <item row="6" column="0"> - <widget class="QCheckBox" name="touchscreen_enabled"> - <property name="text"> - <string>Touchscreen</string> - </property> - </widget> - </item> + <item row="2" column="2"> + <widget class="QPushButton" name="touchscreen_advanced"> + <property name="text"> + <string>Advanced</string> + </property> + </widget> + </item> <item row="3" column="0"> - <widget class="QCheckBox" name="mouse_enabled"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>23</height> - </size> - </property> - <property name="text"> - <string>Mouse</string> - </property> - </widget> - </item> - <item row="8" column="0"> - <widget class="QLabel" name="motion_touch"> - <property name="text"> - <string>Motion / Touch</string> - </property> - </widget> - </item> - <item row="8" column="2"> - <widget class="QPushButton" name="buttonMotionTouch"> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - <item row="7" column="0"> <widget class="QCheckBox" name="debug_enabled"> <property name="text"> <string>Debug Controller</string> </property> </widget> </item> - <item row="7" column="2"> + <item row="3" column="2"> <widget class="QPushButton" name="debug_configure"> <property name="text"> <string>Configure</string> </property> </widget> </item> - <item row="9" column="0"> - <widget class="QCheckBox" name="enable_raw_input"> - <property name="toolTip"> - <string>Requires restarting yuzu</string> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>23</height> - </size> - </property> - <property name="text"> - <string>Enable XInput 8 player support (disables web applet)</string> - </property> - </widget> - </item> </layout> </widget> </item> + <item> + <widget class="QGroupBox" name="otherGroupBox"> + <property name="title"> + <string>Other</string> + </property> + <layout class="QGridLayout" name="OtherGridLayout"> + <item row="1" column="0"> + <widget class="QCheckBox" name="emulate_analog_keyboard"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>23</height> + </size> + </property> + <property name="text"> + <string>Emulate Analog with Keyboard Input</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="enable_raw_input"> + <property name="toolTip"> + <string>Requires restarting yuzu</string> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>23</height> + </size> + </property> + <property name="text"> + <string>Enable XInput 8 player support (disables web applet)</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="enable_udp_controller"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>23</height> + </size> + </property> + <property name="text"> + <string>Enable UDP controllers (not needed for motion)</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QCheckBox" name="mouse_panning"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>23</height> + </size> + </property> + <property name="text"> + <string>Enable mouse panning</string> + </property> + </widget> + </item> + <item row="4" column="2"> + <widget class="QSpinBox" name="mouse_panning_sensitivity"> + <property name="toolTip"> + <string>Mouse sensitivity</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="suffix"> + <string>%</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="motion_touch"> + <property name="text"> + <string>Motion / Touch</string> + </property> + </widget> + </item> + <item row="5" column="2"> + <widget class="QPushButton" name="buttonMotionTouch"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> <item> <spacer name="verticalSpacer"> <property name="orientation"> diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 3aab5d5f8..ec071d6ec 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -12,14 +12,12 @@ #include <QMessageBox> #include <QTimer> #include "common/param_package.h" -#include "core/core.h" -#include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/hid.h" -#include "core/hle/service/sm/sm.h" -#include "input_common/gcadapter/gc_poller.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h" +#include "input_common/drivers/keyboard.h" +#include "input_common/drivers/mouse.h" #include "input_common/main.h" -#include "input_common/mouse/mouse_poller.h" -#include "input_common/udp/udp.h" #include "ui_configure_input_player.h" #include "yuzu/bootmanager.h" #include "yuzu/configuration/config.h" @@ -29,8 +27,6 @@ #include "yuzu/configuration/input_profiles.h" #include "yuzu/util/limitable_input_dialog.h" -using namespace Service::HID; - const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> ConfigureInputPlayer::analog_sub_buttons{{ "up", @@ -41,33 +37,8 @@ const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> namespace { -constexpr std::size_t HANDHELD_INDEX = 8; - -void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, - bool connected, Core::System& system) { - if (!system.IsPoweredOn()) { - return; - } - Service::SM::ServiceManager& sm = system.ServiceManager(); - - auto& npad = sm.GetService<Hid>("hid")->GetAppletResource()->GetController<Controller_NPad>( - HidController::NPad); - - npad.UpdateControllerAt(npad.MapSettingsTypeToNPad(controller_type), npad_index, connected); -} - QString GetKeyName(int key_code) { switch (key_code) { - case Qt::LeftButton: - return QObject::tr("Click 0"); - case Qt::RightButton: - return QObject::tr("Click 1"); - case Qt::MiddleButton: - return QObject::tr("Click 2"); - case Qt::BackButton: - return QObject::tr("Click 3"); - case Qt::ForwardButton: - return QObject::tr("Click 4"); case Qt::Key_Shift: return QObject::tr("Shift"); case Qt::Key_Control: @@ -81,6 +52,61 @@ QString GetKeyName(int key_code) { } } +QString GetButtonName(Common::Input::ButtonNames button_name) { + switch (button_name) { + case Common::Input::ButtonNames::ButtonLeft: + return QObject::tr("Left"); + case Common::Input::ButtonNames::ButtonRight: + return QObject::tr("Right"); + case Common::Input::ButtonNames::ButtonDown: + return QObject::tr("Down"); + case Common::Input::ButtonNames::ButtonUp: + return QObject::tr("Up"); + case Common::Input::ButtonNames::TriggerZ: + return QObject::tr("Z"); + case Common::Input::ButtonNames::TriggerR: + return QObject::tr("R"); + case Common::Input::ButtonNames::TriggerL: + return QObject::tr("L"); + case Common::Input::ButtonNames::ButtonA: + return QObject::tr("A"); + case Common::Input::ButtonNames::ButtonB: + return QObject::tr("B"); + case Common::Input::ButtonNames::ButtonX: + return QObject::tr("X"); + case Common::Input::ButtonNames::ButtonY: + return QObject::tr("Y"); + case Common::Input::ButtonNames::ButtonStart: + return QObject::tr("Start"); + case Common::Input::ButtonNames::L1: + return QObject::tr("L1"); + case Common::Input::ButtonNames::L2: + return QObject::tr("L2"); + case Common::Input::ButtonNames::L3: + return QObject::tr("L3"); + case Common::Input::ButtonNames::R1: + return QObject::tr("R1"); + case Common::Input::ButtonNames::R2: + return QObject::tr("R2"); + case Common::Input::ButtonNames::R3: + return QObject::tr("R3"); + case Common::Input::ButtonNames::Circle: + return QObject::tr("Circle"); + case Common::Input::ButtonNames::Cross: + return QObject::tr("Cross"); + case Common::Input::ButtonNames::Square: + return QObject::tr("Square"); + case Common::Input::ButtonNames::Triangle: + return QObject::tr("Triangle"); + case Common::Input::ButtonNames::Share: + return QObject::tr("Share"); + case Common::Input::ButtonNames::Options: + return QObject::tr("Options"); + default: + return QObject::tr("[undefined]"); + } +} + void SetAnalogParam(const Common::ParamPackage& input_param, Common::ParamPackage& analog_param, const std::string& button_name) { // The poller returned a complete axis, so set all the buttons @@ -97,95 +123,75 @@ void SetAnalogParam(const Common::ParamPackage& input_param, Common::ParamPackag } analog_param.Set(button_name, input_param.Serialize()); } +} // namespace -QString ButtonToText(const Common::ParamPackage& param) { +QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { if (!param.Has("engine")) { return QObject::tr("[not set]"); } + const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); + const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : ""); + const auto common_button_name = input_subsystem->GetButtonName(param); + + // Retrieve the names from Qt if (param.Get("engine", "") == "keyboard") { const QString button_str = GetKeyName(param.Get("code", 0)); - const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); return QObject::tr("%1%2").arg(toggle, button_str); } - if (param.Get("engine", "") == "gcpad") { - if (param.Has("axis")) { - const QString axis_str = QString::fromStdString(param.Get("axis", "")); - const QString direction_str = QString::fromStdString(param.Get("direction", "")); - - return QObject::tr("GC Axis %1%2").arg(axis_str, direction_str); - } - if (param.Has("button")) { - const QString button_str = QString::number(int(std::log2(param.Get("button", 0)))); - return QObject::tr("GC Button %1").arg(button_str); - } - return GetKeyName(param.Get("code", 0)); - } - - if (param.Get("engine", "") == "tas") { - if (param.Has("axis")) { - const QString axis_str = QString::fromStdString(param.Get("axis", "")); - - return QObject::tr("TAS Axis %1").arg(axis_str); - } - if (param.Has("button")) { - const QString button_str = QString::number(int(std::log2(param.Get("button", 0)))); - return QObject::tr("TAS Btn %1").arg(button_str); - } - return GetKeyName(param.Get("code", 0)); + if (common_button_name == Common::Input::ButtonNames::Invalid) { + return QObject::tr("[invalid]"); } - if (param.Get("engine", "") == "cemuhookudp") { - if (param.Has("pad_index")) { - const QString motion_str = QString::fromStdString(param.Get("pad_index", "")); - return QObject::tr("Motion %1").arg(motion_str); - } - return GetKeyName(param.Get("code", 0)); + if (common_button_name == Common::Input::ButtonNames::Engine) { + return QString::fromStdString(param.Get("engine", "")); } - if (param.Get("engine", "") == "sdl") { + if (common_button_name == Common::Input::ButtonNames::Value) { if (param.Has("hat")) { - const QString hat_str = QString::fromStdString(param.Get("hat", "")); - const QString direction_str = QString::fromStdString(param.Get("direction", "")); - - return QObject::tr("Hat %1 %2").arg(hat_str, direction_str); + const QString hat = QString::fromStdString(param.Get("direction", "")); + return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat); } - if (param.Has("axis")) { - const QString axis_str = QString::fromStdString(param.Get("axis", "")); - const QString direction_str = QString::fromStdString(param.Get("direction", "")); - - return QObject::tr("Axis %1%2").arg(axis_str, direction_str); + const QString axis = QString::fromStdString(param.Get("axis", "")); + return QObject::tr("%1%2Axis %3").arg(toggle, inverted, axis); } - - if (param.Has("button")) { - const QString button_str = QString::fromStdString(param.Get("button", "")); - const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); - - return QObject::tr("%1Button %2").arg(toggle, button_str); + if (param.Has("axis_x") && param.Has("axis_y") && param.Has("axis_z")) { + const QString axis_x = QString::fromStdString(param.Get("axis_x", "")); + const QString axis_y = QString::fromStdString(param.Get("axis_y", "")); + const QString axis_z = QString::fromStdString(param.Get("axis_z", "")); + return QObject::tr("%1%2Axis %3,%4,%5").arg(toggle, inverted, axis_x, axis_y, axis_z); } - if (param.Has("motion")) { - return QObject::tr("SDL Motion"); + const QString motion = QString::fromStdString(param.Get("motion", "")); + return QObject::tr("%1%2Motion %3").arg(toggle, inverted, motion); } - - return {}; - } - - if (param.Get("engine", "") == "mouse") { if (param.Has("button")) { - const QString button_str = QString::number(int(param.Get("button", 0))); - const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); - return QObject::tr("%1Click %2").arg(toggle, button_str); + const QString button = QString::fromStdString(param.Get("button", "")); + return QObject::tr("%1%2Button %3").arg(toggle, inverted, button); } - return GetKeyName(param.Get("code", 0)); + } + + QString button_name = GetButtonName(common_button_name); + if (param.Has("hat")) { + return QObject::tr("%1%2Hat %3").arg(toggle, inverted, button_name); + } + if (param.Has("axis")) { + return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); + } + if (param.Has("motion")) { + return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); + } + if (param.Has("button")) { + return QObject::tr("%1%2Button %3").arg(toggle, inverted, button_name); } return QObject::tr("[unknown]"); } -QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { +QString ConfigureInputPlayer::AnalogToText(const Common::ParamPackage& param, + const std::string& dir) { if (!param.Has("engine")) { return QObject::tr("[not set]"); } @@ -194,49 +200,69 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) return ButtonToText(Common::ParamPackage{param.Get(dir, "")}); } + if (!param.Has("axis_x") || !param.Has("axis_y")) { + return QObject::tr("[unknown]"); + } + const auto engine_str = param.Get("engine", ""); const QString axis_x_str = QString::fromStdString(param.Get("axis_x", "")); const QString axis_y_str = QString::fromStdString(param.Get("axis_y", "")); const bool invert_x = param.Get("invert_x", "+") == "-"; const bool invert_y = param.Get("invert_y", "+") == "-"; - if (engine_str == "sdl" || engine_str == "gcpad" || engine_str == "mouse" || - engine_str == "tas") { - if (dir == "modifier") { - return QObject::tr("[unused]"); - } - if (dir == "left") { - const QString invert_x_str = QString::fromStdString(invert_x ? "+" : "-"); - return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str); - } - if (dir == "right") { - const QString invert_x_str = QString::fromStdString(invert_x ? "-" : "+"); - return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str); - } - if (dir == "up") { - const QString invert_y_str = QString::fromStdString(invert_y ? "-" : "+"); - return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str); - } - if (dir == "down") { - const QString invert_y_str = QString::fromStdString(invert_y ? "+" : "-"); - return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str); - } + if (dir == "modifier") { + return QObject::tr("[unused]"); + } - return {}; + if (dir == "left") { + const QString invert_x_str = QString::fromStdString(invert_x ? "+" : "-"); + return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str); } + if (dir == "right") { + const QString invert_x_str = QString::fromStdString(invert_x ? "-" : "+"); + return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str); + } + if (dir == "up") { + const QString invert_y_str = QString::fromStdString(invert_y ? "-" : "+"); + return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str); + } + if (dir == "down") { + const QString invert_y_str = QString::fromStdString(invert_y ? "+" : "-"); + return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str); + } + return QObject::tr("[unknown]"); } -} // namespace ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row, InputCommon::InputSubsystem* input_subsystem_, - InputProfiles* profiles_, Core::System& system_, - bool debug) + InputProfiles* profiles_, Core::HID::HIDCore& hid_core_, + bool is_powered_on_, bool debug) : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), - debug(debug), input_subsystem{input_subsystem_}, profiles(profiles_), - timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()), - bottom_row(bottom_row), system{system_} { + debug(debug), is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, + profiles(profiles_), timeout_timer(std::make_unique<QTimer>()), + poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row), hid_core{hid_core_} { + if (player_index == 0) { + auto* emulated_controller_p1 = + hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* emulated_controller_hanheld = + hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); + emulated_controller_p1->SaveCurrentConfig(); + emulated_controller_p1->EnableConfiguration(); + emulated_controller_hanheld->SaveCurrentConfig(); + emulated_controller_hanheld->EnableConfiguration(); + if (emulated_controller_hanheld->IsConnected(true)) { + emulated_controller_p1->Disconnect(); + emulated_controller = emulated_controller_hanheld; + } else { + emulated_controller = emulated_controller_p1; + } + } else { + emulated_controller = hid_core.GetEmulatedControllerByIndex(player_index); + emulated_controller->SaveCurrentConfig(); + emulated_controller->EnableConfiguration(); + } ui->setupUi(this); setFocusPolicy(Qt::ClickFocus); @@ -278,31 +304,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup}; analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange}; - const auto ConfigureButtonClick = [&](QPushButton* button, std::size_t button_id, - Common::ParamPackage* param, int default_val, - InputCommon::Polling::DeviceType type) { - connect(button, &QPushButton::clicked, [=, this] { - HandleClick( - button, button_id, - [=, this](Common::ParamPackage params) { - // Workaround for ZL & ZR for analog triggers like on XBOX - // controllers. Analog triggers (from controllers like the XBOX - // controller) would not work due to a different range of their - // signals (from 0 to 255 on analog triggers instead of -32768 to - // 32768 on analog joysticks). The SDL driver misinterprets analog - // triggers as analog joysticks. - // TODO: reinterpret the signal range for analog triggers to map the - // values correctly. This is required for the correct emulation of - // the analog triggers of the GameCube controller. - if (button == ui->buttonZL || button == ui->buttonZR) { - params.Set("direction", "+"); - params.Set("threshold", "0.5"); - } - *param = std::move(params); - }, - type); - }); - }; + ui->controllerFrame->SetController(emulated_controller); for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { auto* const button = button_map[button_id]; @@ -311,34 +313,52 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i continue; } - ConfigureButtonClick(button_map[button_id], button_id, &buttons_param[button_id], - Config::default_buttons[button_id], - InputCommon::Polling::DeviceType::Button); + connect(button, &QPushButton::clicked, [=, this] { + HandleClick( + button, button_id, + [=, this](Common::ParamPackage params) { + emulated_controller->SetButtonParam(button_id, params); + }, + InputCommon::Polling::InputType::Button); + }); button->setContextMenuPolicy(Qt::CustomContextMenu); connect(button, &QPushButton::customContextMenuRequested, [=, this](const QPoint& menu_location) { QMenu context_menu; + Common::ParamPackage param = emulated_controller->GetButtonParam(button_id); context_menu.addAction(tr("Clear"), [&] { - buttons_param[button_id].Clear(); + emulated_controller->SetButtonParam(button_id, {}); button_map[button_id]->setText(tr("[not set]")); }); - if (buttons_param[button_id].Has("toggle")) { + if (param.Has("button") || param.Has("hat")) { context_menu.addAction(tr("Toggle button"), [&] { - const bool toggle_value = - !buttons_param[button_id].Get("toggle", false); - buttons_param[button_id].Set("toggle", toggle_value); - button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); + const bool toggle_value = !param.Get("toggle", false); + param.Set("toggle", toggle_value); + button_map[button_id]->setText(ButtonToText(param)); + emulated_controller->SetButtonParam(button_id, param); + }); + context_menu.addAction(tr("Invert button"), [&] { + const bool toggle_value = !param.Get("inverted", false); + param.Set("inverted", toggle_value); + button_map[button_id]->setText(ButtonToText(param)); + emulated_controller->SetButtonParam(button_id, param); }); } - if (buttons_param[button_id].Has("threshold")) { + if (param.Has("axis")) { + context_menu.addAction(tr("Invert axis"), [&] { + const bool toggle_value = !(param.Get("invert", "+") == "-"); + param.Set("invert", toggle_value ? "-" : "+"); + button_map[button_id]->setText(ButtonToText(param)); + emulated_controller->SetButtonParam(button_id, param); + }); context_menu.addAction(tr("Set threshold"), [&] { - const int button_threshold = static_cast<int>( - buttons_param[button_id].Get("threshold", 0.5f) * 100.0f); + const int button_threshold = + static_cast<int>(param.Get("threshold", 0.5f) * 100.0f); const int new_threshold = QInputDialog::getInt( this, tr("Set threshold"), tr("Choose a value between 0% and 100%"), button_threshold, 0, 100); - buttons_param[button_id].Set("threshold", new_threshold / 100.0f); + param.Set("threshold", new_threshold / 100.0f); if (button_id == Settings::NativeButton::ZL) { ui->sliderZLThreshold->setValue(new_threshold); @@ -346,11 +366,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i if (button_id == Settings::NativeButton::ZR) { ui->sliderZRThreshold->setValue(new_threshold); } + emulated_controller->SetButtonParam(button_id, param); }); } - context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); - ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); }); } @@ -360,9 +379,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i continue; } - ConfigureButtonClick(motion_map[motion_id], motion_id, &motions_param[motion_id], - Config::default_motions[motion_id], - InputCommon::Polling::DeviceType::Motion); + connect(button, &QPushButton::clicked, [=, this] { + HandleClick( + button, motion_id, + [=, this](Common::ParamPackage params) { + emulated_controller->SetMotionParam(motion_id, params); + }, + InputCommon::Polling::InputType::Motion); + }); button->setContextMenuPolicy(Qt::CustomContextMenu); @@ -370,7 +394,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i [=, this](const QPoint& menu_location) { QMenu context_menu; context_menu.addAction(tr("Clear"), [&] { - motions_param[motion_id].Clear(); + emulated_controller->SetMotionParam(motion_id, {}); motion_map[motion_id]->setText(tr("[not set]")); }); context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location)); @@ -378,16 +402,22 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i } connect(ui->sliderZLThreshold, &QSlider::valueChanged, [=, this] { - if (buttons_param[Settings::NativeButton::ZL].Has("threshold")) { + Common::ParamPackage param = + emulated_controller->GetButtonParam(Settings::NativeButton::ZL); + if (param.Has("threshold")) { const auto slider_value = ui->sliderZLThreshold->value(); - buttons_param[Settings::NativeButton::ZL].Set("threshold", slider_value / 100.0f); + param.Set("threshold", slider_value / 100.0f); + emulated_controller->SetButtonParam(Settings::NativeButton::ZL, param); } }); connect(ui->sliderZRThreshold, &QSlider::valueChanged, [=, this] { - if (buttons_param[Settings::NativeButton::ZR].Has("threshold")) { + Common::ParamPackage param = + emulated_controller->GetButtonParam(Settings::NativeButton::ZR); + if (param.Has("threshold")) { const auto slider_value = ui->sliderZRThreshold->value(); - buttons_param[Settings::NativeButton::ZR].Set("threshold", slider_value / 100.0f); + param.Set("threshold", slider_value / 100.0f); + emulated_controller->SetButtonParam(Settings::NativeButton::ZR, param); } }); @@ -415,45 +445,45 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i HandleClick( analog_map_buttons[analog_id][sub_button_id], analog_id, [=, this](const Common::ParamPackage& params) { - SetAnalogParam(params, analogs_param[analog_id], - analog_sub_buttons[sub_button_id]); + Common::ParamPackage param = emulated_controller->GetStickParam(analog_id); + SetAnalogParam(params, param, analog_sub_buttons[sub_button_id]); + emulated_controller->SetStickParam(analog_id, param); }, - InputCommon::Polling::DeviceType::AnalogPreferred); + InputCommon::Polling::InputType::Stick); }); analog_button->setContextMenuPolicy(Qt::CustomContextMenu); - connect( - analog_button, &QPushButton::customContextMenuRequested, - [=, this](const QPoint& menu_location) { - QMenu context_menu; - context_menu.addAction(tr("Clear"), [&] { - analogs_param[analog_id].Clear(); - analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); - }); - context_menu.addAction(tr("Invert axis"), [&] { - if (sub_button_id == 2 || sub_button_id == 3) { - const bool invert_value = - analogs_param[analog_id].Get("invert_x", "+") == "-"; - const std::string invert_str = invert_value ? "+" : "-"; - analogs_param[analog_id].Set("invert_x", invert_str); - } - if (sub_button_id == 0 || sub_button_id == 1) { - const bool invert_value = - analogs_param[analog_id].Get("invert_y", "+") == "-"; - const std::string invert_str = invert_value ? "+" : "-"; - analogs_param[analog_id].Set("invert_y", invert_str); - } - for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; - ++sub_button_id) { - analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( - analogs_param[analog_id], analog_sub_buttons[sub_button_id])); - } + connect(analog_button, &QPushButton::customContextMenuRequested, + [=, this](const QPoint& menu_location) { + QMenu context_menu; + Common::ParamPackage param = emulated_controller->GetStickParam(analog_id); + context_menu.addAction(tr("Clear"), [&] { + emulated_controller->SetStickParam(analog_id, {}); + analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); + }); + context_menu.addAction(tr("Invert axis"), [&] { + if (sub_button_id == 2 || sub_button_id == 3) { + const bool invert_value = param.Get("invert_x", "+") == "-"; + const std::string invert_str = invert_value ? "+" : "-"; + param.Set("invert_x", invert_str); + emulated_controller->SetStickParam(analog_id, param); + } + if (sub_button_id == 0 || sub_button_id == 1) { + const bool invert_value = param.Get("invert_y", "+") == "-"; + const std::string invert_str = invert_value ? "+" : "-"; + param.Set("invert_y", invert_str); + emulated_controller->SetStickParam(analog_id, param); + } + for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; + ++sub_button_id) { + analog_map_buttons[analog_id][sub_button_id]->setText( + AnalogToText(param, analog_sub_buttons[sub_button_id])); + } + }); + context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal( + menu_location)); }); - context_menu.exec( - analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(menu_location)); - ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); - }); } // Handle clicks for the modifier buttons as well. @@ -461,9 +491,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i HandleClick( analog_map_modifier_button[analog_id], analog_id, [=, this](const Common::ParamPackage& params) { - analogs_param[analog_id].Set("modifier", params.Serialize()); + Common::ParamPackage param = emulated_controller->GetStickParam(analog_id); + param.Set("modifier", params.Serialize()); + emulated_controller->SetStickParam(analog_id, param); }, - InputCommon::Polling::DeviceType::Button); + InputCommon::Polling::InputType::Button); }); analog_map_modifier_button[analog_id]->setContextMenuPolicy(Qt::CustomContextMenu); @@ -471,18 +503,21 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i connect(analog_map_modifier_button[analog_id], &QPushButton::customContextMenuRequested, [=, this](const QPoint& menu_location) { QMenu context_menu; + Common::ParamPackage param = emulated_controller->GetStickParam(analog_id); context_menu.addAction(tr("Clear"), [&] { - analogs_param[analog_id].Set("modifier", ""); + param.Set("modifier", ""); analog_map_modifier_button[analog_id]->setText(tr("[not set]")); + emulated_controller->SetStickParam(analog_id, param); }); context_menu.addAction(tr("Toggle button"), [&] { Common::ParamPackage modifier_param = - Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")}; + Common::ParamPackage{param.Get("modifier", "")}; const bool toggle_value = !modifier_param.Get("toggle", false); modifier_param.Set("toggle", toggle_value); - analogs_param[analog_id].Set("modifier", modifier_param.Serialize()); + param.Set("modifier", modifier_param.Serialize()); analog_map_modifier_button[analog_id]->setText( ButtonToText(modifier_param)); + emulated_controller->SetStickParam(analog_id, param); }); context_menu.exec( analog_map_modifier_button[analog_id]->mapToGlobal(menu_location)); @@ -490,37 +525,39 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i connect(analog_map_range_spinbox[analog_id], qOverload<int>(&QSpinBox::valueChanged), [=, this] { + Common::ParamPackage param = emulated_controller->GetStickParam(analog_id); const auto spinbox_value = analog_map_range_spinbox[analog_id]->value(); - analogs_param[analog_id].Set("range", spinbox_value / 100.0f); - ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); + param.Set("range", spinbox_value / 100.0f); + emulated_controller->SetStickParam(analog_id, param); }); connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] { + Common::ParamPackage param = emulated_controller->GetStickParam(analog_id); const auto slider_value = analog_map_deadzone_slider[analog_id]->value(); analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value)); - analogs_param[analog_id].Set("deadzone", slider_value / 100.0f); - ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); + param.Set("deadzone", slider_value / 100.0f); + emulated_controller->SetStickParam(analog_id, param); }); connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] { + Common::ParamPackage param = emulated_controller->GetStickParam(analog_id); const auto slider_value = analog_map_modifier_slider[analog_id]->value(); analog_map_modifier_label[analog_id]->setText( tr("Modifier Range: %1%").arg(slider_value)); - analogs_param[analog_id].Set("modifier_scale", slider_value / 100.0f); + param.Set("modifier_scale", slider_value / 100.0f); + emulated_controller->SetStickParam(analog_id, param); }); } // Player Connected checkbox - connect(ui->groupConnectedController, &QGroupBox::toggled, [this](bool checked) { - emit Connected(checked); - ui->controllerFrame->SetConnectedStatus(checked); - }); + connect(ui->groupConnectedController, &QGroupBox::toggled, + [this](bool checked) { emit Connected(checked); }); if (player_index == 0) { connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) { emit HandheldStateChanged(GetControllerTypeFromIndex(index) == - Settings::ControllerType::Handheld); + Core::HID::NpadStyleIndex::Handheld); }); } @@ -537,18 +574,43 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i SetConnectableControllers(); } - UpdateControllerIcon(); UpdateControllerAvailableButtons(); UpdateControllerEnabledButtons(); UpdateControllerButtonNames(); UpdateMotionButtons(); - connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) { - UpdateControllerIcon(); - UpdateControllerAvailableButtons(); - UpdateControllerEnabledButtons(); - UpdateControllerButtonNames(); - UpdateMotionButtons(); - }); + connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), + [this, player_index](int) { + UpdateControllerAvailableButtons(); + UpdateControllerEnabledButtons(); + UpdateControllerButtonNames(); + UpdateMotionButtons(); + const Core::HID::NpadStyleIndex type = + GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); + + if (player_index == 0) { + auto* emulated_controller_p1 = + hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* emulated_controller_hanheld = + hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); + bool is_connected = emulated_controller->IsConnected(true); + + emulated_controller_p1->SetNpadStyleIndex(type); + emulated_controller_hanheld->SetNpadStyleIndex(type); + if (is_connected) { + if (type == Core::HID::NpadStyleIndex::Handheld) { + emulated_controller_p1->Disconnect(); + emulated_controller_hanheld->Connect(); + emulated_controller = emulated_controller_hanheld; + } else { + emulated_controller_hanheld->Disconnect(); + emulated_controller_p1->Connect(); + emulated_controller = emulated_controller_p1; + } + } + ui->controllerFrame->SetController(emulated_controller); + } + emulated_controller->SetNpadStyleIndex(type); + }); connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this, &ConfigureInputPlayer::UpdateMappingWithDefaults); @@ -563,62 +625,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); connect(poll_timer.get(), &QTimer::timeout, [this] { - Common::ParamPackage params; - if (input_subsystem->GetGCButtons()->IsPolling()) { - params = input_subsystem->GetGCButtons()->GetNextInput(); - if (params.Has("engine") && IsInputAcceptable(params)) { - SetPollingResult(params, false); - return; - } - } - if (input_subsystem->GetGCAnalogs()->IsPolling()) { - params = input_subsystem->GetGCAnalogs()->GetNextInput(); - if (params.Has("engine") && IsInputAcceptable(params)) { - SetPollingResult(params, false); - return; - } - } - if (input_subsystem->GetUDPMotions()->IsPolling()) { - params = input_subsystem->GetUDPMotions()->GetNextInput(); - if (params.Has("engine")) { - SetPollingResult(params, false); - return; - } - } - if (input_subsystem->GetMouseButtons()->IsPolling()) { - params = input_subsystem->GetMouseButtons()->GetNextInput(); - if (params.Has("engine") && IsInputAcceptable(params)) { - SetPollingResult(params, false); - return; - } - } - if (input_subsystem->GetMouseAnalogs()->IsPolling()) { - params = input_subsystem->GetMouseAnalogs()->GetNextInput(); - if (params.Has("engine") && IsInputAcceptable(params)) { - SetPollingResult(params, false); - return; - } - } - if (input_subsystem->GetMouseMotions()->IsPolling()) { - params = input_subsystem->GetMouseMotions()->GetNextInput(); - if (params.Has("engine") && IsInputAcceptable(params)) { - SetPollingResult(params, false); - return; - } - } - if (input_subsystem->GetMouseTouch()->IsPolling()) { - params = input_subsystem->GetMouseTouch()->GetNextInput(); - if (params.Has("engine") && IsInputAcceptable(params)) { - SetPollingResult(params, false); - return; - } - } - for (auto& poller : device_pollers) { - params = poller->GetNextInput(); - if (params.Has("engine") && IsInputAcceptable(params)) { - SetPollingResult(params, false); - return; - } + const auto& params = input_subsystem->GetNextInput(); + if (params.Has("engine") && IsInputAcceptable(params)) { + SetPollingResult(params, false); + return; } }); @@ -634,110 +644,38 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i &ConfigureInputPlayer::SaveProfile); LoadConfiguration(); - ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); - ui->controllerFrame->SetConnectedStatus(ui->groupConnectedController->isChecked()); } -ConfigureInputPlayer::~ConfigureInputPlayer() = default; - -void ConfigureInputPlayer::ApplyConfiguration() { - auto& player = Settings::values.players.GetValue()[player_index]; - auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons; - auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs; - - std::transform(buttons_param.begin(), buttons_param.end(), buttons.begin(), - [](const Common::ParamPackage& param) { return param.Serialize(); }); - std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(), - [](const Common::ParamPackage& param) { return param.Serialize(); }); - - if (debug) { - return; - } - - auto& motions = player.motions; - - std::transform(motions_param.begin(), motions_param.end(), motions.begin(), - [](const Common::ParamPackage& param) { return param.Serialize(); }); - - // Apply configuration for handheld +ConfigureInputPlayer::~ConfigureInputPlayer() { if (player_index == 0) { - auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; - const auto handheld_connected = handheld.connected; - handheld = player; - handheld.connected = handheld_connected; + auto* emulated_controller_p1 = + hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* emulated_controller_hanheld = + hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); + emulated_controller_p1->DisableConfiguration(); + emulated_controller_hanheld->DisableConfiguration(); + } else { + emulated_controller->DisableConfiguration(); } } -void ConfigureInputPlayer::TryConnectSelectedController() { - auto& player = Settings::values.players.GetValue()[player_index]; - - const auto controller_type = - GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); - const auto player_connected = ui->groupConnectedController->isChecked() && - controller_type != Settings::ControllerType::Handheld; - - // Connect Handheld depending on Player 1's controller configuration. +void ConfigureInputPlayer::ApplyConfiguration() { if (player_index == 0) { - auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; - const auto handheld_connected = ui->groupConnectedController->isChecked() && - controller_type == Settings::ControllerType::Handheld; - // Connect only if handheld is going from disconnected to connected - if (!handheld.connected && handheld_connected) { - UpdateController(controller_type, HANDHELD_INDEX, true, system); - } - handheld.connected = handheld_connected; - } - - if (player.controller_type == controller_type && player.connected == player_connected) { - // Set vibration devices in the event that the input device has changed. - ConfigureVibration::SetVibrationDevices(player_index); - return; - } - - player.controller_type = controller_type; - player.connected = player_connected; - - ConfigureVibration::SetVibrationDevices(player_index); - - if (!player.connected) { - return; - } - - UpdateController(controller_type, player_index, true, system); -} - -void ConfigureInputPlayer::TryDisconnectSelectedController() { - const auto& player = Settings::values.players.GetValue()[player_index]; - - const auto controller_type = - GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); - const auto player_connected = ui->groupConnectedController->isChecked() && - controller_type != Settings::ControllerType::Handheld; - - // Disconnect Handheld depending on Player 1's controller configuration. - if (player_index == 0 && player.controller_type == Settings::ControllerType::Handheld) { - const auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; - const auto handheld_connected = ui->groupConnectedController->isChecked() && - controller_type == Settings::ControllerType::Handheld; - // Disconnect only if handheld is going from connected to disconnected - if (handheld.connected && !handheld_connected) { - UpdateController(controller_type, HANDHELD_INDEX, false, system); - } - return; - } - - // Do not do anything if the controller configuration has not changed. - if (player.controller_type == controller_type && player.connected == player_connected) { - return; - } - - // Do not disconnect if the controller is already disconnected - if (!player.connected) { + auto* emulated_controller_p1 = + hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* emulated_controller_hanheld = + hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); + emulated_controller_p1->DisableConfiguration(); + emulated_controller_p1->SaveCurrentConfig(); + emulated_controller_p1->EnableConfiguration(); + emulated_controller_hanheld->DisableConfiguration(); + emulated_controller_hanheld->SaveCurrentConfig(); + emulated_controller_hanheld->EnableConfiguration(); return; } - - // Disconnect the controller first. - UpdateController(controller_type, player_index, false, system); + emulated_controller->DisableConfiguration(); + emulated_controller->SaveCurrentConfig(); + emulated_controller->EnableConfiguration(); } void ConfigureInputPlayer::showEvent(QShowEvent* event) { @@ -762,22 +700,7 @@ void ConfigureInputPlayer::RetranslateUI() { } void ConfigureInputPlayer::LoadConfiguration() { - auto& player = Settings::values.players.GetValue()[player_index]; - if (debug) { - std::transform(Settings::values.debug_pad_buttons.begin(), - Settings::values.debug_pad_buttons.end(), buttons_param.begin(), - [](const std::string& str) { return Common::ParamPackage(str); }); - std::transform(Settings::values.debug_pad_analogs.begin(), - Settings::values.debug_pad_analogs.end(), analogs_param.begin(), - [](const std::string& str) { return Common::ParamPackage(str); }); - } else { - std::transform(player.buttons.begin(), player.buttons.end(), buttons_param.begin(), - [](const std::string& str) { return Common::ParamPackage(str); }); - std::transform(player.analogs.begin(), player.analogs.end(), analogs_param.begin(), - [](const std::string& str) { return Common::ParamPackage(str); }); - std::transform(player.motions.begin(), player.motions.end(), motions_param.begin(), - [](const std::string& str) { return Common::ParamPackage(str); }); - } + emulated_controller->ReloadFromSettings(); UpdateUI(); UpdateInputDeviceCombobox(); @@ -786,14 +709,19 @@ void ConfigureInputPlayer::LoadConfiguration() { return; } - ui->comboControllerType->setCurrentIndex(GetIndexFromControllerType(player.controller_type)); - ui->groupConnectedController->setChecked( - player.connected || - (player_index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected)); + const int comboBoxIndex = + GetIndexFromControllerType(emulated_controller->GetNpadStyleIndex(true)); + ui->comboControllerType->setCurrentIndex(comboBoxIndex); + ui->groupConnectedController->setChecked(emulated_controller->IsConnected(true)); } void ConfigureInputPlayer::ConnectPlayer(bool connected) { ui->groupConnectedController->setChecked(connected); + if (connected) { + emulated_controller->Connect(); + } else { + emulated_controller->Disconnect(); + } } void ConfigureInputPlayer::UpdateInputDeviceCombobox() { @@ -803,48 +731,64 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() { return; } - // Find the first button that isn't empty. - const auto button_param = - std::find_if(buttons_param.begin(), buttons_param.end(), - [](const Common::ParamPackage param) { return param.Has("engine"); }); - const bool buttons_empty = button_param == buttons_param.end(); + const auto devices = + emulated_controller->GetMappedDevices(Core::HID::EmulatedDeviceIndex::AllDevices); + UpdateInputDevices(); - const auto current_engine = button_param->Get("engine", ""); - const auto current_guid = button_param->Get("guid", ""); - const auto current_port = button_param->Get("port", ""); + if (devices.empty()) { + return; + } - const bool is_keyboard_mouse = current_engine == "keyboard" || current_engine == "mouse"; + if (devices.size() > 2) { + ui->comboDevices->setCurrentIndex(0); + return; + } - UpdateInputDevices(); + const auto first_engine = devices[0].Get("engine", ""); + const auto first_guid = devices[0].Get("guid", ""); + const auto first_port = devices[0].Get("port", 0); - if (buttons_empty) { + if (devices.size() == 1) { + const auto devices_it = + std::find_if(input_devices.begin(), input_devices.end(), + [first_engine, first_guid, first_port](const Common::ParamPackage param) { + return param.Get("engine", "") == first_engine && + param.Get("guid", "") == first_guid && + param.Get("port", 0) == first_port; + }); + const int device_index = + devices_it != input_devices.end() + ? static_cast<int>(std::distance(input_devices.begin(), devices_it)) + : 0; + ui->comboDevices->setCurrentIndex(device_index); return; } - const bool all_one_device = - std::all_of(buttons_param.begin(), buttons_param.end(), - [current_engine, current_guid, current_port, - is_keyboard_mouse](const Common::ParamPackage param) { - if (is_keyboard_mouse) { - return !param.Has("engine") || param.Get("engine", "") == "keyboard" || - param.Get("engine", "") == "mouse"; - } - return !param.Has("engine") || (param.Get("engine", "") == current_engine && - param.Get("guid", "") == current_guid && - param.Get("port", "") == current_port); - }); + const auto second_engine = devices[1].Get("engine", ""); + const auto second_guid = devices[1].Get("guid", ""); + const auto second_port = devices[1].Get("port", 0); - if (all_one_device) { - if (is_keyboard_mouse) { - ui->comboDevices->setCurrentIndex(1); - return; - } + const bool is_keyboard_mouse = (first_engine == "keyboard" || first_engine == "mouse") && + (second_engine == "keyboard" || second_engine == "mouse"); + + if (is_keyboard_mouse) { + ui->comboDevices->setCurrentIndex(2); + return; + } + + const bool is_engine_equal = first_engine == second_engine; + const bool is_port_equal = first_port == second_port; + + if (is_engine_equal && is_port_equal) { const auto devices_it = std::find_if( input_devices.begin(), input_devices.end(), - [current_engine, current_guid, current_port](const Common::ParamPackage param) { - return param.Get("class", "") == current_engine && - param.Get("guid", "") == current_guid && - param.Get("port", "") == current_port; + [first_engine, first_guid, second_guid, first_port](const Common::ParamPackage param) { + const bool is_guid_valid = + (param.Get("guid", "") == first_guid && + param.Get("guid2", "") == second_guid) || + (param.Get("guid", "") == second_guid && param.Get("guid2", "") == first_guid); + return param.Get("engine", "") == first_engine && is_guid_valid && + param.Get("port", 0) == first_port; }); const int device_index = devices_it != input_devices.end() @@ -866,8 +810,7 @@ void ConfigureInputPlayer::ClearAll() { if (button == nullptr) { continue; } - - buttons_param[button_id].Clear(); + emulated_controller->SetButtonParam(button_id, {}); } for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { @@ -876,8 +819,7 @@ void ConfigureInputPlayer::ClearAll() { if (analog_button == nullptr) { continue; } - - analogs_param[analog_id].Clear(); + emulated_controller->SetStickParam(analog_id, {}); } } @@ -886,8 +828,7 @@ void ConfigureInputPlayer::ClearAll() { if (motion_button == nullptr) { continue; } - - motions_param[motion_id].Clear(); + emulated_controller->SetMotionParam(motion_id, {}); } UpdateUI(); @@ -896,26 +837,31 @@ void ConfigureInputPlayer::ClearAll() { void ConfigureInputPlayer::UpdateUI() { for (int button = 0; button < Settings::NativeButton::NumButtons; ++button) { - button_map[button]->setText(ButtonToText(buttons_param[button])); + const Common::ParamPackage param = emulated_controller->GetButtonParam(button); + button_map[button]->setText(ButtonToText(param)); } - if (buttons_param[Settings::NativeButton::ZL].Has("threshold")) { - const int button_threshold = static_cast<int>( - buttons_param[Settings::NativeButton::ZL].Get("threshold", 0.5f) * 100.0f); + const Common::ParamPackage ZL_param = + emulated_controller->GetButtonParam(Settings::NativeButton::ZL); + if (ZL_param.Has("threshold")) { + const int button_threshold = static_cast<int>(ZL_param.Get("threshold", 0.5f) * 100.0f); ui->sliderZLThreshold->setValue(button_threshold); } - if (buttons_param[Settings::NativeButton::ZR].Has("threshold")) { - const int button_threshold = static_cast<int>( - buttons_param[Settings::NativeButton::ZR].Get("threshold", 0.5f) * 100.0f); + const Common::ParamPackage ZR_param = + emulated_controller->GetButtonParam(Settings::NativeButton::ZR); + if (ZR_param.Has("threshold")) { + const int button_threshold = static_cast<int>(ZR_param.Get("threshold", 0.5f) * 100.0f); ui->sliderZRThreshold->setValue(button_threshold); } for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { - motion_map[motion_id]->setText(ButtonToText(motions_param[motion_id])); + const Common::ParamPackage param = emulated_controller->GetMotionParam(motion_id); + motion_map[motion_id]->setText(ButtonToText(param)); } for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { + const Common::ParamPackage param = emulated_controller->GetStickParam(analog_id); for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; @@ -923,12 +869,11 @@ void ConfigureInputPlayer::UpdateUI() { continue; } - analog_button->setText( - AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); + analog_button->setText(AnalogToText(param, analog_sub_buttons[sub_button_id])); } analog_map_modifier_button[analog_id]->setText( - ButtonToText(Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")})); + ButtonToText(Common::ParamPackage{param.Get("modifier", "")})); const auto deadzone_label = analog_map_deadzone_label[analog_id]; const auto deadzone_slider = analog_map_deadzone_slider[analog_id]; @@ -939,26 +884,14 @@ void ConfigureInputPlayer::UpdateUI() { const auto range_spinbox = analog_map_range_spinbox[analog_id]; int slider_value; - auto& param = analogs_param[analog_id]; - const bool is_controller = - param.Get("engine", "") == "sdl" || param.Get("engine", "") == "gcpad" || - param.Get("engine", "") == "mouse" || param.Get("engine", "") == "tas"; + const bool is_controller = input_subsystem->IsController(param); if (is_controller) { - if (!param.Has("deadzone")) { - param.Set("deadzone", 0.1f); - } - slider_value = static_cast<int>(param.Get("deadzone", 0.1f) * 100); + slider_value = static_cast<int>(param.Get("deadzone", 0.15f) * 100); deadzone_label->setText(tr("Deadzone: %1%").arg(slider_value)); deadzone_slider->setValue(slider_value); - if (!param.Has("range")) { - param.Set("range", 1.0f); - } range_spinbox->setValue(static_cast<int>(param.Get("range", 1.0f) * 100)); } else { - if (!param.Has("modifier_scale")) { - param.Set("modifier_scale", 0.5f); - } slider_value = static_cast<int>(param.Get("modifier_scale", 0.5f) * 100); modifier_label->setText(tr("Modifier Range: %1%").arg(slider_value)); modifier_slider->setValue(slider_value); @@ -970,79 +903,73 @@ void ConfigureInputPlayer::UpdateUI() { modifier_label->setVisible(!is_controller); modifier_slider->setVisible(!is_controller); range_groupbox->setVisible(is_controller); - ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); } } void ConfigureInputPlayer::SetConnectableControllers() { const auto add_controllers = [this](bool enable_all, - Controller_NPad::NpadStyleSet npad_style_set = {}) { + Core::HID::NpadStyleTag npad_style_set = {}) { index_controller_type_pairs.clear(); ui->comboControllerType->clear(); if (enable_all || npad_style_set.fullkey == 1) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Settings::ControllerType::ProController); + Core::HID::NpadStyleIndex::ProController); ui->comboControllerType->addItem(tr("Pro Controller")); } if (enable_all || npad_style_set.joycon_dual == 1) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Settings::ControllerType::DualJoyconDetached); + Core::HID::NpadStyleIndex::JoyconDual); ui->comboControllerType->addItem(tr("Dual Joycons")); } if (enable_all || npad_style_set.joycon_left == 1) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Settings::ControllerType::LeftJoycon); + Core::HID::NpadStyleIndex::JoyconLeft); ui->comboControllerType->addItem(tr("Left Joycon")); } if (enable_all || npad_style_set.joycon_right == 1) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Settings::ControllerType::RightJoycon); + Core::HID::NpadStyleIndex::JoyconRight); ui->comboControllerType->addItem(tr("Right Joycon")); } if (player_index == 0 && (enable_all || npad_style_set.handheld == 1)) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Settings::ControllerType::Handheld); + Core::HID::NpadStyleIndex::Handheld); ui->comboControllerType->addItem(tr("Handheld")); } if (enable_all || npad_style_set.gamecube == 1) { index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), - Settings::ControllerType::GameCube); + Core::HID::NpadStyleIndex::GameCube); ui->comboControllerType->addItem(tr("GameCube Controller")); } }; - if (!system.IsPoweredOn()) { + if (!is_powered_on) { add_controllers(true); return; } - Service::SM::ServiceManager& sm = system.ServiceManager(); - - auto& npad = sm.GetService<Hid>("hid")->GetAppletResource()->GetController<Controller_NPad>( - HidController::NPad); - - add_controllers(false, npad.GetSupportedStyleSet()); + add_controllers(false, hid_core.GetSupportedStyleTag()); } -Settings::ControllerType ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const { +Core::HID::NpadStyleIndex ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const { const auto it = std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), [index](const auto& pair) { return pair.first == index; }); if (it == index_controller_type_pairs.end()) { - return Settings::ControllerType::ProController; + return Core::HID::NpadStyleIndex::ProController; } return it->second; } -int ConfigureInputPlayer::GetIndexFromControllerType(Settings::ControllerType type) const { +int ConfigureInputPlayer::GetIndexFromControllerType(Core::HID::NpadStyleIndex type) const { const auto it = std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), [type](const auto& pair) { return pair.second == type; }); @@ -1057,52 +984,15 @@ int ConfigureInputPlayer::GetIndexFromControllerType(Settings::ControllerType ty void ConfigureInputPlayer::UpdateInputDevices() { input_devices = input_subsystem->GetInputDevices(); ui->comboDevices->clear(); - for (auto& device : input_devices) { - const std::string display = device.Get("display", "Unknown"); - ui->comboDevices->addItem(QString::fromStdString(display), {}); - if (display == "TAS") { - device.Set("pad", static_cast<u8>(player_index)); - } + for (auto device : input_devices) { + ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); } } -void ConfigureInputPlayer::UpdateControllerIcon() { - // We aren't using Qt's built in theme support here since we aren't drawing an icon (and its - // "nonstandard" to use an image through the icon support) - const QString stylesheet = [this] { - switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { - case Settings::ControllerType::ProController: - return QStringLiteral("image: url(:/controller/pro_controller%0)"); - case Settings::ControllerType::DualJoyconDetached: - return QStringLiteral("image: url(:/controller/dual_joycon%0)"); - case Settings::ControllerType::LeftJoycon: - return QStringLiteral("image: url(:/controller/single_joycon_left_vertical%0)"); - case Settings::ControllerType::RightJoycon: - return QStringLiteral("image: url(:/controller/single_joycon_right_vertical%0)"); - case Settings::ControllerType::Handheld: - return QStringLiteral("image: url(:/controller/handheld%0)"); - default: - return QString{}; - } - }(); - - const QString theme = [] { - if (QIcon::themeName().contains(QStringLiteral("dark"))) { - return QStringLiteral("_dark"); - } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { - return QStringLiteral("_midnight"); - } else { - return QString{}; - } - }(); - ui->controllerFrame->SetControllerType( - GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())); -} - void ConfigureInputPlayer::UpdateControllerAvailableButtons() { auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); if (debug) { - layout = Settings::ControllerType::ProController; + layout = Core::HID::NpadStyleIndex::ProController; } // List of all the widgets that will be hidden by any of the following layouts that need @@ -1127,15 +1017,15 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { std::vector<QWidget*> layout_hidden; switch (layout) { - case Settings::ControllerType::ProController: - case Settings::ControllerType::DualJoyconDetached: - case Settings::ControllerType::Handheld: + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::JoyconDual: + case Core::HID::NpadStyleIndex::Handheld: layout_hidden = { ui->buttonShoulderButtonsSLSR, ui->horizontalSpacerShoulderButtonsWidget2, }; break; - case Settings::ControllerType::LeftJoycon: + case Core::HID::NpadStyleIndex::JoyconLeft: layout_hidden = { ui->horizontalSpacerShoulderButtonsWidget2, ui->buttonShoulderButtonsRight, @@ -1143,7 +1033,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { ui->bottomRight, }; break; - case Settings::ControllerType::RightJoycon: + case Core::HID::NpadStyleIndex::JoyconRight: layout_hidden = { ui->horizontalSpacerShoulderButtonsWidget, ui->buttonShoulderButtonsLeft, @@ -1151,7 +1041,7 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { ui->bottomLeft, }; break; - case Settings::ControllerType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: layout_hidden = { ui->buttonShoulderButtonsSLSR, ui->horizontalSpacerShoulderButtonsWidget2, @@ -1159,6 +1049,8 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { ui->buttonMiscButtonsScreenshotGroup, }; break; + default: + break; } for (auto* widget : layout_hidden) { @@ -1169,13 +1061,12 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { void ConfigureInputPlayer::UpdateControllerEnabledButtons() { auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); if (debug) { - layout = Settings::ControllerType::ProController; + layout = Core::HID::NpadStyleIndex::ProController; } // List of all the widgets that will be disabled by any of the following layouts that need // "enabled" after the controller type changes - const std::array<QWidget*, 4> layout_enable = { - ui->buttonHome, + const std::array<QWidget*, 3> layout_enable = { ui->buttonLStickPressedGroup, ui->groupRStickPressed, ui->buttonShoulderButtonsButtonLGroup, @@ -1187,17 +1078,13 @@ void ConfigureInputPlayer::UpdateControllerEnabledButtons() { std::vector<QWidget*> layout_disable; switch (layout) { - case Settings::ControllerType::ProController: - case Settings::ControllerType::DualJoyconDetached: - case Settings::ControllerType::Handheld: - case Settings::ControllerType::LeftJoycon: - case Settings::ControllerType::RightJoycon: - // TODO(wwylele): enable this when we actually emulate it - layout_disable = { - ui->buttonHome, - }; + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::JoyconDual: + case Core::HID::NpadStyleIndex::Handheld: + case Core::HID::NpadStyleIndex::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconRight: break; - case Settings::ControllerType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: layout_disable = { ui->buttonHome, ui->buttonLStickPressedGroup, @@ -1205,6 +1092,8 @@ void ConfigureInputPlayer::UpdateControllerEnabledButtons() { ui->buttonShoulderButtonsButtonLGroup, }; break; + default: + break; } for (auto* widget : layout_disable) { @@ -1222,24 +1111,24 @@ void ConfigureInputPlayer::UpdateMotionButtons() { // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller. switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { - case Settings::ControllerType::ProController: - case Settings::ControllerType::LeftJoycon: - case Settings::ControllerType::Handheld: + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::JoyconLeft: + case Core::HID::NpadStyleIndex::Handheld: // Show "Motion 1" and hide "Motion 2". ui->buttonMotionLeftGroup->show(); ui->buttonMotionRightGroup->hide(); break; - case Settings::ControllerType::RightJoycon: + case Core::HID::NpadStyleIndex::JoyconRight: // Show "Motion 2" and hide "Motion 1". ui->buttonMotionLeftGroup->hide(); ui->buttonMotionRightGroup->show(); break; - case Settings::ControllerType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: // Hide both "Motion 1/2". ui->buttonMotionLeftGroup->hide(); ui->buttonMotionRightGroup->hide(); break; - case Settings::ControllerType::DualJoyconDetached: + case Core::HID::NpadStyleIndex::JoyconDual: default: // Show both "Motion 1/2". ui->buttonMotionLeftGroup->show(); @@ -1251,15 +1140,15 @@ void ConfigureInputPlayer::UpdateMotionButtons() { void ConfigureInputPlayer::UpdateControllerButtonNames() { auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); if (debug) { - layout = Settings::ControllerType::ProController; + layout = Core::HID::NpadStyleIndex::ProController; } switch (layout) { - case Settings::ControllerType::ProController: - case Settings::ControllerType::DualJoyconDetached: - case Settings::ControllerType::Handheld: - case Settings::ControllerType::LeftJoycon: - case Settings::ControllerType::RightJoycon: + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::JoyconDual: + case Core::HID::NpadStyleIndex::Handheld: + case Core::HID::NpadStyleIndex::JoyconLeft: + case Core::HID::NpadStyleIndex::JoyconRight: ui->buttonMiscButtonsPlusGroup->setTitle(tr("Plus")); ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("ZL")); ui->buttonShoulderButtonsZRGroup->setTitle(tr("ZR")); @@ -1267,7 +1156,7 @@ void ConfigureInputPlayer::UpdateControllerButtonNames() { ui->LStick->setTitle(tr("Left Stick")); ui->RStick->setTitle(tr("Right Stick")); break; - case Settings::ControllerType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: ui->buttonMiscButtonsPlusGroup->setTitle(tr("Start / Pause")); ui->buttonShoulderButtonsButtonZLGroup->setTitle(tr("L")); ui->buttonShoulderButtonsZRGroup->setTitle(tr("R")); @@ -1275,6 +1164,8 @@ void ConfigureInputPlayer::UpdateControllerButtonNames() { ui->LStick->setTitle(tr("Control Stick")); ui->RStick->setTitle(tr("C-Stick")); break; + default: + break; } } @@ -1283,45 +1174,82 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() { return; } - if (ui->comboDevices->currentIndex() == 1) { - // Reset keyboard bindings + for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { + const auto* const button = button_map[button_id]; + if (button == nullptr) { + continue; + } + emulated_controller->SetButtonParam(button_id, {}); + } + + for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { + for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { + const auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; + if (analog_button == nullptr) { + continue; + } + emulated_controller->SetStickParam(analog_id, {}); + } + } + + for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { + const auto* const motion_button = motion_map[motion_id]; + if (motion_button == nullptr) { + continue; + } + emulated_controller->SetMotionParam(motion_id, {}); + } + + // Reset keyboard or mouse bindings + if (ui->comboDevices->currentIndex() == 1 || ui->comboDevices->currentIndex() == 2) { for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { - buttons_param[button_id] = Common::ParamPackage{ - InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; + emulated_controller->SetButtonParam( + button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( + Config::default_buttons[button_id])}); } for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { + Common::ParamPackage analog_param{}; for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { Common::ParamPackage params{InputCommon::GenerateKeyboardParam( Config::default_analogs[analog_id][sub_button_id])}; - SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); + SetAnalogParam(params, analog_param, analog_sub_buttons[sub_button_id]); } - analogs_param[analog_id].Set("modifier", InputCommon::GenerateKeyboardParam( - Config::default_stick_mod[analog_id])); + analog_param.Set("modifier", InputCommon::GenerateKeyboardParam( + Config::default_stick_mod[analog_id])); + emulated_controller->SetStickParam(analog_id, analog_param); } for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { - motions_param[motion_id] = Common::ParamPackage{ - InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])}; + emulated_controller->SetMotionParam( + motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( + Config::default_motions[motion_id])}); } - UpdateUI(); - return; + // If mouse is selected we want to override with mappings from the driver + if (ui->comboDevices->currentIndex() == 1) { + UpdateUI(); + return; + } } // Reset controller bindings const auto& device = input_devices[ui->comboDevices->currentIndex()]; - auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); - auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); - auto motion_mapping = input_subsystem->GetMotionMappingForDevice(device); - for (std::size_t i = 0; i < buttons_param.size(); ++i) { - buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; + auto button_mappings = input_subsystem->GetButtonMappingForDevice(device); + auto analog_mappings = input_subsystem->GetAnalogMappingForDevice(device); + auto motion_mappings = input_subsystem->GetMotionMappingForDevice(device); + + for (const auto& button_mapping : button_mappings) { + const std::size_t index = button_mapping.first; + emulated_controller->SetButtonParam(index, button_mapping.second); } - for (std::size_t i = 0; i < analogs_param.size(); ++i) { - analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; + for (const auto& analog_mapping : analog_mappings) { + const std::size_t index = analog_mapping.first; + emulated_controller->SetStickParam(index, analog_mapping.second); } - for (std::size_t i = 0; i < motions_param.size(); ++i) { - motions_param[i] = motion_mapping[static_cast<Settings::NativeMotion::Values>(i)]; + for (const auto& motion_mapping : motion_mappings) { + const std::size_t index = motion_mapping.first; + emulated_controller->SetMotionParam(index, motion_mapping.second); } UpdateUI(); @@ -1330,7 +1258,7 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() { void ConfigureInputPlayer::HandleClick( QPushButton* button, std::size_t button_id, std::function<void(const Common::ParamPackage&)> new_input_setter, - InputCommon::Polling::DeviceType type) { + InputCommon::Polling::InputType type) { if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) { button->setText(tr("Shake!")); } else { @@ -1338,71 +1266,31 @@ void ConfigureInputPlayer::HandleClick( } button->setFocus(); - // The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a - // controller, then they don't want keyboard/mouse input - want_keyboard_mouse = ui->comboDevices->currentIndex() < 2; - input_setter = new_input_setter; - device_pollers = input_subsystem->GetPollers(type); - - for (auto& poller : device_pollers) { - poller->Start(); - } + input_subsystem->BeginMapping(type); QWidget::grabMouse(); QWidget::grabKeyboard(); - if (type == InputCommon::Polling::DeviceType::Button) { - input_subsystem->GetGCButtons()->BeginConfiguration(); - } else { - input_subsystem->GetGCAnalogs()->BeginConfiguration(); - } - - if (type == InputCommon::Polling::DeviceType::Motion) { - input_subsystem->GetUDPMotions()->BeginConfiguration(); - } - - if (type == InputCommon::Polling::DeviceType::Button) { - input_subsystem->GetMouseButtons()->BeginConfiguration(); - } else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) { - input_subsystem->GetMouseAnalogs()->BeginConfiguration(); - } else if (type == InputCommon::Polling::DeviceType::Motion) { - input_subsystem->GetMouseMotions()->BeginConfiguration(); - } else { - input_subsystem->GetMouseTouch()->BeginConfiguration(); - } - - if (type == InputCommon::Polling::DeviceType::Button) { + if (type == InputCommon::Polling::InputType::Button) { ui->controllerFrame->BeginMappingButton(button_id); - } else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) { + } else if (type == InputCommon::Polling::InputType::Stick) { ui->controllerFrame->BeginMappingAnalog(button_id); } timeout_timer->start(2500); // Cancel after 2.5 seconds - poll_timer->start(50); // Check for new inputs every 50ms + poll_timer->start(25); // Check for new inputs every 25ms } void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { timeout_timer->stop(); poll_timer->stop(); - for (auto& poller : device_pollers) { - poller->Stop(); - } + input_subsystem->StopMapping(); QWidget::releaseMouse(); QWidget::releaseKeyboard(); - input_subsystem->GetGCButtons()->EndConfiguration(); - input_subsystem->GetGCAnalogs()->EndConfiguration(); - - input_subsystem->GetUDPMotions()->EndConfiguration(); - - input_subsystem->GetMouseButtons()->EndConfiguration(); - input_subsystem->GetMouseAnalogs()->EndConfiguration(); - input_subsystem->GetMouseMotions()->EndConfiguration(); - input_subsystem->GetMouseTouch()->EndConfiguration(); - if (!abort) { (*input_setter)(params); } @@ -1419,15 +1307,20 @@ bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params) return true; } + if (params.Has("motion")) { + return true; + } + // Keyboard/Mouse - if (ui->comboDevices->currentIndex() == 1) { + if (ui->comboDevices->currentIndex() == 1 || ui->comboDevices->currentIndex() == 2) { return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse"; } const auto current_input_device = input_devices[ui->comboDevices->currentIndex()]; - return params.Get("engine", "") == current_input_device.Get("class", "") && - params.Get("guid", "") == current_input_device.Get("guid", "") && - params.Get("port", "") == current_input_device.Get("port", ""); + return params.Get("engine", "") == current_input_device.Get("engine", "") && + (params.Get("guid", "") == current_input_device.Get("guid", "") || + params.Get("guid", "") == current_input_device.Get("guid2", "")) && + params.Get("port", 0) == current_input_device.Get("port", 0); } void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { @@ -1436,25 +1329,17 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { } const auto button = GRenderWindow::QtButtonToMouseButton(event->button()); - input_subsystem->GetMouse()->PressButton(0, 0, button); + input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button); } void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { + event->ignore(); if (!input_setter || !event) { return; } - if (event->key() != Qt::Key_Escape) { - if (want_keyboard_mouse) { - SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, - false); - } else { - // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling - return; - } + input_subsystem->GetKeyboard()->PressKey(event->key()); } - - SetPollingResult({}, true); } void ConfigureInputPlayer::CreateProfile() { diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index 39b44b8a5..47df6b3d3 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h @@ -29,48 +29,37 @@ class QWidget; class InputProfiles; -namespace Core { -class System; -} - namespace InputCommon { class InputSubsystem; } namespace InputCommon::Polling { -class DevicePoller; -enum class DeviceType; +enum class InputType; } // namespace InputCommon::Polling namespace Ui { class ConfigureInputPlayer; } +namespace Core::HID { +class HIDCore; +class EmulatedController; +enum class NpadStyleIndex : u8; +} // namespace Core::HID + class ConfigureInputPlayer : public QWidget { Q_OBJECT public: explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row, InputCommon::InputSubsystem* input_subsystem_, - InputProfiles* profiles_, Core::System& system_, - bool debug = false); + InputProfiles* profiles_, Core::HID::HIDCore& hid_core_, + bool is_powered_on_, bool debug = false); ~ConfigureInputPlayer() override; /// Save all button configurations to settings file. void ApplyConfiguration(); - /** - * Attempts to connect the currently selected controller in the HID backend. - * This function will not do anything if it is not connected in the frontend. - */ - void TryConnectSelectedController(); - - /** - * Attempts to disconnect the currently selected controller in the HID backend. - * This function will not do anything if the configuration has not changed. - */ - void TryDisconnectSelectedController(); - /// Set the connection state checkbox (used to sync state). void ConnectPlayer(bool connected); @@ -104,6 +93,10 @@ protected: void showEvent(QShowEvent* event) override; private: + QString ButtonToText(const Common::ParamPackage& param); + + QString AnalogToText(const Common::ParamPackage& param, const std::string& dir); + void changeEvent(QEvent* event) override; void RetranslateUI(); @@ -113,7 +106,7 @@ private: /// Called when the button was pressed. void HandleClick(QPushButton* button, std::size_t button_id, std::function<void(const Common::ParamPackage&)> new_input_setter, - InputCommon::Polling::DeviceType type); + InputCommon::Polling::InputType type); /// Finish polling and configure input using the input_setter. void SetPollingResult(const Common::ParamPackage& params, bool abort); @@ -134,17 +127,14 @@ private: void SetConnectableControllers(); /// Gets the Controller Type for a given controller combobox index. - Settings::ControllerType GetControllerTypeFromIndex(int index) const; + Core::HID::NpadStyleIndex GetControllerTypeFromIndex(int index) const; /// Gets the controller combobox index for a given Controller Type. - int GetIndexFromControllerType(Settings::ControllerType type) const; + int GetIndexFromControllerType(Core::HID::NpadStyleIndex type) const; /// Update the available input devices. void UpdateInputDevices(); - /// Update the current controller icon. - void UpdateControllerIcon(); - /// Hides and disables controller settings based on the current controller type. void UpdateControllerAvailableButtons(); @@ -176,6 +166,7 @@ private: std::size_t player_index; bool debug; + bool is_powered_on; InputCommon::InputSubsystem* input_subsystem; @@ -185,7 +176,7 @@ private: std::unique_ptr<QTimer> poll_timer; /// Stores a pair of "Connected Controllers" combobox index and Controller Type enum. - std::vector<std::pair<int, Settings::ControllerType>> index_controller_type_pairs; + std::vector<std::pair<int, Core::HID::NpadStyleIndex>> index_controller_type_pairs; static constexpr int PLAYER_COUNT = 8; std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox; @@ -193,9 +184,7 @@ private: /// This will be the the setting function when an input is awaiting configuration. std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; - std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param; - std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param; - std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions> motions_param; + Core::HID::EmulatedController* emulated_controller; static constexpr int ANALOG_SUB_BUTTONS_NUM = 4; @@ -221,15 +210,9 @@ private: static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons; - std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers; - /// A flag to indicate that the "Map Analog Stick" pop-up has been shown and accepted once. bool map_analog_stick_accepted{}; - /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, - /// keyboard events are ignored. - bool want_keyboard_mouse{}; - /// List of physical devices users can map with. If a SDL backed device is selected, then you /// can use this device to get a default mapping. std::vector<Common::ParamPackage> input_devices; @@ -239,5 +222,5 @@ private: /// parent of the widget to this widget (but thats fine). QWidget* bottom_row; - Core::System& system; + Core::HID::HIDCore& hid_core; }; diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui index e7433912b..756a414b5 100644 --- a/src/yuzu/configuration/configure_input_player.ui +++ b/src/yuzu/configuration/configure_input_player.ui @@ -89,31 +89,6 @@ <height>21</height> </size> </property> - <item> - <property name="text"> - <string>Pro Controller</string> - </property> - </item> - <item> - <property name="text"> - <string>Dual Joycons</string> - </property> - </item> - <item> - <property name="text"> - <string>Left Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Right Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Handheld</string> - </property> - </item> </widget> </item> </layout> @@ -142,22 +117,9 @@ </property> <item> <widget class="QComboBox" name="comboDevices"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>21</height> - </size> + <property name="minimumContentsLength"> + <number>60</number> </property> - <item> - <property name="text"> - <string>Any</string> - </property> - </item> - <item> - <property name="text"> - <string>Keyboard/Mouse</string> - </property> - </item> </widget> </item> <item> @@ -342,7 +304,7 @@ <number>3</number> </property> <property name="topMargin"> - <number>0</number> + <number>6</number> </property> <property name="rightMargin"> <number>3</number> @@ -918,7 +880,7 @@ <number>3</number> </property> <property name="topMargin"> - <number>0</number> + <number>6</number> </property> <property name="rightMargin"> <number>3</number> @@ -2221,7 +2183,7 @@ <number>3</number> </property> <property name="topMargin"> - <number>0</number> + <number>6</number> </property> <property name="rightMargin"> <number>3</number> @@ -2570,7 +2532,7 @@ <number>3</number> </property> <property name="topMargin"> - <number>0</number> + <number>6</number> </property> <property name="rightMargin"> <number>3</number> diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index f31f86339..6630321cb 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -6,10 +6,12 @@ #include <QMenu> #include <QPainter> #include <QTimer> + +#include "core/hid/emulated_controller.h" #include "yuzu/configuration/configure_input_player_widget.h" PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) { - UpdateColors(); + is_controller_set = false; QTimer* timer = new QTimer(this); connect(timer, &QTimer::timeout, this, QOverload<>::of(&PlayerControlPreview::UpdateInput)); @@ -17,91 +19,37 @@ PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) { timer->start(16); } -PlayerControlPreview::~PlayerControlPreview() = default; - -void PlayerControlPreview::SetPlayerInput(std::size_t index, const ButtonParam& buttons_param, - const AnalogParam& analogs_param) { - player_index = index; - Settings::ButtonsRaw buttonss; - Settings::AnalogsRaw analogs; - std::transform(buttons_param.begin(), buttons_param.end(), buttonss.begin(), - [](const Common::ParamPackage& param) { return param.Serialize(); }); - std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(), - [](const Common::ParamPackage& param) { return param.Serialize(); }); - - std::transform(buttonss.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, - buttonss.begin() + Settings::NativeButton::BUTTON_NS_END, buttons.begin(), - Input::CreateDevice<Input::ButtonDevice>); - std::transform(analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, - analogs.begin() + Settings::NativeAnalog::STICK_HID_END, sticks.begin(), - Input::CreateDevice<Input::AnalogDevice>); - UpdateColors(); -} -void PlayerControlPreview::SetPlayerInputRaw(std::size_t index, - const Settings::ButtonsRaw& buttons_, - Settings::AnalogsRaw analogs_) { - player_index = index; - std::transform(buttons_.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, - buttons_.begin() + Settings::NativeButton::BUTTON_NS_END, buttons.begin(), - Input::CreateDevice<Input::ButtonDevice>); - std::transform(analogs_.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, - analogs_.begin() + Settings::NativeAnalog::STICK_HID_END, sticks.begin(), - Input::CreateDevice<Input::AnalogDevice>); - UpdateColors(); -} - -PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size_t index, - bool player_on) { - if (!player_on) { - return {0, 0, 0, 0}; - } - - switch (index) { - case 0: - return {1, 0, 0, 0}; - case 1: - return {1, 1, 0, 0}; - case 2: - return {1, 1, 1, 0}; - case 3: - return {1, 1, 1, 1}; - case 4: - return {1, 0, 0, 1}; - case 5: - return {1, 0, 1, 0}; - case 6: - return {1, 0, 1, 1}; - case 7: - return {0, 1, 1, 0}; - default: - return {0, 0, 0, 0}; - } -} - -void PlayerControlPreview::SetConnectedStatus(bool checked) { - LedPattern led_pattern = GetColorPattern(player_index, checked); +PlayerControlPreview::~PlayerControlPreview() { + UnloadController(); +}; - led_color[0] = led_pattern.position1 ? colors.led_on : colors.led_off; - led_color[1] = led_pattern.position2 ? colors.led_on : colors.led_off; - led_color[2] = led_pattern.position3 ? colors.led_on : colors.led_off; - led_color[3] = led_pattern.position4 ? colors.led_on : colors.led_off; - is_enabled = checked; - ResetInputs(); +void PlayerControlPreview::SetController(Core::HID::EmulatedController* controller_) { + UnloadController(); + is_controller_set = true; + controller = controller_; + Core::HID::ControllerUpdateCallback engine_callback{ + .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }, + .is_npad_service = false, + }; + callback_key = controller->SetCallback(engine_callback); + ControllerUpdate(Core::HID::ControllerTriggerType::All); } -void PlayerControlPreview::SetControllerType(const Settings::ControllerType type) { - controller_type = type; - UpdateColors(); +void PlayerControlPreview::UnloadController() { + if (is_controller_set) { + controller->DeleteCallback(callback_key); + is_controller_set = false; + } } -void PlayerControlPreview::BeginMappingButton(std::size_t index) { - button_mapping_index = index; +void PlayerControlPreview::BeginMappingButton(std::size_t button_id) { + button_mapping_index = button_id; mapping_active = true; } -void PlayerControlPreview::BeginMappingAnalog(std::size_t index) { - button_mapping_index = Settings::NativeButton::LStick + index; - analog_mapping_index = index; +void PlayerControlPreview::BeginMappingAnalog(std::size_t stick_id) { + button_mapping_index = Settings::NativeButton::LStick + stick_id; + analog_mapping_index = stick_id; mapping_active = true; } @@ -157,84 +105,109 @@ void PlayerControlPreview::UpdateColors() { colors.left = colors.primary; colors.right = colors.primary; // Possible alternative to set colors from settings - // colors.left = QColor(Settings::values.players.GetValue()[player_index].body_color_left); - // colors.right = QColor(Settings::values.players.GetValue()[player_index].body_color_right); + // colors.left = QColor(controller->GetColors().left.body); + // colors.right = QColor(controller->GetColors().right.body); } void PlayerControlPreview::ResetInputs() { - for (std::size_t index = 0; index < button_values.size(); ++index) { - button_values[index] = false; - } - - for (std::size_t index = 0; index < axis_values.size(); ++index) { - axis_values[index].properties = {0, 1, 0}; - axis_values[index].value = {0, 0}; - axis_values[index].raw_value = {0, 0}; - } + button_values.fill({ + .value = false, + }); + stick_values.fill({ + .x = {.value = 0, .properties = {0, 1, 0}}, + .y = {.value = 0, .properties = {0, 1, 0}}, + }); + trigger_values.fill({ + .analog = {.value = 0, .properties = {0, 1, 0}}, + .pressed = {.value = false}, + }); update(); } -void PlayerControlPreview::UpdateInput() { - if (!is_enabled && !mapping_active && !Settings::values.tas_enable) { +void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType type) { + if (type == Core::HID::ControllerTriggerType::All) { + ControllerUpdate(Core::HID::ControllerTriggerType::Color); + ControllerUpdate(Core::HID::ControllerTriggerType::Type); + ControllerUpdate(Core::HID::ControllerTriggerType::Connected); + ControllerUpdate(Core::HID::ControllerTriggerType::Button); + ControllerUpdate(Core::HID::ControllerTriggerType::Stick); + ControllerUpdate(Core::HID::ControllerTriggerType::Trigger); + ControllerUpdate(Core::HID::ControllerTriggerType::Battery); return; } - bool input_changed = false; - const auto& button_state = buttons; - for (std::size_t index = 0; index < button_values.size(); ++index) { - bool value = false; - if (index < Settings::NativeButton::BUTTON_NS_END) { - value = button_state[index]->GetStatus(); - } - bool blink = mapping_active && index == button_mapping_index; - if (analog_mapping_index == Settings::NativeAnalog::NUM_STICKS_HID) { - blink &= blink_counter > 25; - } - if (button_values[index] != value || blink) { - input_changed = true; - } - button_values[index] = value || blink; + + switch (type) { + case Core::HID::ControllerTriggerType::Connected: + is_connected = true; + led_pattern = controller->GetLedPattern(); + needs_redraw = true; + break; + case Core::HID::ControllerTriggerType::Disconnected: + is_connected = false; + led_pattern.raw = 0; + needs_redraw = true; + break; + case Core::HID::ControllerTriggerType::Type: + controller_type = controller->GetNpadStyleIndex(true); + needs_redraw = true; + break; + case Core::HID::ControllerTriggerType::Color: + UpdateColors(); + needs_redraw = true; + break; + case Core::HID::ControllerTriggerType::Button: + button_values = controller->GetButtonsValues(); + needs_redraw = true; + break; + case Core::HID::ControllerTriggerType::Stick: + using namespace Settings::NativeAnalog; + stick_values = controller->GetSticksValues(); + // Y axis is inverted + stick_values[LStick].y.value = -stick_values[LStick].y.value; + stick_values[LStick].y.raw_value = -stick_values[LStick].y.raw_value; + stick_values[RStick].y.value = -stick_values[RStick].y.value; + stick_values[RStick].y.raw_value = -stick_values[RStick].y.raw_value; + needs_redraw = true; + break; + case Core::HID::ControllerTriggerType::Trigger: + trigger_values = controller->GetTriggersValues(); + needs_redraw = true; + break; + case Core::HID::ControllerTriggerType::Battery: + battery_values = controller->GetBatteryValues(); + needs_redraw = true; + break; + default: + break; } +} - const auto& analog_state = sticks; - for (std::size_t index = 0; index < axis_values.size(); ++index) { - const auto [stick_x_f, stick_y_f] = analog_state[index]->GetStatus(); - const auto [stick_x_rf, stick_y_rf] = analog_state[index]->GetRawStatus(); +void PlayerControlPreview::UpdateInput() { + if (mapping_active) { - if (static_cast<int>(stick_x_rf * 45) != - static_cast<int>(axis_values[index].raw_value.x() * 45) || - static_cast<int>(-stick_y_rf * 45) != - static_cast<int>(axis_values[index].raw_value.y() * 45)) { - input_changed = true; + for (std::size_t index = 0; index < button_values.size(); ++index) { + bool blink = index == button_mapping_index; + if (analog_mapping_index == Settings::NativeAnalog::NumAnalogs) { + blink &= blink_counter > 25; + } + if (button_values[index].value != blink) { + needs_redraw = true; + } + button_values[index].value = blink; } - axis_values[index].properties = analog_state[index]->GetAnalogProperties(); - axis_values[index].value = QPointF(stick_x_f, -stick_y_f); - axis_values[index].raw_value = QPointF(stick_x_rf, -stick_y_rf); - - const bool blink_analog = mapping_active && index == analog_mapping_index; - if (blink_analog) { - input_changed = true; - axis_values[index].value = - QPointF(blink_counter < 25 ? -blink_counter / 25.0f : 0, - blink_counter > 25 ? -(blink_counter - 25) / 25.0f : 0); + for (std::size_t index = 0; index < stick_values.size(); ++index) { + const bool blink_analog = index == analog_mapping_index; + if (blink_analog) { + needs_redraw = true; + stick_values[index].x.value = blink_counter < 25 ? -blink_counter / 25.0f : 0; + stick_values[index].y.value = + blink_counter > 25 ? -(blink_counter - 25) / 25.0f : 0; + } } } - - if (input_changed) { + if (needs_redraw) { update(); - if (controller_callback.input != nullptr) { - ControllerInput input{ - .axis_values = {std::pair<float, float>{ - axis_values[Settings::NativeAnalog::LStick].value.x(), - axis_values[Settings::NativeAnalog::LStick].value.y()}, - std::pair<float, float>{ - axis_values[Settings::NativeAnalog::RStick].value.x(), - axis_values[Settings::NativeAnalog::RStick].value.y()}}, - .button_values = button_values, - .changed = true, - }; - controller_callback.input(std::move(input)); - } } if (mapping_active) { @@ -242,10 +215,6 @@ void PlayerControlPreview::UpdateInput() { } } -void PlayerControlPreview::SetCallBack(ControllerCallback callback_) { - controller_callback = std::move(callback_); -} - void PlayerControlPreview::paintEvent(QPaintEvent* event) { QFrame::paintEvent(event); QPainter p(this); @@ -253,22 +222,22 @@ void PlayerControlPreview::paintEvent(QPaintEvent* event) { const QPointF center = rect().center(); switch (controller_type) { - case Settings::ControllerType::Handheld: + case Core::HID::NpadStyleIndex::Handheld: DrawHandheldController(p, center); break; - case Settings::ControllerType::DualJoyconDetached: + case Core::HID::NpadStyleIndex::JoyconDual: DrawDualController(p, center); break; - case Settings::ControllerType::LeftJoycon: + case Core::HID::NpadStyleIndex::JoyconLeft: DrawLeftController(p, center); break; - case Settings::ControllerType::RightJoycon: + case Core::HID::NpadStyleIndex::JoyconRight: DrawRightController(p, center); break; - case Settings::ControllerType::GameCube: + case Core::HID::NpadStyleIndex::GameCube: DrawGCController(p, center); break; - case Settings::ControllerType::ProController: + case Core::HID::NpadStyleIndex::ProController: default: DrawProController(p, center); break; @@ -281,7 +250,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) // Sideview left joystick DrawJoystickSideview(p, center + QPoint(142, -69), - -axis_values[Settings::NativeAnalog::LStick].value.y(), 1.15f, + -stick_values[Settings::NativeAnalog::LStick].y.value, 1.15f, button_values[LStick]); // Topview D-pad buttons @@ -292,7 +261,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) // Topview left joystick DrawJoystickSideview(p, center + QPointF(-140.5f, -28), - -axis_values[Settings::NativeAnalog::LStick].value.x() + 15.0f, 1.15f, + -stick_values[Settings::NativeAnalog::LStick].x.value + 15.0f, 1.15f, button_values[LStick]); // Topview minus button @@ -334,8 +303,10 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) { // Draw joysticks using namespace Settings::NativeAnalog; - DrawJoystick(p, center + QPointF(9, -69) + (axis_values[LStick].value * 8), 1.8f, - button_values[Settings::NativeButton::LStick]); + DrawJoystick(p, + center + QPointF(9, -69) + + (QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value) * 8), + 1.8f, button_values[Settings::NativeButton::LStick]); DrawRawJoystick(p, center + QPointF(-140, 90), QPointF(0, 0)); } @@ -384,6 +355,10 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) p.setPen(colors.font2); p.setBrush(colors.font2); DrawCircle(p, center + QPoint(26, 71), 5); + + // Draw battery + DrawBattery(p, center + QPoint(-170, -140), + battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); } void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) { @@ -392,20 +367,22 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center // Sideview right joystick DrawJoystickSideview(p, center + QPoint(173 - 315, 11), - axis_values[Settings::NativeAnalog::RStick].value.y() + 10.0f, 1.15f, + stick_values[Settings::NativeAnalog::RStick].y.value + 10.0f, 1.15f, button_values[Settings::NativeButton::RStick]); + // Topview right joystick + DrawJoystickSideview(p, center + QPointF(140, -28), + -stick_values[Settings::NativeAnalog::RStick].x.value + 15.0f, 1.15f, + button_values[RStick]); + // Topview face buttons p.setPen(colors.outline); button_color = colors.button; DrawRoundButton(p, center + QPoint(163, -21), button_values[A], 11, 5, Direction::Up); + DrawRoundButton(p, center + QPoint(140, -21), button_values[B], 11, 5, Direction::Up); + DrawRoundButton(p, center + QPoint(140, -21), button_values[X], 11, 5, Direction::Up); DrawRoundButton(p, center + QPoint(117, -21), button_values[Y], 11, 5, Direction::Up); - // Topview right joystick - DrawJoystickSideview(p, center + QPointF(140, -28), - -axis_values[Settings::NativeAnalog::RStick].value.x() + 15.0f, 1.15f, - button_values[RStick]); - // Topview plus button p.setPen(colors.outline); button_color = colors.button; @@ -448,8 +425,10 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center { // Draw joysticks using namespace Settings::NativeAnalog; - DrawJoystick(p, center + QPointF(-9, 11) + (axis_values[RStick].value * 8), 1.8f, - button_values[Settings::NativeButton::RStick]); + DrawJoystick(p, + center + QPointF(-9, 11) + + (QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value) * 8), + 1.8f, button_values[Settings::NativeButton::RStick]); DrawRawJoystick(p, QPointF(0, 0), center + QPointF(140, 90)); } @@ -503,6 +482,10 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center p.setPen(colors.transparent); p.setBrush(colors.font2); DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5); + + // Draw battery + DrawBattery(p, center + QPoint(110, -140), + battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]); } void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) { @@ -512,17 +495,19 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) // Left/Right trigger DrawDualTriggers(p, center, button_values[L], button_values[R]); + // Topview right joystick + DrawJoystickSideview(p, center + QPointF(180, -78), + -stick_values[Settings::NativeAnalog::RStick].x.value + 15.0f, 1, + button_values[RStick]); + // Topview face buttons p.setPen(colors.outline); button_color = colors.button; DrawRoundButton(p, center + QPoint(200, -71), button_values[A], 10, 5, Direction::Up); + DrawRoundButton(p, center + QPoint(180, -71), button_values[B], 10, 5, Direction::Up); + DrawRoundButton(p, center + QPoint(180, -71), button_values[X], 10, 5, Direction::Up); DrawRoundButton(p, center + QPoint(160, -71), button_values[Y], 10, 5, Direction::Up); - // Topview right joystick - DrawJoystickSideview(p, center + QPointF(180, -78), - -axis_values[Settings::NativeAnalog::RStick].value.x() + 15.0f, 1, - button_values[RStick]); - // Topview plus button p.setPen(colors.outline); button_color = colors.button; @@ -538,7 +523,7 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) // Topview left joystick DrawJoystickSideview(p, center + QPointF(-180.5f, -78), - -axis_values[Settings::NativeAnalog::LStick].value.x() + 15.0f, 1, + -stick_values[Settings::NativeAnalog::LStick].x.value + 15.0f, 1, button_values[LStick]); // Topview minus button @@ -557,13 +542,13 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) { // Draw joysticks using namespace Settings::NativeAnalog; - const auto& l_stick = axis_values[LStick]; + const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value); const auto l_button = button_values[Settings::NativeButton::LStick]; - const auto& r_stick = axis_values[RStick]; + const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value); const auto r_button = button_values[Settings::NativeButton::RStick]; - DrawJoystick(p, center + QPointF(-65, -65) + (l_stick.value * 7), 1.62f, l_button); - DrawJoystick(p, center + QPointF(65, 12) + (r_stick.value * 7), 1.62f, r_button); + DrawJoystick(p, center + QPointF(-65, -65) + (l_stick * 7), 1.62f, l_button); + DrawJoystick(p, center + QPointF(65, 12) + (r_stick * 7), 1.62f, r_button); DrawRawJoystick(p, center + QPointF(-180, 90), center + QPointF(180, 90)); } @@ -634,6 +619,12 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) p.setPen(colors.transparent); p.setBrush(colors.font2); DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f); + + // Draw battery + DrawBattery(p, center + QPoint(-100, -160), + battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); + DrawBattery(p, center + QPoint(40, -160), + battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]); } void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) { @@ -643,13 +634,13 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen { // Draw joysticks using namespace Settings::NativeAnalog; - const auto& l_stick = axis_values[LStick]; + const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value); const auto l_button = button_values[Settings::NativeButton::LStick]; - const auto& r_stick = axis_values[RStick]; + const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value); const auto r_button = button_values[Settings::NativeButton::RStick]; - DrawJoystick(p, center + QPointF(-171, -41) + (l_stick.value * 4), 1.0f, l_button); - DrawJoystick(p, center + QPointF(171, 8) + (r_stick.value * 4), 1.0f, r_button); + DrawJoystick(p, center + QPointF(-171, -41) + (l_stick * 4), 1.0f, l_button); + DrawJoystick(p, center + QPointF(171, 8) + (r_stick * 4), 1.0f, r_button); DrawRawJoystick(p, center + QPointF(-50, 0), center + QPointF(50, 0)); } @@ -732,6 +723,12 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen p.setPen(colors.transparent); p.setBrush(colors.font2); DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f); + + // Draw battery + DrawBattery(p, center + QPoint(-200, 110), + battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); + DrawBattery(p, center + QPoint(130, 110), + battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]); } void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) { @@ -741,9 +738,11 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) { // Draw joysticks using namespace Settings::NativeAnalog; - DrawProJoystick(p, center + QPointF(-111, -55), axis_values[LStick].value, 11, + const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value); + const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value); + DrawProJoystick(p, center + QPointF(-111, -55), l_stick, 11, button_values[Settings::NativeButton::LStick]); - DrawProJoystick(p, center + QPointF(51, 0), axis_values[RStick].value, 11, + DrawProJoystick(p, center + QPointF(51, 0), r_stick, 11, button_values[Settings::NativeButton::RStick]); DrawRawJoystick(p, center + QPointF(-50, 105), center + QPointF(50, 105)); } @@ -817,24 +816,27 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) p.setPen(colors.transparent); p.setBrush(colors.font2); DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f); + + // Draw battery + DrawBattery(p, center + QPoint(-30, -160), + battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); } void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) { - DrawGCTriggers(p, center, button_values[Settings::NativeButton::ZL], - button_values[Settings::NativeButton::ZR]); + DrawGCTriggers(p, center, trigger_values[0], trigger_values[1]); DrawGCButtonZ(p, center, button_values[Settings::NativeButton::R]); DrawGCBody(p, center); { // Draw joysticks using namespace Settings::NativeAnalog; - DrawGCJoystick(p, center + QPointF(-111, -44) + (axis_values[LStick].value * 10), false); + const auto l_stick = QPointF(stick_values[LStick].x.value, stick_values[LStick].y.value); + const auto r_stick = QPointF(stick_values[RStick].x.value, stick_values[RStick].y.value); + DrawGCJoystick(p, center + QPointF(-111, -44) + (l_stick * 10), {}); button_color = colors.button2; - DrawCircleButton(p, center + QPointF(61, 37) + (axis_values[RStick].value * 9.5f), false, - 15); + DrawCircleButton(p, center + QPointF(61, 37) + (r_stick * 9.5f), {}, 15); p.setPen(colors.transparent); p.setBrush(colors.font); - DrawSymbol(p, center + QPointF(61, 37) + (axis_values[RStick].value * 9.5f), Symbol::C, - 1.0f); + DrawSymbol(p, center + QPointF(61, 37) + (r_stick * 9.5f), Symbol::C, 1.0f); DrawRawJoystick(p, center + QPointF(-198, -125), center + QPointF(198, -125)); } @@ -871,6 +873,10 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) { // Minus and Plus buttons p.setPen(colors.outline); DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8); + + // Draw battery + DrawBattery(p, center + QPoint(-30, -165), + battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); } constexpr std::array<float, 13 * 2> symbol_a = { @@ -1837,10 +1843,14 @@ void PlayerControlPreview::DrawLeftBody(QPainter& p, const QPointF center) { const float led_size = 5.0f; const QPointF led_position = sideview_center + QPointF(0, -36); int led_count = 0; - for (const auto& color : led_color) { - p.setBrush(color); - DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); - } + p.setBrush(led_pattern.position1 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position2 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position3 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position4 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); } void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) { @@ -1933,14 +1943,19 @@ void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) { const float led_size = 5.0f; const QPointF led_position = sideview_center + QPointF(0, -36); int led_count = 0; - for (const auto& color : led_color) { - p.setBrush(color); - DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); - } -} - -void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bool left_pressed, - bool right_pressed) { + p.setBrush(led_pattern.position1 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position2 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position3 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); + p.setBrush(led_pattern.position4 ? colors.led_on : colors.led_off); + DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size); +} + +void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed) { std::array<QPointF, pro_left_trigger.size() / 2> qleft_trigger; std::array<QPointF, pro_left_trigger.size() / 2> qright_trigger; std::array<QPointF, pro_body_top.size()> qbody_top; @@ -1949,8 +1964,10 @@ void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bo const float trigger_x = pro_left_trigger[point * 2 + 0]; const float trigger_y = pro_left_trigger[point * 2 + 1]; - qleft_trigger[point] = center + QPointF(trigger_x, trigger_y + (left_pressed ? 2 : 0)); - qright_trigger[point] = center + QPointF(-trigger_x, trigger_y + (right_pressed ? 2 : 0)); + qleft_trigger[point] = + center + QPointF(trigger_x, trigger_y + (left_pressed.value ? 2 : 0)); + qright_trigger[point] = + center + QPointF(-trigger_x, trigger_y + (right_pressed.value ? 2 : 0)); } for (std::size_t point = 0; point < pro_body_top.size() / 2; ++point) { @@ -1967,16 +1984,17 @@ void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bo DrawPolygon(p, qbody_top); // Left trigger - p.setBrush(left_pressed ? colors.highlight : colors.button); + p.setBrush(left_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); // Right trigger - p.setBrush(right_pressed ? colors.highlight : colors.button); + p.setBrush(right_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); } -void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, bool left_pressed, - bool right_pressed) { +void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, + Common::Input::TriggerStatus left_trigger, + Common::Input::TriggerStatus right_trigger) { std::array<QPointF, left_gc_trigger.size() / 2> qleft_trigger; std::array<QPointF, left_gc_trigger.size() / 2> qright_trigger; @@ -1984,32 +2002,37 @@ void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, boo const float trigger_x = left_gc_trigger[point * 2 + 0]; const float trigger_y = left_gc_trigger[point * 2 + 1]; - qleft_trigger[point] = center + QPointF(trigger_x, trigger_y + (left_pressed ? 10 : 0)); - qright_trigger[point] = center + QPointF(-trigger_x, trigger_y + (right_pressed ? 10 : 0)); + qleft_trigger[point] = + center + QPointF(trigger_x, trigger_y + (left_trigger.analog.value * 10.0f)); + qright_trigger[point] = + center + QPointF(-trigger_x, trigger_y + (right_trigger.analog.value * 10.0f)); } // Left trigger p.setPen(colors.outline); - p.setBrush(left_pressed ? colors.highlight : colors.button); + p.setBrush(left_trigger.pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); // Right trigger - p.setBrush(right_pressed ? colors.highlight : colors.button); + p.setBrush(right_trigger.pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); // Draw L text p.setPen(colors.transparent); p.setBrush(colors.font); - DrawSymbol(p, center + QPointF(-132, -119 + (left_pressed ? 10 : 0)), Symbol::L, 1.7f); + DrawSymbol(p, center + QPointF(-132, -119 + (left_trigger.analog.value * 10.0f)), Symbol::L, + 1.7f); // Draw R text p.setPen(colors.transparent); p.setBrush(colors.font); - DrawSymbol(p, center + QPointF(121.5f, -119 + (right_pressed ? 10 : 0)), Symbol::R, 1.7f); + DrawSymbol(p, center + QPointF(121.5f, -119 + (right_trigger.analog.value * 10.0f)), Symbol::R, + 1.7f); } void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF center, - bool left_pressed, bool right_pressed) { + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed) { std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger; std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger; @@ -2018,23 +2041,24 @@ void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF cente const float left_trigger_y = left_joycon_trigger[point * 2 + 1]; qleft_trigger[point] = - center + QPointF(left_trigger_x, left_trigger_y + (left_pressed ? 0.5f : 0)); + center + QPointF(left_trigger_x, left_trigger_y + (left_pressed.value ? 0.5f : 0)); qright_trigger[point] = - center + QPointF(-left_trigger_x, left_trigger_y + (right_pressed ? 0.5f : 0)); + center + QPointF(-left_trigger_x, left_trigger_y + (right_pressed.value ? 0.5f : 0)); } // Left trigger p.setPen(colors.outline); - p.setBrush(left_pressed ? colors.highlight : colors.button); + p.setBrush(left_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); // Right trigger - p.setBrush(right_pressed ? colors.highlight : colors.button); + p.setBrush(right_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); } -void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, bool left_pressed, - bool right_pressed) { +void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed) { std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger; std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger; constexpr float size = 1.62f; @@ -2043,25 +2067,27 @@ void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, b const float left_trigger_x = left_joycon_trigger[point * 2 + 0]; const float left_trigger_y = left_joycon_trigger[point * 2 + 1]; - qleft_trigger[point] = center + QPointF(left_trigger_x * size + offset, - left_trigger_y * size + (left_pressed ? 0.5f : 0)); + qleft_trigger[point] = + center + QPointF(left_trigger_x * size + offset, + left_trigger_y * size + (left_pressed.value ? 0.5f : 0)); qright_trigger[point] = center + QPointF(-left_trigger_x * size - offset, - left_trigger_y * size + (right_pressed ? 0.5f : 0)); + left_trigger_y * size + (right_pressed.value ? 0.5f : 0)); } // Left trigger p.setPen(colors.outline); - p.setBrush(left_pressed ? colors.highlight : colors.button); + p.setBrush(left_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); // Right trigger - p.setBrush(right_pressed ? colors.highlight : colors.button); + p.setBrush(right_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); } -void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF center, - bool left_pressed, bool right_pressed) { +void PlayerControlPreview::DrawDualTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed) { std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger; std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger; constexpr float size = 0.9f; @@ -2080,9 +2106,9 @@ void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF ce } p.setPen(colors.outline); - p.setBrush(left_pressed ? colors.highlight : colors.button); + p.setBrush(left_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); - p.setBrush(right_pressed ? colors.highlight : colors.button); + p.setBrush(right_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); // Draw L text @@ -2096,8 +2122,9 @@ void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF ce DrawSymbol(p, center + QPointF(177, -84), Symbol::R, 1.0f); } -void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF center, - bool left_pressed, bool right_pressed) { +void PlayerControlPreview::DrawDualZTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed) { std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger; std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger; constexpr float size = 0.9f; @@ -2114,9 +2141,9 @@ void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF c } p.setPen(colors.outline); - p.setBrush(left_pressed ? colors.highlight : colors.button); + p.setBrush(left_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); - p.setBrush(right_pressed ? colors.highlight : colors.button); + p.setBrush(right_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); // Draw ZL text @@ -2130,7 +2157,8 @@ void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF c DrawSymbol(p, center + QPointF(180, -113), Symbol::ZR, 1.0f); } -void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, bool left_pressed) { +void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& left_pressed) { std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger; constexpr float size = 1.78f; constexpr float offset = 311.5f; @@ -2138,15 +2166,16 @@ void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, b for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) { qleft_trigger[point] = center + QPointF(left_joycon_trigger[point * 2] * size + offset, left_joycon_trigger[point * 2 + 1] * size - - (left_pressed ? 0.5f : 1.0f)); + (left_pressed.value ? 0.5f : 1.0f)); } p.setPen(colors.outline); - p.setBrush(left_pressed ? colors.highlight : colors.button); + p.setBrush(left_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); } -void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center, bool left_pressed) { +void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& left_pressed) { std::array<QPointF, left_joycon_sideview_zl.size() / 2> qleft_trigger; constexpr float size = 1.1115f; constexpr float offset2 = 335; @@ -2154,18 +2183,18 @@ void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center, for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) { qleft_trigger[point] = center + QPointF(left_joycon_sideview_zl[point * 2] * size + offset2, left_joycon_sideview_zl[point * 2 + 1] * size + - (left_pressed ? 1.5f : 1.0f)); + (left_pressed.value ? 1.5f : 1.0f)); } p.setPen(colors.outline); - p.setBrush(left_pressed ? colors.highlight : colors.button); + p.setBrush(left_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); - p.drawArc(center.x() + 158, center.y() + (left_pressed ? -203.5f : -204.0f), 77, 77, 225 * 16, - 44 * 16); + p.drawArc(center.x() + 158, center.y() + (left_pressed.value ? -203.5f : -204.0f), 77, 77, + 225 * 16, 44 * 16); } -void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF center, - bool left_pressed) { +void PlayerControlPreview::DrawLeftTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed) { std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger; for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) { @@ -2174,7 +2203,7 @@ void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF ce } p.setPen(colors.outline); - p.setBrush(left_pressed ? colors.highlight : colors.button); + p.setBrush(left_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); // Draw L text @@ -2183,8 +2212,8 @@ void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF ce DrawSymbol(p, center + QPointF(-143, -36), Symbol::L, 1.0f); } -void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF center, - bool left_pressed) { +void PlayerControlPreview::DrawLeftZTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& left_pressed) { std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger; for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) { @@ -2193,7 +2222,7 @@ void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF c } p.setPen(colors.outline); - p.setBrush(left_pressed ? colors.highlight : colors.button); + p.setBrush(left_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qleft_trigger); // Draw ZL text @@ -2203,7 +2232,7 @@ void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF c } void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center, - bool right_pressed) { + const Common::Input::ButtonStatus& right_pressed) { std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger; constexpr float size = 1.78f; constexpr float offset = 311.5f; @@ -2211,36 +2240,36 @@ void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center, for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) { qright_trigger[point] = center + QPointF(-left_joycon_trigger[point * 2] * size - offset, left_joycon_trigger[point * 2 + 1] * size - - (right_pressed ? 0.5f : 1.0f)); + (right_pressed.value ? 0.5f : 1.0f)); } p.setPen(colors.outline); - p.setBrush(right_pressed ? colors.highlight : colors.button); + p.setBrush(right_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); } void PlayerControlPreview::DrawRightZTriggers(QPainter& p, const QPointF center, - bool right_pressed) { + const Common::Input::ButtonStatus& right_pressed) { std::array<QPointF, left_joycon_sideview_zl.size() / 2> qright_trigger; constexpr float size = 1.1115f; constexpr float offset2 = 335; for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) { qright_trigger[point] = - center + - QPointF(-left_joycon_sideview_zl[point * 2] * size - offset2, - left_joycon_sideview_zl[point * 2 + 1] * size + (right_pressed ? 0.5f : 0) + 1); + center + QPointF(-left_joycon_sideview_zl[point * 2] * size - offset2, + left_joycon_sideview_zl[point * 2 + 1] * size + + (right_pressed.value ? 0.5f : 0) + 1); } p.setPen(colors.outline); - p.setBrush(right_pressed ? colors.highlight : colors.button); + p.setBrush(right_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); - p.drawArc(center.x() - 236, center.y() + (right_pressed ? -203.5f : -204.0f), 77, 77, 271 * 16, - 44 * 16); + p.drawArc(center.x() - 236, center.y() + (right_pressed.value ? -203.5f : -204.0f), 77, 77, + 271 * 16, 44 * 16); } -void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF center, - bool right_pressed) { +void PlayerControlPreview::DrawRightTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& right_pressed) { std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger; for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) { @@ -2249,7 +2278,7 @@ void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF c } p.setPen(colors.outline); - p.setBrush(right_pressed ? colors.highlight : colors.button); + p.setBrush(right_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); // Draw R text @@ -2258,8 +2287,8 @@ void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF c DrawSymbol(p, center + QPointF(137, -36), Symbol::R, 1.0f); } -void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF center, - bool right_pressed) { +void PlayerControlPreview::DrawRightZTriggersTopView( + QPainter& p, const QPointF center, const Common::Input::ButtonStatus& right_pressed) { std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger; for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) { @@ -2268,7 +2297,7 @@ void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF } p.setPen(colors.outline); - p.setBrush(right_pressed ? colors.highlight : colors.button); + p.setBrush(right_pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qright_trigger); // Draw ZR text @@ -2278,13 +2307,13 @@ void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF } void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float size, - bool pressed) { + const Common::Input::ButtonStatus& pressed) { const float radius1 = 13.0f * size; const float radius2 = 9.0f * size; // Outer circle p.setPen(colors.outline); - p.setBrush(pressed ? colors.highlight : colors.button); + p.setBrush(pressed.value ? colors.highlight : colors.button); DrawCircle(p, center, radius1); // Cross @@ -2292,17 +2321,18 @@ void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float p.drawLine(center - QPoint(0, radius1), center + QPoint(0, radius1)); // Inner circle - p.setBrush(pressed ? colors.highlight2 : colors.button2); + p.setBrush(pressed.value ? colors.highlight2 : colors.button2); DrawCircle(p, center, radius2); } void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF center, float angle, - float size, bool pressed) { + float size, + const Common::Input::ButtonStatus& pressed) { QVector<QPointF> joystick; joystick.reserve(static_cast<int>(left_joystick_sideview.size() / 2)); for (std::size_t point = 0; point < left_joystick_sideview.size() / 2; ++point) { - joystick.append(QPointF(left_joystick_sideview[point * 2] * size + (pressed ? 1 : 0), + joystick.append(QPointF(left_joystick_sideview[point * 2] * size + (pressed.value ? 1 : 0), left_joystick_sideview[point * 2 + 1] * size - 1)); } @@ -2314,14 +2344,15 @@ void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF cente // Draw joystick p.setPen(colors.outline); - p.setBrush(pressed ? colors.highlight : colors.button); + p.setBrush(pressed.value ? colors.highlight : colors.button); p.drawPolygon(p2); p.drawLine(p2.at(1), p2.at(30)); p.drawLine(p2.at(32), p2.at(71)); } void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, const QPointF offset, - float offset_scalar, bool pressed) { + float offset_scalar, + const Common::Input::ButtonStatus& pressed) { const float radius1 = 24.0f; const float radius2 = 17.0f; @@ -2339,11 +2370,11 @@ void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, co // Outer circle p.setPen(colors.outline); - p.setBrush(pressed ? colors.highlight : colors.button); + p.setBrush(pressed.value ? colors.highlight : colors.button); p.drawEllipse(QPointF(0, 0), radius1 * amplitude, radius1); // Inner circle - p.setBrush(pressed ? colors.highlight2 : colors.button2); + p.setBrush(pressed.value ? colors.highlight2 : colors.button2); const float inner_offset = (radius1 - radius2) * 0.4f * ((offset.x() == 0 && offset.y() < 0) ? -1.0f : 1.0f); @@ -2355,14 +2386,15 @@ void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, co p.restore(); } -void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, bool pressed) { +void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& pressed) { // Outer circle p.setPen(colors.outline); - p.setBrush(pressed ? colors.highlight : colors.button); + p.setBrush(pressed.value ? colors.highlight : colors.button); DrawCircle(p, center, 26.0f); // Inner circle - p.setBrush(pressed ? colors.highlight2 : colors.button2); + p.setBrush(pressed.value ? colors.highlight2 : colors.button2); DrawCircle(p, center, 19.0f); p.setBrush(colors.transparent); DrawCircle(p, center, 13.5f); @@ -2371,31 +2403,29 @@ void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, boo void PlayerControlPreview::DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right) { using namespace Settings::NativeAnalog; - if (controller_type != Settings::ControllerType::LeftJoycon) { - DrawJoystickProperties(p, center_right, axis_values[RStick].properties); + if (center_right != QPointF(0, 0)) { + DrawJoystickProperties(p, center_right, stick_values[RStick].x.properties); p.setPen(colors.indicator); p.setBrush(colors.indicator); - DrawJoystickDot(p, center_right, axis_values[RStick].raw_value, - axis_values[RStick].properties); + DrawJoystickDot(p, center_right, stick_values[RStick], true); p.setPen(colors.indicator2); p.setBrush(colors.indicator2); - DrawJoystickDot(p, center_right, axis_values[RStick].value, axis_values[RStick].properties); + DrawJoystickDot(p, center_right, stick_values[RStick], false); } - if (controller_type != Settings::ControllerType::RightJoycon) { - DrawJoystickProperties(p, center_left, axis_values[LStick].properties); + if (center_left != QPointF(0, 0)) { + DrawJoystickProperties(p, center_left, stick_values[LStick].x.properties); p.setPen(colors.indicator); p.setBrush(colors.indicator); - DrawJoystickDot(p, center_left, axis_values[LStick].raw_value, - axis_values[LStick].properties); + DrawJoystickDot(p, center_left, stick_values[LStick], true); p.setPen(colors.indicator2); p.setBrush(colors.indicator2); - DrawJoystickDot(p, center_left, axis_values[LStick].value, axis_values[LStick].properties); + DrawJoystickDot(p, center_left, stick_values[LStick], false); } } -void PlayerControlPreview::DrawJoystickProperties(QPainter& p, const QPointF center, - const Input::AnalogProperties& properties) { +void PlayerControlPreview::DrawJoystickProperties( + QPainter& p, const QPointF center, const Common::Input::AnalogProperties& properties) { constexpr float size = 45.0f; const float range = size * properties.range; const float deadzone = size * properties.deadzone; @@ -2414,19 +2444,26 @@ void PlayerControlPreview::DrawJoystickProperties(QPainter& p, const QPointF cen DrawCircle(p, center, deadzone); } -void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center, const QPointF value, - const Input::AnalogProperties& properties) { +void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center, + const Common::Input::StickStatus& stick, bool raw) { constexpr float size = 45.0f; - const float range = size * properties.range; + const float range = size * stick.x.properties.range; - // Dot pointer - DrawCircle(p, center + (value * range), 2); + if (raw) { + const QPointF value = QPointF(stick.x.raw_value, stick.y.raw_value) * size; + DrawCircle(p, center + value, 2); + return; + } + + const QPointF value = QPointF(stick.x.value, stick.y.value) * range; + DrawCircle(p, center + value, 2); } -void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width, +void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& pressed, float width, float height, Direction direction, float radius) { p.setBrush(button_color); - if (pressed) { + if (pressed.value) { switch (direction) { case Direction::Left: center.setX(center.x() - 1); @@ -2448,17 +2485,19 @@ void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, bool pre QRectF rect = {center.x() - width, center.y() - height, width * 2.0f, height * 2.0f}; p.drawRoundedRect(rect, radius, radius); } -void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center, bool pressed, +void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& pressed, int button_size) { p.setPen(colors.outline); - p.setBrush(pressed ? colors.highlight : colors.button); + p.setBrush(pressed.value ? colors.highlight : colors.button); DrawRectangle(p, center, button_size, button_size / 3.0f); } -void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, bool pressed, +void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& pressed, int button_size) { // Draw outer line p.setPen(colors.outline); - p.setBrush(pressed ? colors.highlight : colors.button); + p.setBrush(pressed.value ? colors.highlight : colors.button); DrawRectangle(p, center, button_size, button_size / 3.0f); DrawRectangle(p, center, button_size / 3.0f, button_size); @@ -2471,7 +2510,8 @@ void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, boo DrawRectangle(p, center, button_size / 3.0f, button_size); } -void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, bool pressed) { +void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& pressed) { std::array<QPointF, gc_button_x.size() / 2> button_x; for (std::size_t point = 0; point < gc_button_x.size() / 2; ++point) { @@ -2479,11 +2519,12 @@ void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, bool } p.setPen(colors.outline); - p.setBrush(pressed ? colors.highlight : colors.button); + p.setBrush(pressed.value ? colors.highlight : colors.button); DrawPolygon(p, button_x); } -void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, bool pressed) { +void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& pressed) { std::array<QPointF, gc_button_y.size() / 2> button_x; for (std::size_t point = 0; point < gc_button_y.size() / 2; ++point) { @@ -2491,27 +2532,29 @@ void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, bool } p.setPen(colors.outline); - p.setBrush(pressed ? colors.highlight : colors.button); + p.setBrush(pressed.value ? colors.highlight : colors.button); DrawPolygon(p, button_x); } -void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center, bool pressed) { +void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& pressed) { std::array<QPointF, gc_button_z.size() / 2> button_x; for (std::size_t point = 0; point < gc_button_z.size() / 2; ++point) { button_x[point] = center + QPointF(gc_button_z[point * 2], - gc_button_z[point * 2 + 1] + (pressed ? 1 : 0)); + gc_button_z[point * 2 + 1] + (pressed.value ? 1 : 0)); } p.setPen(colors.outline); - p.setBrush(pressed ? colors.highlight : colors.button2); + p.setBrush(pressed.value ? colors.highlight : colors.button2); DrawPolygon(p, button_x); } -void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center, bool pressed, +void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center, + const Common::Input::ButtonStatus& pressed, float button_size) { p.setBrush(button_color); - if (pressed) { + if (pressed.value) { p.setBrush(colors.highlight); } p.drawEllipse(center, button_size, button_size); @@ -2540,7 +2583,8 @@ void PlayerControlPreview::DrawArrowButtonOutline(QPainter& p, const QPointF cen } void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, - const Direction direction, bool pressed, float size) { + const Direction direction, + const Common::Input::ButtonStatus& pressed, float size) { std::array<QPointF, up_arrow_button.size() / 2> arrow_button; QPoint offset; @@ -2552,38 +2596,39 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, case Direction::Up: arrow_button[point] = center + QPointF(up_arrow_x * size, up_arrow_y * size); break; - case Direction::Left: - arrow_button[point] = center + QPointF(up_arrow_y * size, up_arrow_x * size); - break; case Direction::Right: arrow_button[point] = center + QPointF(-up_arrow_y * size, up_arrow_x * size); break; case Direction::Down: arrow_button[point] = center + QPointF(up_arrow_x * size, -up_arrow_y * size); break; + case Direction::Left: + // Compiler doesn't optimize this correctly check why + arrow_button[point] = center + QPointF(up_arrow_y * size, up_arrow_x * size); + break; case Direction::None: break; } } // Draw arrow button - p.setPen(pressed ? colors.highlight : colors.button); - p.setBrush(pressed ? colors.highlight : colors.button); + p.setPen(pressed.value ? colors.highlight : colors.button); + p.setBrush(pressed.value ? colors.highlight : colors.button); DrawPolygon(p, arrow_button); switch (direction) { case Direction::Up: offset = QPoint(0, -20 * size); break; - case Direction::Left: - offset = QPoint(-20 * size, 0); - break; case Direction::Right: offset = QPoint(20 * size, 0); break; case Direction::Down: offset = QPoint(0, 20 * size); break; + case Direction::Left: + offset = QPoint(-20 * size, 0); + break; case Direction::None: offset = QPoint(0, 0); break; @@ -2596,7 +2641,8 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, } void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center, - const Direction direction, bool pressed) { + const Direction direction, + const Common::Input::ButtonStatus& pressed) { std::array<QPointF, trigger_button.size() / 2> qtrigger_button; for (std::size_t point = 0; point < trigger_button.size() / 2; ++point) { @@ -2619,10 +2665,51 @@ void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center, // Draw arrow button p.setPen(colors.outline); - p.setBrush(pressed ? colors.highlight : colors.button); + p.setBrush(pressed.value ? colors.highlight : colors.button); DrawPolygon(p, qtrigger_button); } +void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center, + Common::Input::BatteryLevel battery) { + if (battery == Common::Input::BatteryLevel::None) { + return; + } + p.setPen(colors.outline); + p.setBrush(colors.transparent); + p.drawRect(center.x(), center.y(), 56, 20); + p.drawRect(center.x() + 56, center.y() + 6, 3, 8); + p.setBrush(colors.deadzone); + switch (battery) { + case Common::Input::BatteryLevel::Charging: + p.setBrush(colors.indicator2); + p.drawText(center + QPoint(2, 14), tr("Charging")); + break; + case Common::Input::BatteryLevel::Full: + p.drawRect(center.x() + 42, center.y(), 14, 20); + p.drawRect(center.x() + 28, center.y(), 14, 20); + p.drawRect(center.x() + 14, center.y(), 14, 20); + p.drawRect(center.x(), center.y(), 14, 20); + break; + case Common::Input::BatteryLevel::Medium: + p.drawRect(center.x() + 28, center.y(), 14, 20); + p.drawRect(center.x() + 14, center.y(), 14, 20); + p.drawRect(center.x(), center.y(), 14, 20); + break; + case Common::Input::BatteryLevel::Low: + p.drawRect(center.x() + 14, center.y(), 14, 20); + p.drawRect(center.x(), center.y(), 14, 20); + break; + case Common::Input::BatteryLevel::Critical: + p.drawRect(center.x(), center.y(), 14, 20); + break; + case Common::Input::BatteryLevel::Empty: + p.drawRect(center.x(), center.y(), 5, 20); + break; + default: + break; + } +} + void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol symbol, float icon_size) { std::array<QPointF, house.size() / 2> house_icon; diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index f4bbfa528..4cd5c3be0 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -7,9 +7,11 @@ #include <array> #include <QFrame> #include <QPointer> -#include "common/settings.h" -#include "core/frontend/input.h" -#include "yuzu/debugger/controller.h" + +#include "common/input.h" +#include "common/settings_input.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_types.h" class QLabel; @@ -24,17 +26,26 @@ public: explicit PlayerControlPreview(QWidget* parent); ~PlayerControlPreview() override; - void SetPlayerInput(std::size_t index, const ButtonParam& buttons_param, - const AnalogParam& analogs_param); - void SetPlayerInputRaw(std::size_t index, const Settings::ButtonsRaw& buttons_, - Settings::AnalogsRaw analogs_); - void SetConnectedStatus(bool checked); - void SetControllerType(Settings::ControllerType type); + // Sets the emulated controller to be displayed + void SetController(Core::HID::EmulatedController* controller); + + // Disables events from the emulated controller + void UnloadController(); + + // Starts blinking animation at the button specified void BeginMappingButton(std::size_t button_id); - void BeginMappingAnalog(std::size_t button_id); + + // Starts moving animation at the stick specified + void BeginMappingAnalog(std::size_t stick_id); + + // Stops any ongoing animation void EndMapping(); + + // Handles emulated controller events + void ControllerUpdate(Core::HID::ControllerTriggerType type); + + // Updates input on sheduled interval void UpdateInput(); - void SetCallBack(ControllerCallback callback_); protected: void paintEvent(QPaintEvent* event) override; @@ -63,22 +74,6 @@ private: SR, }; - struct AxisValue { - QPointF value{}; - QPointF raw_value{}; - Input::AnalogProperties properties{}; - int size{}; - QPoint offset{}; - bool active{}; - }; - - struct LedPattern { - bool position1; - bool position2; - bool position3; - bool position4; - }; - struct ColorMapping { QColor outline{}; QColor primary{}; @@ -101,7 +96,6 @@ private: QColor deadzone{}; }; - static LedPattern GetColorPattern(std::size_t index, bool player_on); void UpdateColors(); void ResetInputs(); @@ -122,47 +116,75 @@ private: void DrawGCBody(QPainter& p, QPointF center); // Draw triggers functions - void DrawProTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); - void DrawGCTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); - void DrawHandheldTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); - void DrawDualTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); - void DrawDualTriggersTopView(QPainter& p, QPointF center, bool left_pressed, - bool right_pressed); - void DrawDualZTriggersTopView(QPainter& p, QPointF center, bool left_pressed, - bool right_pressed); - void DrawLeftTriggers(QPainter& p, QPointF center, bool left_pressed); - void DrawLeftZTriggers(QPainter& p, QPointF center, bool left_pressed); - void DrawLeftTriggersTopView(QPainter& p, QPointF center, bool left_pressed); - void DrawLeftZTriggersTopView(QPainter& p, QPointF center, bool left_pressed); - void DrawRightTriggers(QPainter& p, QPointF center, bool right_pressed); - void DrawRightZTriggers(QPainter& p, QPointF center, bool right_pressed); - void DrawRightTriggersTopView(QPainter& p, QPointF center, bool right_pressed); - void DrawRightZTriggersTopView(QPainter& p, QPointF center, bool right_pressed); + void DrawProTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed); + void DrawGCTriggers(QPainter& p, QPointF center, Common::Input::TriggerStatus left_trigger, + Common::Input::TriggerStatus right_trigger); + void DrawHandheldTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed); + void DrawDualTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed); + void DrawDualTriggersTopView(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed); + void DrawDualZTriggersTopView(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed, + const Common::Input::ButtonStatus& right_pressed); + void DrawLeftTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed); + void DrawLeftZTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed); + void DrawLeftTriggersTopView(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed); + void DrawLeftZTriggersTopView(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& left_pressed); + void DrawRightTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& right_pressed); + void DrawRightZTriggers(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& right_pressed); + void DrawRightTriggersTopView(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& right_pressed); + void DrawRightZTriggersTopView(QPainter& p, QPointF center, + const Common::Input::ButtonStatus& right_pressed); // Draw joystick functions - void DrawJoystick(QPainter& p, QPointF center, float size, bool pressed); - void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size, bool pressed); + void DrawJoystick(QPainter& p, QPointF center, float size, + const Common::Input::ButtonStatus& pressed); + void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size, + const Common::Input::ButtonStatus& pressed); void DrawRawJoystick(QPainter& p, QPointF center_left, QPointF center_right); void DrawJoystickProperties(QPainter& p, QPointF center, - const Input::AnalogProperties& properties); - void DrawJoystickDot(QPainter& p, QPointF center, QPointF value, - const Input::AnalogProperties& properties); - void DrawProJoystick(QPainter& p, QPointF center, QPointF offset, float scalar, bool pressed); - void DrawGCJoystick(QPainter& p, QPointF center, bool pressed); + const Common::Input::AnalogProperties& properties); + void DrawJoystickDot(QPainter& p, QPointF center, const Common::Input::StickStatus& stick, + bool raw); + void DrawProJoystick(QPainter& p, QPointF center, QPointF offset, float scalar, + const Common::Input::ButtonStatus& pressed); + void DrawGCJoystick(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed); // Draw button functions - void DrawCircleButton(QPainter& p, QPointF center, bool pressed, float button_size); - void DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width, float height, - Direction direction = Direction::None, float radius = 2); - void DrawMinusButton(QPainter& p, QPointF center, bool pressed, int button_size); - void DrawPlusButton(QPainter& p, QPointF center, bool pressed, int button_size); - void DrawGCButtonX(QPainter& p, QPointF center, bool pressed); - void DrawGCButtonY(QPainter& p, QPointF center, bool pressed); - void DrawGCButtonZ(QPainter& p, QPointF center, bool pressed); + void DrawCircleButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed, + float button_size); + void DrawRoundButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed, + float width, float height, Direction direction = Direction::None, + float radius = 2); + void DrawMinusButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed, + int button_size); + void DrawPlusButton(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed, + int button_size); + void DrawGCButtonX(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed); + void DrawGCButtonY(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed); + void DrawGCButtonZ(QPainter& p, QPointF center, const Common::Input::ButtonStatus& pressed); void DrawArrowButtonOutline(QPainter& p, const QPointF center, float size = 1.0f); - void DrawArrowButton(QPainter& p, QPointF center, Direction direction, bool pressed, - float size = 1.0f); - void DrawTriggerButton(QPainter& p, QPointF center, Direction direction, bool pressed); + void DrawArrowButton(QPainter& p, QPointF center, Direction direction, + const Common::Input::ButtonStatus& pressed, float size = 1.0f); + void DrawTriggerButton(QPainter& p, QPointF center, Direction direction, + const Common::Input::ButtonStatus& pressed); + + // Draw battery functions + void DrawBattery(QPainter& p, QPointF center, Common::Input::BatteryLevel battery); // Draw icon functions void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size); @@ -178,24 +200,23 @@ private: void SetTextFont(QPainter& p, float text_size, const QString& font_family = QStringLiteral("sans-serif")); - using ButtonArray = - std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::BUTTON_NS_END>; - using StickArray = - std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>; + bool is_controller_set{}; + bool is_connected{}; + bool needs_redraw{}; + Core::HID::NpadStyleIndex controller_type; - ControllerCallback controller_callback; - bool is_enabled{}; bool mapping_active{}; int blink_counter{}; + int callback_key; QColor button_color{}; ColorMapping colors{}; - std::array<QColor, 4> led_color{}; - ButtonArray buttons{}; - StickArray sticks{}; + Core::HID::LedPattern led_pattern{0, 0, 0, 0}; std::size_t player_index{}; - std::size_t button_mapping_index{Settings::NativeButton::BUTTON_NS_END}; - std::size_t analog_mapping_index{Settings::NativeAnalog::NUM_STICKS_HID}; - std::array<AxisValue, Settings::NativeAnalog::NUM_STICKS_HID> axis_values{}; - std::array<bool, Settings::NativeButton::NumButtons> button_values{}; - Settings::ControllerType controller_type{Settings::ControllerType::ProController}; + Core::HID::EmulatedController* controller; + std::size_t button_mapping_index{Settings::NativeButton::NumButtons}; + std::size_t analog_mapping_index{Settings::NativeAnalog::NumAnalogs}; + Core::HID::ButtonValues button_values{}; + Core::HID::SticksValues stick_values{}; + Core::HID::TriggerValues trigger_values{}; + Core::HID::BatteryValues battery_values{}; }; diff --git a/src/yuzu/configuration/configure_input_profile_dialog.cpp b/src/yuzu/configuration/configure_input_profile_dialog.cpp index cd5a88cea..17bbe6b61 100644 --- a/src/yuzu/configuration/configure_input_profile_dialog.cpp +++ b/src/yuzu/configuration/configure_input_profile_dialog.cpp @@ -11,8 +11,8 @@ ConfigureInputProfileDialog::ConfigureInputProfileDialog( QWidget* parent, InputCommon::InputSubsystem* input_subsystem, InputProfiles* profiles, Core::System& system) : QDialog(parent), ui(std::make_unique<Ui::ConfigureInputProfileDialog>()), - profile_widget( - new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, system, false)) { + profile_widget(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, + system.HIDCore(), system.IsPoweredOn(), false)) { ui->setupUi(this); ui->controllerLayout->addWidget(profile_widget); diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp index f8e08c422..8539a5c8b 100644 --- a/src/yuzu/configuration/configure_motion_touch.cpp +++ b/src/yuzu/configuration/configure_motion_touch.cpp @@ -15,9 +15,9 @@ #include "common/logging/log.h" #include "common/settings.h" +#include "input_common/drivers/udp_client.h" +#include "input_common/helpers/udp_protocol.h" #include "input_common/main.h" -#include "input_common/udp/client.h" -#include "input_common/udp/udp.h" #include "ui_configure_motion_touch.h" #include "yuzu/configuration/configure_motion_touch.h" #include "yuzu/configuration/configure_touch_from_button.h" @@ -93,6 +93,7 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent, "using-a-controller-or-android-phone-for-motion-or-touch-input'><span " "style=\"text-decoration: underline; color:#039be5;\">Learn More</span></a>")); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); SetConfiguration(); UpdateUiDisplay(); ConnectEvents(); @@ -101,17 +102,14 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent, ConfigureMotionTouch::~ConfigureMotionTouch() = default; void ConfigureMotionTouch::SetConfiguration() { - const Common::ParamPackage motion_param(Settings::values.motion_device.GetValue()); const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue()); - ui->touch_from_button_checkbox->setChecked(Settings::values.use_touch_from_button.GetValue()); touch_from_button_maps = Settings::values.touch_from_button_maps; for (const auto& touch_map : touch_from_button_maps) { ui->touch_from_button_map->addItem(QString::fromStdString(touch_map.name)); } ui->touch_from_button_map->setCurrentIndex( Settings::values.touch_from_button_map_index.GetValue()); - ui->motion_sensitivity->setValue(motion_param.Get("sensitivity", 0.01f)); min_x = touch_param.Get("min_x", 100); min_y = touch_param.Get("min_y", 50); @@ -139,9 +137,6 @@ void ConfigureMotionTouch::SetConfiguration() { void ConfigureMotionTouch::UpdateUiDisplay() { const QString cemuhook_udp = QStringLiteral("cemuhookudp"); - ui->motion_sensitivity_label->setVisible(true); - ui->motion_sensitivity->setVisible(true); - ui->touch_calibration->setVisible(true); ui->touch_calibration_config->setVisible(true); ui->touch_calibration_label->setVisible(true); @@ -312,7 +307,6 @@ void ConfigureMotionTouch::ApplyConfiguration() { touch_param.Set("max_y", max_y); Settings::values.touch_device = touch_param.Serialize(); - Settings::values.use_touch_from_button = ui->touch_from_button_checkbox->isChecked(); Settings::values.touch_from_button_map_index = ui->touch_from_button_map->currentIndex(); Settings::values.touch_from_button_maps = touch_from_button_maps; Settings::values.udp_input_servers = GetUDPServerString(); diff --git a/src/yuzu/configuration/configure_motion_touch.ui b/src/yuzu/configuration/configure_motion_touch.ui index 1e35ea946..c75a84ae4 100644 --- a/src/yuzu/configuration/configure_motion_touch.ui +++ b/src/yuzu/configuration/configure_motion_touch.ui @@ -2,14 +2,6 @@ <ui version="4.0"> <class>ConfigureMotionTouch</class> <widget class="QDialog" name="ConfigureMotionTouch"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>500</width> - <height>482</height> - </rect> - </property> <property name="windowTitle"> <string>Configure Motion / Touch</string> </property> @@ -18,48 +10,6 @@ </property> <layout class="QVBoxLayout"> <item> - <widget class="QGroupBox" name="motion_group_box"> - <property name="title"> - <string>Mouse Motion</string> - </property> - <layout class="QVBoxLayout"> - <item> - <layout class="QHBoxLayout"> - <item> - <widget class="QLabel" name="motion_sensitivity_label"> - <property name="text"> - <string>Sensitivity:</string> - </property> - </widget> - </item> - <item> - <widget class="QDoubleSpinBox" name="motion_sensitivity"> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="decimals"> - <number>4</number> - </property> - <property name="minimum"> - <double>0.010000000000000</double> - </property> - <property name="maximum"> - <double>10.000000000000000</double> - </property> - <property name="singleStep"> - <double>0.001000000000000</double> - </property> - <property name="value"> - <double>0.010000000000000</double> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> <widget class="QGroupBox" name="touch_group_box"> <property name="title"> <string>Touch</string> @@ -101,19 +51,13 @@ </item> <item> <layout class="QHBoxLayout"> - <item> - <widget class="QCheckBox" name="touch_from_button_checkbox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Use button mapping:</string> - </property> - </widget> - </item> + <item> + <widget class="QLabel" name="touch_from_button_label"> + <property name="text"> + <string>Touch from button profile:</string> + </property> + </widget> + </item> <item> <widget class="QComboBox" name="touch_from_button_map"/> </item> diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp deleted file mode 100644 index 2af3afda8..000000000 --- a/src/yuzu/configuration/configure_mouse_advanced.cpp +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <memory> - -#include <QKeyEvent> -#include <QMenu> -#include <QTimer> - -#include "common/assert.h" -#include "common/param_package.h" -#include "input_common/main.h" -#include "ui_configure_mouse_advanced.h" -#include "yuzu/configuration/config.h" -#include "yuzu/configuration/configure_mouse_advanced.h" - -static QString GetKeyName(int key_code) { - switch (key_code) { - case Qt::LeftButton: - return QObject::tr("Click 0"); - case Qt::RightButton: - return QObject::tr("Click 1"); - case Qt::MiddleButton: - return QObject::tr("Click 2"); - case Qt::BackButton: - return QObject::tr("Click 3"); - case Qt::ForwardButton: - return QObject::tr("Click 4"); - case Qt::Key_Shift: - return QObject::tr("Shift"); - case Qt::Key_Control: - return QObject::tr("Ctrl"); - case Qt::Key_Alt: - return QObject::tr("Alt"); - case Qt::Key_Meta: - return {}; - default: - return QKeySequence(key_code).toString(); - } -} - -static QString ButtonToText(const Common::ParamPackage& param) { - if (!param.Has("engine")) { - return QObject::tr("[not set]"); - } - - if (param.Get("engine", "") == "keyboard") { - return GetKeyName(param.Get("code", 0)); - } - - if (param.Get("engine", "") == "sdl") { - if (param.Has("hat")) { - const QString hat_str = QString::fromStdString(param.Get("hat", "")); - const QString direction_str = QString::fromStdString(param.Get("direction", "")); - - return QObject::tr("Hat %1 %2").arg(hat_str, direction_str); - } - - if (param.Has("axis")) { - const QString axis_str = QString::fromStdString(param.Get("axis", "")); - const QString direction_str = QString::fromStdString(param.Get("direction", "")); - - return QObject::tr("Axis %1%2").arg(axis_str, direction_str); - } - - if (param.Has("button")) { - const QString button_str = QString::fromStdString(param.Get("button", "")); - - return QObject::tr("Button %1").arg(button_str); - } - return {}; - } - - return QObject::tr("[unknown]"); -} - -ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent, - InputCommon::InputSubsystem* input_subsystem_) - : QDialog(parent), - ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), input_subsystem{input_subsystem_}, - timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { - ui->setupUi(this); - setFocusPolicy(Qt::ClickFocus); - - button_map = { - ui->left_button, ui->right_button, ui->middle_button, ui->forward_button, ui->back_button, - }; - - for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) { - auto* const button = button_map[button_id]; - if (button == nullptr) { - continue; - } - - button->setContextMenuPolicy(Qt::CustomContextMenu); - connect(button, &QPushButton::clicked, [=, this] { - HandleClick( - button_map[button_id], - [=, this](const Common::ParamPackage& params) { - buttons_param[button_id] = params; - }, - InputCommon::Polling::DeviceType::Button); - }); - connect(button, &QPushButton::customContextMenuRequested, - [=, this](const QPoint& menu_location) { - QMenu context_menu; - context_menu.addAction(tr("Clear"), [&] { - buttons_param[button_id].Clear(); - button_map[button_id]->setText(tr("[not set]")); - }); - context_menu.addAction(tr("Restore Default"), [&] { - buttons_param[button_id] = - Common::ParamPackage{InputCommon::GenerateKeyboardParam( - Config::default_mouse_buttons[button_id])}; - button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); - }); - context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); - }); - } - - connect(ui->buttonClearAll, &QPushButton::clicked, [this] { ClearAll(); }); - connect(ui->buttonRestoreDefaults, &QPushButton::clicked, [this] { RestoreDefaults(); }); - - timeout_timer->setSingleShot(true); - connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); - - connect(poll_timer.get(), &QTimer::timeout, [this] { - Common::ParamPackage params; - for (auto& poller : device_pollers) { - params = poller->GetNextInput(); - if (params.Has("engine")) { - SetPollingResult(params, false); - return; - } - } - }); - - LoadConfiguration(); - resize(0, 0); -} - -ConfigureMouseAdvanced::~ConfigureMouseAdvanced() = default; - -void ConfigureMouseAdvanced::ApplyConfiguration() { - std::transform(buttons_param.begin(), buttons_param.end(), - Settings::values.mouse_buttons.begin(), - [](const Common::ParamPackage& param) { return param.Serialize(); }); -} - -void ConfigureMouseAdvanced::LoadConfiguration() { - std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(), - buttons_param.begin(), - [](const std::string& str) { return Common::ParamPackage(str); }); - UpdateButtonLabels(); -} - -void ConfigureMouseAdvanced::changeEvent(QEvent* event) { - if (event->type() == QEvent::LanguageChange) { - RetranslateUI(); - } - - QDialog::changeEvent(event); -} - -void ConfigureMouseAdvanced::RetranslateUI() { - ui->retranslateUi(this); -} - -void ConfigureMouseAdvanced::RestoreDefaults() { - for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) { - buttons_param[button_id] = Common::ParamPackage{ - InputCommon::GenerateKeyboardParam(Config::default_mouse_buttons[button_id])}; - } - - UpdateButtonLabels(); -} - -void ConfigureMouseAdvanced::ClearAll() { - for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - const auto* const button = button_map[i]; - if (button != nullptr && button->isEnabled()) { - buttons_param[i].Clear(); - } - } - - UpdateButtonLabels(); -} - -void ConfigureMouseAdvanced::UpdateButtonLabels() { - for (int button = 0; button < Settings::NativeMouseButton::NumMouseButtons; button++) { - button_map[button]->setText(ButtonToText(buttons_param[button])); - } -} - -void ConfigureMouseAdvanced::HandleClick( - QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, - InputCommon::Polling::DeviceType type) { - button->setText(tr("[press key]")); - button->setFocus(); - - // Keyboard keys or mouse buttons can only be used as button devices - want_keyboard_mouse = type == InputCommon::Polling::DeviceType::Button; - if (want_keyboard_mouse) { - const auto iter = std::find(button_map.begin(), button_map.end(), button); - ASSERT(iter != button_map.end()); - const auto index = std::distance(button_map.begin(), iter); - ASSERT(index < Settings::NativeButton::NumButtons && index >= 0); - } - - input_setter = new_input_setter; - - device_pollers = input_subsystem->GetPollers(type); - - for (auto& poller : device_pollers) { - poller->Start(); - } - - QWidget::grabMouse(); - QWidget::grabKeyboard(); - - timeout_timer->start(2500); // Cancel after 2.5 seconds - poll_timer->start(50); // Check for new inputs every 50ms -} - -void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) { - timeout_timer->stop(); - poll_timer->stop(); - for (auto& poller : device_pollers) { - poller->Stop(); - } - - QWidget::releaseMouse(); - QWidget::releaseKeyboard(); - - if (!abort) { - (*input_setter)(params); - } - - UpdateButtonLabels(); - input_setter = std::nullopt; -} - -void ConfigureMouseAdvanced::mousePressEvent(QMouseEvent* event) { - if (!input_setter || !event) { - return; - } - - if (want_keyboard_mouse) { - SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())}, - false); - } else { - // We don't want any mouse buttons, so don't stop polling - return; - } - - SetPollingResult({}, true); -} - -void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { - if (!input_setter || !event) { - return; - } - - if (event->key() != Qt::Key_Escape) { - if (want_keyboard_mouse) { - SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, - false); - } else { - // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling - return; - } - } - SetPollingResult({}, true); -} diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h deleted file mode 100644 index 65b6fca9a..000000000 --- a/src/yuzu/configuration/configure_mouse_advanced.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <memory> -#include <optional> -#include <QDialog> - -class QCheckBox; -class QPushButton; -class QTimer; - -namespace InputCommon { -class InputSubsystem; -} - -namespace Ui { -class ConfigureMouseAdvanced; -} - -class ConfigureMouseAdvanced : public QDialog { - Q_OBJECT - -public: - explicit ConfigureMouseAdvanced(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_); - ~ConfigureMouseAdvanced() override; - - void ApplyConfiguration(); - -private: - void changeEvent(QEvent* event) override; - void RetranslateUI(); - - /// Load configuration settings. - void LoadConfiguration(); - /// Restore all buttons to their default values. - void RestoreDefaults(); - /// Clear all input configuration - void ClearAll(); - - /// Update UI to reflect current configuration. - void UpdateButtonLabels(); - - /// Called when the button was pressed. - void HandleClick(QPushButton* button, - std::function<void(const Common::ParamPackage&)> new_input_setter, - InputCommon::Polling::DeviceType type); - - /// Finish polling and configure input using the input_setter - void SetPollingResult(const Common::ParamPackage& params, bool abort); - - /// Handle mouse button press events. - void mousePressEvent(QMouseEvent* event) override; - - /// Handle key press events. - void keyPressEvent(QKeyEvent* event) override; - - std::unique_ptr<Ui::ConfigureMouseAdvanced> ui; - - InputCommon::InputSubsystem* input_subsystem; - - /// This will be the the setting function when an input is awaiting configuration. - std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; - - std::array<QPushButton*, Settings::NativeMouseButton::NumMouseButtons> button_map; - std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons> buttons_param; - - std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers; - - std::unique_ptr<QTimer> timeout_timer; - std::unique_ptr<QTimer> poll_timer; - - /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, - /// keyboard events are ignored. - bool want_keyboard_mouse = false; -}; diff --git a/src/yuzu/configuration/configure_mouse_advanced.ui b/src/yuzu/configuration/configure_mouse_advanced.ui deleted file mode 100644 index 5b99e1c37..000000000 --- a/src/yuzu/configuration/configure_mouse_advanced.ui +++ /dev/null @@ -1,335 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ConfigureMouseAdvanced</class> - <widget class="QDialog" name="ConfigureMouseAdvanced"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>310</width> - <height>193</height> - </rect> - </property> - <property name="windowTitle"> - <string>Configure Mouse</string> - </property> - <property name="styleSheet"> - <string notr="true">QPushButton { - min-width: 60px; -}</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QGroupBox" name="gridGroupBox"> - <property name="title"> - <string>Mouse Buttons</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="3" column="5"> - <layout class="QVBoxLayout" name="verticalLayout_6"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Forward:</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QPushButton" name="forward_button"> - <property name="minimumSize"> - <size> - <width>68</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>68</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </item> - <item row="3" column="1"> - <layout class="QVBoxLayout" name="verticalLayout_5"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QLabel" name="label_4"> - <property name="minimumSize"> - <size> - <width>54</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>Back:</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QPushButton" name="back_button"> - <property name="minimumSize"> - <size> - <width>68</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </item> - <item row="0" column="1"> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Left:</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QPushButton" name="left_button"> - <property name="minimumSize"> - <size> - <width>68</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </item> - <item row="0" column="3"> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Middle:</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QPushButton" name="middle_button"> - <property name="minimumSize"> - <size> - <width>68</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>68</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </item> - <item row="0" column="6"> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="5"> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Right:</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QPushButton" name="right_button"> - <property name="minimumSize"> - <size> - <width>68</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>68</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </item> - <item row="0" column="2"> - <spacer name="horizontalSpacer_4"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="4"> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <widget class="QPushButton" name="buttonClearAll"> - <property name="minimumSize"> - <size> - <width>68</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>68</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>Clear</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="buttonRestoreDefaults"> - <property name="minimumSize"> - <size> - <width>68</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>68</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>Defaults</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="styleSheet"> - <string notr="true"/> - </property> - <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>ConfigureMouseAdvanced</receiver> - <slot>accept()</slot> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>ConfigureMouseAdvanced</receiver> - <slot>reject()</slot> - </connection> - </connections> -</ui> diff --git a/src/yuzu/configuration/configure_tas.cpp b/src/yuzu/configuration/configure_tas.cpp index 8e5a4c72d..979a8db61 100644 --- a/src/yuzu/configuration/configure_tas.cpp +++ b/src/yuzu/configuration/configure_tas.cpp @@ -32,7 +32,6 @@ void ConfigureTasDialog::LoadConfiguration() { ui->tas_path_edit->setText( QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::TASDir))); ui->tas_enable->setChecked(Settings::values.tas_enable.GetValue()); - ui->tas_control_swap->setChecked(Settings::values.tas_swap_controllers.GetValue()); ui->tas_loop_script->setChecked(Settings::values.tas_loop.GetValue()); ui->tas_pause_on_load->setChecked(Settings::values.pause_tas_on_load.GetValue()); } @@ -40,7 +39,6 @@ void ConfigureTasDialog::LoadConfiguration() { void ConfigureTasDialog::ApplyConfiguration() { Common::FS::SetYuzuPath(Common::FS::YuzuPath::TASDir, ui->tas_path_edit->text().toStdString()); Settings::values.tas_enable.SetValue(ui->tas_enable->isChecked()); - Settings::values.tas_swap_controllers.SetValue(ui->tas_control_swap->isChecked()); Settings::values.tas_loop.SetValue(ui->tas_loop_script->isChecked()); Settings::values.pause_tas_on_load.SetValue(ui->tas_pause_on_load->isChecked()); } diff --git a/src/yuzu/configuration/configure_tas.ui b/src/yuzu/configuration/configure_tas.ui index 7d44895c4..cf88a5bf0 100644 --- a/src/yuzu/configuration/configure_tas.ui +++ b/src/yuzu/configuration/configure_tas.ui @@ -59,20 +59,13 @@ </widget> </item> <item row="1" column="0" colspan="4"> - <widget class="QCheckBox" name="tas_control_swap"> - <property name="text"> - <string>Automatic controller profile swapping</string> - </property> - </widget> - </item> - <item row="2" column="0" colspan="4"> <widget class="QCheckBox" name="tas_loop_script"> <property name="text"> <string>Loop script</string> </property> </widget> </item> - <item row="3" column="0" colspan="4"> + <item row="2" column="0" colspan="4"> <widget class="QCheckBox" name="tas_pause_on_load"> <property name="enabled"> <bool>false</bool> diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp index 40129f228..bde0a08c4 100644 --- a/src/yuzu/configuration/configure_touch_from_button.cpp +++ b/src/yuzu/configuration/configure_touch_from_button.cpp @@ -163,13 +163,10 @@ void ConfigureTouchFromButton::ConnectEvents() { connect(timeout_timer.get(), &QTimer::timeout, [this]() { SetPollingResult({}, true); }); connect(poll_timer.get(), &QTimer::timeout, [this]() { - Common::ParamPackage params; - for (auto& poller : device_pollers) { - params = poller->GetNextInput(); - if (params.Has("engine")) { - SetPollingResult(params, false); - return; - } + const auto& params = input_subsystem->GetNextInput(); + if (params.Has("engine")) { + SetPollingResult(params, false); + return; } }); } @@ -248,11 +245,7 @@ void ConfigureTouchFromButton::GetButtonInput(const int row_index, const bool is } }; - device_pollers = input_subsystem->GetPollers(InputCommon::Polling::DeviceType::Button); - - for (auto& poller : device_pollers) { - poller->Start(); - } + input_subsystem->BeginMapping(InputCommon::Polling::InputType::Button); grabKeyboard(); grabMouse(); @@ -365,14 +358,14 @@ void ConfigureTouchFromButton::SetCoordinates(const int dot_id, const QPoint& po void ConfigureTouchFromButton::SetPollingResult(const Common::ParamPackage& params, const bool cancel) { + timeout_timer->stop(); + poll_timer->stop(); + input_subsystem->StopMapping(); + releaseKeyboard(); releaseMouse(); qApp->restoreOverrideCursor(); - timeout_timer->stop(); - poll_timer->stop(); - for (auto& poller : device_pollers) { - poller->Stop(); - } + if (input_setter) { (*input_setter)(params, cancel); input_setter.reset(); diff --git a/src/yuzu/configuration/configure_touch_from_button.h b/src/yuzu/configuration/configure_touch_from_button.h index d9513e3bc..e1400481a 100644 --- a/src/yuzu/configuration/configure_touch_from_button.h +++ b/src/yuzu/configuration/configure_touch_from_button.h @@ -24,10 +24,6 @@ namespace InputCommon { class InputSubsystem; } -namespace InputCommon::Polling { -class DevicePoller; -} - namespace Settings { struct TouchFromButtonMap; } @@ -85,7 +81,6 @@ private: std::unique_ptr<QTimer> timeout_timer; std::unique_ptr<QTimer> poll_timer; - std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers; std::optional<std::function<void(const Common::ParamPackage&, bool)>> input_setter; static constexpr int DataRoleDot = Qt::ItemDataRole::UserRole + 2; diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp index 46a0f3025..adce04b27 100644 --- a/src/yuzu/configuration/configure_vibration.cpp +++ b/src/yuzu/configuration/configure_vibration.cpp @@ -59,80 +59,6 @@ void ConfigureVibration::ApplyConfiguration() { ui->checkBoxAccurateVibration->isChecked()); } -void ConfigureVibration::SetVibrationDevices(std::size_t player_index) { - using namespace Settings::NativeButton; - static constexpr std::array<std::array<Settings::NativeButton::Values, 6>, 2> buttons{{ - {DLeft, DUp, DRight, DDown, L, ZL}, // Left Buttons - {A, B, X, Y, R, ZR}, // Right Buttons - }}; - - auto& player = Settings::values.players.GetValue()[player_index]; - - for (std::size_t device_idx = 0; device_idx < buttons.size(); ++device_idx) { - std::unordered_map<std::string, int> params_count; - - for (const auto button_index : buttons[device_idx]) { - const auto& player_button = player.buttons[button_index]; - - if (params_count.find(player_button) != params_count.end()) { - ++params_count[player_button]; - continue; - } - - params_count.insert_or_assign(player_button, 1); - } - - const auto it = std::max_element( - params_count.begin(), params_count.end(), - [](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; }); - - auto& vibration_param_str = player.vibrations[device_idx]; - vibration_param_str.clear(); - - if (it->first.empty()) { - continue; - } - - const auto param = Common::ParamPackage(it->first); - - const auto engine = param.Get("engine", ""); - const auto guid = param.Get("guid", ""); - const auto port = param.Get("port", ""); - - if (engine.empty() || engine == "keyboard" || engine == "mouse" || engine == "tas") { - continue; - } - - vibration_param_str += fmt::format("engine:{}", engine); - - if (!port.empty()) { - vibration_param_str += fmt::format(",port:{}", port); - } - if (!guid.empty()) { - vibration_param_str += fmt::format(",guid:{}", guid); - } - } - - if (player.vibrations[0] != player.vibrations[1]) { - return; - } - - if (!player.vibrations[0].empty() && - player.controller_type != Settings::ControllerType::RightJoycon) { - player.vibrations[1].clear(); - } else if (!player.vibrations[1].empty() && - player.controller_type == Settings::ControllerType::RightJoycon) { - player.vibrations[0].clear(); - } -} - -void ConfigureVibration::SetAllVibrationDevices() { - // Set vibration devices for all player indices including handheld - for (std::size_t player_idx = 0; player_idx < NUM_PLAYERS + 1; ++player_idx) { - SetVibrationDevices(player_idx); - } -} - void ConfigureVibration::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { RetranslateUI(); diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h index 07411a86f..37bbc2653 100644 --- a/src/yuzu/configuration/configure_vibration.h +++ b/src/yuzu/configuration/configure_vibration.h @@ -24,9 +24,6 @@ public: void ApplyConfiguration(); - static void SetVibrationDevices(std::size_t player_index); - static void SetAllVibrationDevices(); - private: void changeEvent(QEvent* event) override; void RetranslateUI(); |