| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | // Copyright 2016 Citra Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | #include <memory>
 | 
					
						
							|  |  |  | #include <utility>
 | 
					
						
							| 
									
										
										
										
											2018-12-01 11:11:11 -05:00
										 |  |  | #include <QGridLayout>
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | #include <QInputDialog>
 | 
					
						
							| 
									
										
										
										
											2019-01-17 12:06:38 -05:00
										 |  |  | #include <QKeyEvent>
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | #include <QMenu>
 | 
					
						
							|  |  |  | #include <QMessageBox>
 | 
					
						
							|  |  |  | #include <QTimer>
 | 
					
						
							|  |  |  | #include "common/param_package.h"
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | #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"
 | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  | #include "input_common/gcadapter/gc_poller.h"
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | #include "input_common/main.h"
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:35:42 -05:00
										 |  |  | #include "input_common/udp/udp.h"
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | #include "ui_configure_input_player.h"
 | 
					
						
							|  |  |  | #include "yuzu/configuration/config.h"
 | 
					
						
							|  |  |  | #include "yuzu/configuration/configure_input_player.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | constexpr std::size_t HANDHELD_INDEX = 8; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> | 
					
						
							| 
									
										
										
										
											2020-06-21 15:31:57 -04:00
										 |  |  |     ConfigureInputPlayer::analog_sub_buttons{{ | 
					
						
							|  |  |  |         "up", | 
					
						
							|  |  |  |         "down", | 
					
						
							|  |  |  |         "left", | 
					
						
							|  |  |  |         "right", | 
					
						
							|  |  |  |     }}; | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, | 
					
						
							|  |  |  |                       bool connected) { | 
					
						
							|  |  |  |     Core::System& system{Core::System::GetInstance()}; | 
					
						
							|  |  |  |     if (!system.IsPoweredOn()) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Service::SM::ServiceManager& sm = system.ServiceManager(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto& npad = | 
					
						
							|  |  |  |         sm.GetService<Service::HID::Hid>("hid") | 
					
						
							|  |  |  |             ->GetAppletResource() | 
					
						
							|  |  |  |             ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     npad.UpdateControllerAt(npad.MapSettingsTypeToNPad(controller_type), npad_index, connected); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// Maps the controller type combobox index to Controller Type enum
 | 
					
						
							|  |  |  | constexpr Settings::ControllerType GetControllerTypeFromIndex(int index) { | 
					
						
							|  |  |  |     switch (index) { | 
					
						
							|  |  |  |     case 0: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return Settings::ControllerType::ProController; | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |         return Settings::ControllerType::DualJoyconDetached; | 
					
						
							|  |  |  |     case 2: | 
					
						
							|  |  |  |         return Settings::ControllerType::LeftJoycon; | 
					
						
							|  |  |  |     case 3: | 
					
						
							|  |  |  |         return Settings::ControllerType::RightJoycon; | 
					
						
							|  |  |  |     case 4: | 
					
						
							|  |  |  |         return Settings::ControllerType::Handheld; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// Maps the Controller Type enum to controller type combobox index
 | 
					
						
							|  |  |  | constexpr int GetIndexFromControllerType(Settings::ControllerType type) { | 
					
						
							|  |  |  |     switch (type) { | 
					
						
							|  |  |  |     case Settings::ControllerType::ProController: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     case Settings::ControllerType::DualJoyconDetached: | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     case Settings::ControllerType::LeftJoycon: | 
					
						
							|  |  |  |         return 2; | 
					
						
							|  |  |  |     case Settings::ControllerType::RightJoycon: | 
					
						
							|  |  |  |         return 3; | 
					
						
							|  |  |  |     case Settings::ControllerType::Handheld: | 
					
						
							|  |  |  |         return 4; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | QString GetKeyName(int key_code) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     switch (key_code) { | 
					
						
							| 
									
										
										
										
											2020-08-23 08:04:26 -04:00
										 |  |  |     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"); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     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: | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     default: | 
					
						
							|  |  |  |         return QKeySequence(key_code).toString(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 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
 | 
					
						
							|  |  |  |     if (input_param.Has("axis_x") && input_param.Has("axis_y")) { | 
					
						
							|  |  |  |         analog_param = input_param; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // Check if the current configuration has either no engine or an axis binding.
 | 
					
						
							|  |  |  |     // Clears out the old binding and adds one with analog_from_button.
 | 
					
						
							|  |  |  |     if (!analog_param.Has("engine") || analog_param.Has("axis_x") || analog_param.Has("axis_y")) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         analog_param = { | 
					
						
							|  |  |  |             {"engine", "analog_from_button"}, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     analog_param.Set(button_name, input_param.Serialize()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | QString ButtonToText(const Common::ParamPackage& param) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     if (!param.Has("engine")) { | 
					
						
							|  |  |  |         return QObject::tr("[not set]"); | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (param.Get("engine", "") == "keyboard") { | 
					
						
							| 
									
										
										
										
											2018-11-03 12:55:39 -04:00
										 |  |  |         return GetKeyName(param.Get("code", 0)); | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-21 12:36:28 -04:00
										 |  |  |     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", "")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 22:02:50 -04:00
										 |  |  |             return QObject::tr("GC Axis %1%2").arg(axis_str, direction_str); | 
					
						
							| 
									
										
										
										
											2020-06-21 12:36:28 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (param.Has("button")) { | 
					
						
							|  |  |  |             const QString button_str = QString::number(int(std::log2(param.Get("button", 0)))); | 
					
						
							| 
									
										
										
										
											2020-06-22 22:02:50 -04:00
										 |  |  |             return QObject::tr("GC Button %1").arg(button_str); | 
					
						
							| 
									
										
										
										
											2020-06-21 12:36:28 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |         return GetKeyName(param.Get("code", 0)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:35:42 -05:00
										 |  |  |     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)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |     if (param.Get("engine", "") == "sdl") { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         if (param.Has("hat")) { | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |             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); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         if (param.Has("axis")) { | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |             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); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         if (param.Has("button")) { | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |             const QString button_str = QString::fromStdString(param.Get("button", "")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return QObject::tr("Button %1").arg(button_str); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return QObject::tr("[unknown]"); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     if (!param.Has("engine")) { | 
					
						
							|  |  |  |         return QObject::tr("[not set]"); | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (param.Get("engine", "") == "analog_from_button") { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         return ButtonToText(Common::ParamPackage{param.Get(dir, "")}); | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-02 15:54:44 -04:00
										 |  |  |     if (param.Get("engine", "") == "sdl") { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         if (dir == "modifier") { | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |             return QObject::tr("[unused]"); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (dir == "left" || dir == "right") { | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |             const QString axis_x_str = QString::fromStdString(param.Get("axis_x", "")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return QObject::tr("Axis %1").arg(axis_x_str); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (dir == "up" || dir == "down") { | 
					
						
							|  |  |  |             const QString axis_y_str = QString::fromStdString(param.Get("axis_y", "")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return QObject::tr("Axis %1").arg(axis_y_str); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-02 15:54:44 -04:00
										 |  |  |     if (param.Get("engine", "") == "gcpad") { | 
					
						
							|  |  |  |         if (dir == "modifier") { | 
					
						
							|  |  |  |             return QObject::tr("[unused]"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (dir == "left" || dir == "right") { | 
					
						
							|  |  |  |             const QString axis_x_str = QString::fromStdString(param.Get("axis_x", "")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return QObject::tr("GC Axis %1").arg(axis_x_str); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (dir == "up" || dir == "down") { | 
					
						
							|  |  |  |             const QString axis_y_str = QString::fromStdString(param.Get("axis_y", "")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return QObject::tr("GC Axis %1").arg(axis_y_str); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-05-19 11:38:28 -04:00
										 |  |  |     return QObject::tr("[unknown]"); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | } // namespace
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |                                            QWidget* bottom_row, | 
					
						
							|  |  |  |                                            InputCommon::InputSubsystem* input_subsystem_, | 
					
						
							|  |  |  |                                            bool debug) | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |       debug(debug), input_subsystem{input_subsystem_}, timeout_timer(std::make_unique<QTimer>()), | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |       poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     ui->setupUi(this); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     setFocusPolicy(Qt::ClickFocus); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     button_map = { | 
					
						
							| 
									
										
										
										
											2020-08-23 10:56:19 -04:00
										 |  |  |         ui->buttonA,        ui->buttonB,      ui->buttonX,         ui->buttonY, | 
					
						
							|  |  |  |         ui->buttonLStick,   ui->buttonRStick, ui->buttonL,         ui->buttonR, | 
					
						
							|  |  |  |         ui->buttonZL,       ui->buttonZR,     ui->buttonPlus,      ui->buttonMinus, | 
					
						
							|  |  |  |         ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, | 
					
						
							|  |  |  |         ui->buttonSL,       ui->buttonSR,     ui->buttonHome,      ui->buttonScreenshot, | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     analog_map_buttons = {{ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ui->buttonLStickUp, | 
					
						
							|  |  |  |             ui->buttonLStickDown, | 
					
						
							|  |  |  |             ui->buttonLStickLeft, | 
					
						
							|  |  |  |             ui->buttonLStickRight, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             ui->buttonRStickUp, | 
					
						
							|  |  |  |             ui->buttonRStickDown, | 
					
						
							|  |  |  |             ui->buttonRStickLeft, | 
					
						
							|  |  |  |             ui->buttonRStickRight, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     }}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:48:03 -05:00
										 |  |  |     motion_map = { | 
					
						
							|  |  |  |         ui->buttonMotionLeft, | 
					
						
							|  |  |  |         ui->buttonMotionRight, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     analog_map_deadzone_label = {ui->labelLStickDeadzone, ui->labelRStickDeadzone}; | 
					
						
							|  |  |  |     analog_map_deadzone_slider = {ui->sliderLStickDeadzone, ui->sliderRStickDeadzone}; | 
					
						
							|  |  |  |     analog_map_modifier_groupbox = {ui->buttonLStickModGroup, ui->buttonRStickModGroup}; | 
					
						
							| 
									
										
										
										
											2020-10-20 14:23:25 -04:00
										 |  |  |     analog_map_modifier_button = {ui->buttonLStickMod, ui->buttonRStickMod}; | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     analog_map_modifier_label = {ui->labelLStickModifierRange, ui->labelRStickModifierRange}; | 
					
						
							|  |  |  |     analog_map_modifier_slider = {ui->sliderLStickModifierRange, ui->sliderRStickModifierRange}; | 
					
						
							|  |  |  |     analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup}; | 
					
						
							|  |  |  |     analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto ConfigureButtonClick = [&](QPushButton* button, Common::ParamPackage* param, | 
					
						
							| 
									
										
										
										
											2020-09-18 03:44:59 -04:00
										 |  |  |                                           int default_val, InputCommon::Polling::DeviceType type) { | 
					
						
							| 
									
										
										
										
											2020-08-03 11:28:18 -04:00
										 |  |  |         connect(button, &QPushButton::clicked, [=, this] { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |             HandleClick( | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |                 button, | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |                 [=, this](Common::ParamPackage params) { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |                     // 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.
 | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |                     // TODO: reinterpret the signal range for analog triggers to map the
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |                     // values correctly. This is required for the correct emulation of
 | 
					
						
							|  |  |  |                     // the analog triggers of the GameCube controller.
 | 
					
						
							|  |  |  |                     if (button == ui->buttonZL || button == ui->buttonZR) { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |                         params.Set("direction", "+"); | 
					
						
							|  |  |  |                         params.Set("threshold", "0.5"); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |                     *param = std::move(params); | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2020-09-18 03:44:59 -04:00
										 |  |  |                 type); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { | 
					
						
							|  |  |  |         auto* const button = button_map[button_id]; | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         if (button == nullptr) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         ConfigureButtonClick(button_map[button_id], &buttons_param[button_id], | 
					
						
							| 
									
										
										
										
											2020-09-18 03:44:59 -04:00
										 |  |  |                              Config::default_buttons[button_id], | 
					
						
							|  |  |  |                              InputCommon::Polling::DeviceType::Button); | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         button->setContextMenuPolicy(Qt::CustomContextMenu); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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.exec(button_map[button_id]->mapToGlobal(menu_location)); | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:48:03 -05:00
										 |  |  |     for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { | 
					
						
							|  |  |  |         auto* const button = motion_map[motion_id]; | 
					
						
							|  |  |  |         if (button == nullptr) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  |         ConfigureButtonClick(motion_map[motion_id], &motions_param[motion_id], | 
					
						
							| 
									
										
										
										
											2020-09-18 03:44:59 -04:00
										 |  |  |                              Config::default_motions[motion_id], | 
					
						
							|  |  |  |                              InputCommon::Polling::DeviceType::Motion); | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:48:03 -05:00
										 |  |  |         button->setContextMenuPolicy(Qt::CustomContextMenu); | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:48:03 -05:00
										 |  |  |         connect(button, &QPushButton::customContextMenuRequested, | 
					
						
							|  |  |  |                 [=, this](const QPoint& menu_location) { | 
					
						
							|  |  |  |                     QMenu context_menu; | 
					
						
							|  |  |  |                     context_menu.addAction(tr("Clear"), [&] { | 
					
						
							|  |  |  |                         motions_param[motion_id].Clear(); | 
					
						
							|  |  |  |                         motion_map[motion_id]->setText(tr("[not set]")); | 
					
						
							|  |  |  |                     }); | 
					
						
							|  |  |  |                     context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location)); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     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) { | 
					
						
							| 
									
										
										
										
											2019-05-19 12:08:48 -04:00
										 |  |  |             auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-19 12:08:48 -04:00
										 |  |  |             if (analog_button == nullptr) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2019-05-19 12:08:48 -04:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-03 11:28:18 -04:00
										 |  |  |             connect(analog_button, &QPushButton::clicked, [=, this] { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |                 HandleClick( | 
					
						
							|  |  |  |                     analog_map_buttons[analog_id][sub_button_id], | 
					
						
							|  |  |  |                     [=, this](const Common::ParamPackage& params) { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |                         SetAnalogParam(params, analogs_param[analog_id], | 
					
						
							|  |  |  |                                        analog_sub_buttons[sub_button_id]); | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |                     }, | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |                     InputCommon::Polling::DeviceType::AnalogPreferred); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |             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.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal( | 
					
						
							|  |  |  |                             menu_location)); | 
					
						
							|  |  |  |                     }); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  |         // Handle clicks for the modifier buttons as well.
 | 
					
						
							| 
									
										
										
										
											2020-10-20 14:23:25 -04:00
										 |  |  |         connect(analog_map_modifier_button[analog_id], &QPushButton::clicked, [=, this] { | 
					
						
							|  |  |  |             HandleClick( | 
					
						
							|  |  |  |                 analog_map_modifier_button[analog_id], | 
					
						
							|  |  |  |                 [=, this](const Common::ParamPackage& params) { | 
					
						
							|  |  |  |                     analogs_param[analog_id].Set("modifier", params.Serialize()); | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 InputCommon::Polling::DeviceType::Button); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 14:23:25 -04:00
										 |  |  |         analog_map_modifier_button[analog_id]->setContextMenuPolicy(Qt::CustomContextMenu); | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 14:23:25 -04:00
										 |  |  |         connect(analog_map_modifier_button[analog_id], &QPushButton::customContextMenuRequested, | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  |                 [=, this](const QPoint& menu_location) { | 
					
						
							|  |  |  |                     QMenu context_menu; | 
					
						
							|  |  |  |                     context_menu.addAction(tr("Clear"), [&] { | 
					
						
							| 
									
										
										
										
											2020-10-20 14:23:25 -04:00
										 |  |  |                         analogs_param[analog_id].Set("modifier", ""); | 
					
						
							|  |  |  |                         analog_map_modifier_button[analog_id]->setText(tr("[not set]")); | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  |                     }); | 
					
						
							| 
									
										
										
										
											2020-10-20 14:23:25 -04:00
										 |  |  |                     context_menu.exec( | 
					
						
							|  |  |  |                         analog_map_modifier_button[analog_id]->mapToGlobal(menu_location)); | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  |                 }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         connect(analog_map_range_spinbox[analog_id], qOverload<int>(&QSpinBox::valueChanged), | 
					
						
							| 
									
										
										
										
											2020-08-03 11:28:18 -04:00
										 |  |  |                 [=, this] { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |                     const auto spinbox_value = analog_map_range_spinbox[analog_id]->value(); | 
					
						
							|  |  |  |                     analogs_param[analog_id].Set("range", spinbox_value / 100.0f); | 
					
						
							| 
									
										
										
										
											2020-08-03 11:28:18 -04:00
										 |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] { | 
					
						
							|  |  |  |             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); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] { | 
					
						
							|  |  |  |             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); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     // Player Connected checkbox
 | 
					
						
							|  |  |  |     connect(ui->groupConnectedController, &QGroupBox::toggled, | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |             [this](bool checked) { emit Connected(checked); }); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Set up controller type. Only Player 1 can choose Handheld.
 | 
					
						
							|  |  |  |     ui->comboControllerType->clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QStringList controller_types = { | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |         tr("Pro Controller"), | 
					
						
							|  |  |  |         tr("Dual Joycons"), | 
					
						
							|  |  |  |         tr("Left Joycon"), | 
					
						
							|  |  |  |         tr("Right Joycon"), | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (player_index == 0) { | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |         controller_types.append(tr("Handheld")); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |                 [this](int index) { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |                     emit HandheldStateChanged(GetControllerTypeFromIndex(index) == | 
					
						
							|  |  |  |                                               Settings::ControllerType::Handheld); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // The Debug Controller can only choose the Pro Controller.
 | 
					
						
							|  |  |  |     if (debug) { | 
					
						
							|  |  |  |         ui->buttonScreenshot->setEnabled(false); | 
					
						
							|  |  |  |         ui->buttonHome->setEnabled(false); | 
					
						
							|  |  |  |         ui->groupConnectedController->setCheckable(false); | 
					
						
							|  |  |  |         QStringList debug_controller_types = { | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |             tr("Pro Controller"), | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         }; | 
					
						
							|  |  |  |         ui->comboControllerType->addItems(debug_controller_types); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ui->comboControllerType->addItems(controller_types); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     UpdateControllerIcon(); | 
					
						
							|  |  |  |     UpdateControllerAvailableButtons(); | 
					
						
							| 
									
										
										
										
											2020-09-02 12:33:37 -04:00
										 |  |  |     UpdateMotionButtons(); | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |     connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         UpdateControllerIcon(); | 
					
						
							|  |  |  |         UpdateControllerAvailableButtons(); | 
					
						
							| 
									
										
										
										
											2020-09-02 12:33:37 -04:00
										 |  |  |         UpdateMotionButtons(); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |     connect(ui->comboDevices, qOverload<int>(&QComboBox::currentIndexChanged), this, | 
					
						
							|  |  |  |             &ConfigureInputPlayer::UpdateMappingWithDefaults); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); | 
					
						
							|  |  |  |     UpdateInputDevices(); | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |     connect(ui->buttonRefreshDevices, &QPushButton::clicked, | 
					
						
							|  |  |  |             [this] { emit RefreshInputDevices(); }); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     timeout_timer->setSingleShot(true); | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  |     connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-21 15:31:57 -04:00
										 |  |  |     connect(poll_timer.get(), &QTimer::timeout, [this] { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         Common::ParamPackage params; | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |         if (input_subsystem->GetGCButtons()->IsPolling()) { | 
					
						
							|  |  |  |             params = input_subsystem->GetGCButtons()->GetNextInput(); | 
					
						
							| 
									
										
										
										
											2020-06-21 12:36:28 -04:00
										 |  |  |             if (params.Has("engine")) { | 
					
						
							|  |  |  |                 SetPollingResult(params, false); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |         if (input_subsystem->GetGCAnalogs()->IsPolling()) { | 
					
						
							|  |  |  |             params = input_subsystem->GetGCAnalogs()->GetNextInput(); | 
					
						
							| 
									
										
										
										
											2020-06-21 12:36:28 -04:00
										 |  |  |             if (params.Has("engine")) { | 
					
						
							|  |  |  |                 SetPollingResult(params, false); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-04 21:35:42 -05:00
										 |  |  |         if (input_subsystem->GetUDPMotions()->IsPolling()) { | 
					
						
							|  |  |  |             params = input_subsystem->GetUDPMotions()->GetNextInput(); | 
					
						
							|  |  |  |             if (params.Has("engine")) { | 
					
						
							|  |  |  |                 SetPollingResult(params, false); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         for (auto& poller : device_pollers) { | 
					
						
							|  |  |  |             params = poller->GetNextInput(); | 
					
						
							|  |  |  |             if (params.Has("engine")) { | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  |                 SetPollingResult(params, false); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  |     LoadConfiguration(); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // TODO(wwylele): enable this when we actually emulate it
 | 
					
						
							|  |  |  |     ui->buttonHome->setEnabled(false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-04 10:18:59 -05:00
										 |  |  | ConfigureInputPlayer::~ConfigureInputPlayer() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  | void ConfigureInputPlayer::ApplyConfiguration() { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     auto& player = Settings::values.players[player_index]; | 
					
						
							|  |  |  |     auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons; | 
					
						
							|  |  |  |     auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs; | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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(); }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     if (debug) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:48:03 -05:00
										 |  |  |     auto& motions = player.motions; | 
					
						
							|  |  |  |     std::transform(motions_param.begin(), motions_param.end(), motions.begin(), | 
					
						
							|  |  |  |                    [](const Common::ParamPackage& param) { return param.Serialize(); }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     player.controller_type = | 
					
						
							|  |  |  |         static_cast<Settings::ControllerType>(ui->comboControllerType->currentIndex()); | 
					
						
							|  |  |  |     player.connected = ui->groupConnectedController->isChecked(); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     // Player 2-8
 | 
					
						
							|  |  |  |     if (player_index != 0) { | 
					
						
							|  |  |  |         UpdateController(player.controller_type, player_index, player.connected); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Player 1 and Handheld
 | 
					
						
							|  |  |  |     auto& handheld = Settings::values.players[HANDHELD_INDEX]; | 
					
						
							|  |  |  |     // If Handheld is selected, copy all the settings from Player 1 to Handheld.
 | 
					
						
							|  |  |  |     if (player.controller_type == Settings::ControllerType::Handheld) { | 
					
						
							|  |  |  |         handheld = player; | 
					
						
							|  |  |  |         handheld.connected = ui->groupConnectedController->isChecked(); | 
					
						
							|  |  |  |         player.connected = false; // Disconnect Player 1
 | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         player.connected = ui->groupConnectedController->isChecked(); | 
					
						
							|  |  |  |         handheld.connected = false; // Disconnect Handheld
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     UpdateController(player.controller_type, player_index, player.connected); | 
					
						
							|  |  |  |     UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-05 18:39:46 -04:00
										 |  |  | void ConfigureInputPlayer::changeEvent(QEvent* event) { | 
					
						
							|  |  |  |     if (event->type() == QEvent::LanguageChange) { | 
					
						
							|  |  |  |         RetranslateUI(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     QWidget::changeEvent(event); | 
					
						
							| 
									
										
										
										
											2019-06-05 18:39:46 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ConfigureInputPlayer::RetranslateUI() { | 
					
						
							|  |  |  |     ui->retranslateUi(this); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     UpdateUI(); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  | void ConfigureInputPlayer::LoadConfiguration() { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     auto& player = Settings::values.players[player_index]; | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     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 { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         std::transform(player.buttons.begin(), player.buttons.end(), buttons_param.begin(), | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |                        [](const std::string& str) { return Common::ParamPackage(str); }); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         std::transform(player.analogs.begin(), player.analogs.end(), analogs_param.begin(), | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |                        [](const std::string& str) { return Common::ParamPackage(str); }); | 
					
						
							| 
									
										
										
										
											2020-09-04 21:48:03 -05:00
										 |  |  |         std::transform(player.motions.begin(), player.motions.end(), motions_param.begin(), | 
					
						
							|  |  |  |                        [](const std::string& str) { return Common::ParamPackage(str); }); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     UpdateUI(); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     if (debug) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type)); | 
					
						
							|  |  |  |     ui->groupConnectedController->setChecked( | 
					
						
							|  |  |  |         player.connected || | 
					
						
							|  |  |  |         (player_index == 0 && Settings::values.players[HANDHELD_INDEX].connected)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | void ConfigureInputPlayer::UpdateInputDevices() { | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |     input_devices = input_subsystem->GetInputDevices(); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     ui->comboDevices->clear(); | 
					
						
							|  |  |  |     for (auto device : input_devices) { | 
					
						
							|  |  |  |         ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  | void ConfigureInputPlayer::RestoreDefaults() { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     // Reset Buttons
 | 
					
						
							|  |  |  |     for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         buttons_param[button_id] = Common::ParamPackage{ | 
					
						
							|  |  |  |             InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-23 10:56:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  |     // Reset Analogs and Modifier Buttons
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     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) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |             Common::ParamPackage params{InputCommon::GenerateKeyboardParam( | 
					
						
							|  |  |  |                 Config::default_analogs[analog_id][sub_button_id])}; | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |             SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 14:23:25 -04:00
										 |  |  |         analogs_param[analog_id].Set( | 
					
						
							|  |  |  |             "modifier", InputCommon::GenerateKeyboardParam(Config::default_stick_mod[analog_id])); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-04 21:48:03 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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])}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     UpdateUI(); | 
					
						
							|  |  |  |     UpdateInputDevices(); | 
					
						
							|  |  |  |     ui->comboControllerType->setCurrentIndex(0); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ConfigureInputPlayer::ClearAll() { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { | 
					
						
							| 
									
										
										
										
											2019-05-19 12:08:48 -04:00
										 |  |  |         const auto* const button = button_map[button_id]; | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  |         if (button == nullptr) { | 
					
						
							| 
									
										
										
										
											2019-05-19 12:08:48 -04:00
										 |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         buttons_param[button_id].Clear(); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-05-19 12:08:48 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     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) { | 
					
						
							| 
									
										
										
										
											2019-05-19 12:08:48 -04:00
										 |  |  |             const auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  |             if (analog_button == nullptr) { | 
					
						
							| 
									
										
										
										
											2019-05-19 12:08:48 -04:00
										 |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-03 08:54:57 +01:00
										 |  |  |             analogs_param[analog_id].Clear(); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:48:03 -05:00
										 |  |  |     for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  |         const auto* const motion_button = motion_map[motion_id]; | 
					
						
							|  |  |  |         if (motion_button == nullptr) { | 
					
						
							| 
									
										
										
										
											2020-09-04 21:48:03 -05:00
										 |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         motions_param[motion_id].Clear(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     UpdateUI(); | 
					
						
							|  |  |  |     UpdateInputDevices(); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | void ConfigureInputPlayer::UpdateUI() { | 
					
						
							|  |  |  |     for (int button = 0; button < Settings::NativeButton::NumButtons; ++button) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         button_map[button]->setText(ButtonToText(buttons_param[button])); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:48:03 -05:00
										 |  |  |     for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { | 
					
						
							|  |  |  |         motion_map[motion_id]->setText(ButtonToText(motions_param[motion_id])); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     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) { | 
					
						
							| 
									
										
										
										
											2019-05-19 12:08:48 -04:00
										 |  |  |             auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (analog_button == nullptr) { | 
					
						
							|  |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-05-19 12:08:48 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |             analog_button->setText( | 
					
						
							|  |  |  |                 AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-03 08:54:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 14:23:25 -04:00
										 |  |  |         analog_map_modifier_button[analog_id]->setText( | 
					
						
							|  |  |  |             ButtonToText(Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")})); | 
					
						
							| 
									
										
										
										
											2020-09-01 10:02:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         const auto deadzone_label = analog_map_deadzone_label[analog_id]; | 
					
						
							|  |  |  |         const auto deadzone_slider = analog_map_deadzone_slider[analog_id]; | 
					
						
							|  |  |  |         const auto modifier_groupbox = analog_map_modifier_groupbox[analog_id]; | 
					
						
							|  |  |  |         const auto modifier_label = analog_map_modifier_label[analog_id]; | 
					
						
							|  |  |  |         const auto modifier_slider = analog_map_modifier_slider[analog_id]; | 
					
						
							|  |  |  |         const auto range_groupbox = analog_map_range_groupbox[analog_id]; | 
					
						
							|  |  |  |         const auto range_spinbox = analog_map_range_spinbox[analog_id]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         int slider_value; | 
					
						
							| 
									
										
										
										
											2020-01-03 10:30:51 +01:00
										 |  |  |         auto& param = analogs_param[analog_id]; | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         const bool is_controller = | 
					
						
							|  |  |  |             param.Get("engine", "") == "sdl" || param.Get("engine", "") == "gcpad"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_controller) { | 
					
						
							|  |  |  |             if (!param.Has("deadzone")) { | 
					
						
							|  |  |  |                 param.Set("deadzone", 0.1f); | 
					
						
							| 
									
										
										
										
											2020-01-03 08:54:57 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |             slider_value = static_cast<int>(param.Get("deadzone", 0.1f) * 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); | 
					
						
							| 
									
										
										
										
											2020-01-03 08:54:57 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         deadzone_label->setVisible(is_controller); | 
					
						
							|  |  |  |         deadzone_slider->setVisible(is_controller); | 
					
						
							|  |  |  |         modifier_groupbox->setVisible(!is_controller); | 
					
						
							|  |  |  |         modifier_label->setVisible(!is_controller); | 
					
						
							|  |  |  |         modifier_slider->setVisible(!is_controller); | 
					
						
							|  |  |  |         range_groupbox->setVisible(is_controller); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | void ConfigureInputPlayer::UpdateMappingWithDefaults() { | 
					
						
							|  |  |  |     if (ui->comboDevices->currentIndex() < 2) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const auto& device = input_devices[ui->comboDevices->currentIndex()]; | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |     auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); | 
					
						
							|  |  |  |     auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); | 
					
						
							| 
									
										
										
										
											2020-08-29 16:43:06 -04:00
										 |  |  |     for (std::size_t i = 0; i < buttons_param.size(); ++i) { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-29 16:43:06 -04:00
										 |  |  |     for (std::size_t i = 0; i < analogs_param.size(); ++i) { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     UpdateUI(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  | void ConfigureInputPlayer::HandleClick( | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, | 
					
						
							|  |  |  |     InputCommon::Polling::DeviceType type) { | 
					
						
							| 
									
										
										
										
											2020-09-05 09:42:01 -04:00
										 |  |  |     if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) { | 
					
						
							|  |  |  |         button->setText(tr("Shake!")); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         button->setText(tr("[waiting]")); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     button->setFocus(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-23 08:04:26 -04:00
										 |  |  |     // 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; | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     input_setter = new_input_setter; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |     device_pollers = input_subsystem->GetPollers(type); | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (auto& poller : device_pollers) { | 
					
						
							|  |  |  |         poller->Start(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-23 08:04:26 -04:00
										 |  |  |     QWidget::grabMouse(); | 
					
						
							|  |  |  |     QWidget::grabKeyboard(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-21 15:31:57 -04:00
										 |  |  |     if (type == InputCommon::Polling::DeviceType::Button) { | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |         input_subsystem->GetGCButtons()->BeginConfiguration(); | 
					
						
							| 
									
										
										
										
											2020-06-21 15:31:57 -04:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |         input_subsystem->GetGCAnalogs()->BeginConfiguration(); | 
					
						
							| 
									
										
										
										
											2020-06-21 15:31:57 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:35:42 -05:00
										 |  |  |     if (type == InputCommon::Polling::DeviceType::Motion) { | 
					
						
							|  |  |  |         input_subsystem->GetUDPMotions()->BeginConfiguration(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     timeout_timer->start(2500); // Cancel after 2.5 seconds
 | 
					
						
							|  |  |  |     poll_timer->start(50);      // Check for new inputs every 50ms
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  | void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     timeout_timer->stop(); | 
					
						
							|  |  |  |     poll_timer->stop(); | 
					
						
							|  |  |  |     for (auto& poller : device_pollers) { | 
					
						
							|  |  |  |         poller->Stop(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-23 08:04:26 -04:00
										 |  |  |     QWidget::releaseMouse(); | 
					
						
							|  |  |  |     QWidget::releaseKeyboard(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-27 15:16:47 -04:00
										 |  |  |     input_subsystem->GetGCButtons()->EndConfiguration(); | 
					
						
							|  |  |  |     input_subsystem->GetGCAnalogs()->EndConfiguration(); | 
					
						
							| 
									
										
										
										
											2020-06-21 12:36:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 21:35:42 -05:00
										 |  |  |     input_subsystem->GetUDPMotions()->EndConfiguration(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |     if (!abort) { | 
					
						
							|  |  |  |         (*input_setter)(params); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     UpdateUI(); | 
					
						
							| 
									
										
										
										
											2018-11-03 12:55:39 -04:00
										 |  |  |     input_setter = std::nullopt; | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-23 08:04:26 -04:00
										 |  |  | void ConfigureInputPlayer::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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  |     if (!input_setter || !event) { | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (event->key() != Qt::Key_Escape) { | 
					
						
							| 
									
										
										
										
											2020-08-23 08:04:26 -04:00
										 |  |  |         if (want_keyboard_mouse) { | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  |             SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, | 
					
						
							| 
									
										
										
										
											2018-11-01 22:11:44 -04:00
										 |  |  |                              false); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling
 | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-23 08:04:26 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 00:39:23 -04:00
										 |  |  |     SetPollingResult({}, true); | 
					
						
							| 
									
										
										
										
											2020-01-03 09:11:34 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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)
 | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |     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{}; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }(); | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const QString theme = [this] { | 
					
						
							|  |  |  |         if (QIcon::themeName().contains(QStringLiteral("dark"))) { | 
					
						
							|  |  |  |             return QStringLiteral("_dark"); | 
					
						
							|  |  |  |         } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | 
					
						
							|  |  |  |             return QStringLiteral("_midnight"); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             return QString{}; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui->controllerFrame->setStyleSheet(stylesheet.arg(theme)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | 
					
						
							|  |  |  |     auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); | 
					
						
							|  |  |  |     if (debug) { | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |         layout = Settings::ControllerType::ProController; | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // List of all the widgets that will be hidden by any of the following layouts that need
 | 
					
						
							|  |  |  |     // "unhidden" after the controller type changes
 | 
					
						
							| 
									
										
										
										
											2020-08-15 15:26:29 -04:00
										 |  |  |     const std::array<QWidget*, 9> layout_show = { | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  |         ui->buttonShoulderButtonsSLSR, | 
					
						
							|  |  |  |         ui->horizontalSpacerShoulderButtonsWidget, | 
					
						
							|  |  |  |         ui->horizontalSpacerShoulderButtonsWidget2, | 
					
						
							|  |  |  |         ui->buttonShoulderButtonsLeft, | 
					
						
							|  |  |  |         ui->buttonMiscButtonsMinusScreenshot, | 
					
						
							|  |  |  |         ui->bottomLeft, | 
					
						
							|  |  |  |         ui->buttonShoulderButtonsRight, | 
					
						
							|  |  |  |         ui->buttonMiscButtonsPlusHome, | 
					
						
							|  |  |  |         ui->bottomRight, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto* widget : layout_show) { | 
					
						
							|  |  |  |         widget->show(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     std::vector<QWidget*> layout_hidden; | 
					
						
							|  |  |  |     switch (layout) { | 
					
						
							|  |  |  |     case Settings::ControllerType::ProController: | 
					
						
							|  |  |  |     case Settings::ControllerType::DualJoyconDetached: | 
					
						
							|  |  |  |     case Settings::ControllerType::Handheld: | 
					
						
							|  |  |  |         layout_hidden = { | 
					
						
							|  |  |  |             ui->buttonShoulderButtonsSLSR, | 
					
						
							|  |  |  |             ui->horizontalSpacerShoulderButtonsWidget2, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::ControllerType::LeftJoycon: | 
					
						
							|  |  |  |         layout_hidden = { | 
					
						
							|  |  |  |             ui->horizontalSpacerShoulderButtonsWidget2, | 
					
						
							|  |  |  |             ui->buttonShoulderButtonsRight, | 
					
						
							|  |  |  |             ui->buttonMiscButtonsPlusHome, | 
					
						
							|  |  |  |             ui->bottomRight, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::ControllerType::RightJoycon: | 
					
						
							|  |  |  |         layout_hidden = { | 
					
						
							|  |  |  |             ui->horizontalSpacerShoulderButtonsWidget, | 
					
						
							|  |  |  |             ui->buttonShoulderButtonsLeft, | 
					
						
							|  |  |  |             ui->buttonMiscButtonsMinusScreenshot, | 
					
						
							|  |  |  |             ui->bottomLeft, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto* widget : layout_hidden) { | 
					
						
							|  |  |  |         widget->hide(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 12:33:37 -04:00
										 |  |  | void ConfigureInputPlayer::UpdateMotionButtons() { | 
					
						
							|  |  |  |     if (debug) { | 
					
						
							|  |  |  |         // Motion isn't used with the debug controller, hide both groupboxes.
 | 
					
						
							|  |  |  |         ui->buttonMotionLeftGroup->hide(); | 
					
						
							|  |  |  |         ui->buttonMotionRightGroup->hide(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 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: | 
					
						
							|  |  |  |         // Show "Motion 1" and hide "Motion 2".
 | 
					
						
							|  |  |  |         ui->buttonMotionLeftGroup->show(); | 
					
						
							|  |  |  |         ui->buttonMotionRightGroup->hide(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::ControllerType::RightJoycon: | 
					
						
							|  |  |  |         // Show "Motion 2" and hide "Motion 1".
 | 
					
						
							|  |  |  |         ui->buttonMotionLeftGroup->hide(); | 
					
						
							|  |  |  |         ui->buttonMotionRightGroup->show(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Settings::ControllerType::DualJoyconDetached: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         // Show both "Motion 1/2".
 | 
					
						
							|  |  |  |         ui->buttonMotionLeftGroup->show(); | 
					
						
							|  |  |  |         ui->buttonMotionRightGroup->show(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 10:39:53 -04:00
										 |  |  | void ConfigureInputPlayer::showEvent(QShowEvent* event) { | 
					
						
							|  |  |  |     if (bottom_row == nullptr) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QWidget::showEvent(event); | 
					
						
							|  |  |  |     ui->main->addWidget(bottom_row); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ConfigureInputPlayer::ConnectPlayer(bool connected) { | 
					
						
							|  |  |  |     ui->groupConnectedController->setChecked(connected); | 
					
						
							|  |  |  | } |