Make settings controller image change with controller input
							
								
								
									
										21
									
								
								dist/icons/controller/controller.qrc
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,26 +1,5 @@ | ||||
| <RCC> | ||||
|   <qresource prefix="controller"> | ||||
|     <file alias="dual_joycon">dual_joycon.png</file> | ||||
|     <file alias="dual_joycon_dark">dual_joycon_dark.png</file> | ||||
|     <file alias="dual_joycon_midnight">dual_joycon_midnight.png</file> | ||||
|     <file alias="handheld">handheld.png</file> | ||||
|     <file alias="handheld_dark">handheld_dark.png</file> | ||||
|     <file alias="handheld_midnight">handheld_midnight.png</file> | ||||
|     <file alias="pro_controller">pro_controller.png</file> | ||||
|     <file alias="pro_controller_dark">pro_controller_dark.png</file> | ||||
|     <file alias="pro_controller_midnight">pro_controller_midnight.png</file> | ||||
|     <file alias="single_joycon_left">single_joycon_left.png</file> | ||||
|     <file alias="single_joycon_left_dark">single_joycon_left_dark.png</file> | ||||
|     <file alias="single_joycon_left_midnight">single_joycon_left_midnight.png</file> | ||||
|     <file alias="single_joycon_right">single_joycon_right.png</file> | ||||
|     <file alias="single_joycon_right_dark">single_joycon_right_dark.png</file> | ||||
|     <file alias="single_joycon_right_midnight">single_joycon_right_midnight.png</file> | ||||
|     <file alias="single_joycon_left_vertical">single_joycon_left_vertical.png</file> | ||||
|     <file alias="single_joycon_left_vertical_dark">single_joycon_left_vertical_dark.png</file> | ||||
|     <file alias="single_joycon_left_vertical_midnight">single_joycon_left_vertical_midnight.png</file> | ||||
|     <file alias="single_joycon_right_vertical">single_joycon_right_vertical.png</file> | ||||
|     <file alias="single_joycon_right_vertical_dark">single_joycon_right_vertical_dark.png</file> | ||||
|     <file alias="single_joycon_right_vertical_midnight">single_joycon_right_vertical_midnight.png</file> | ||||
|     <file alias="applet_dual_joycon">applet_dual_joycon.png</file> | ||||
|     <file alias="applet_dual_joycon_dark">applet_dual_joycon_dark.png</file>	 | ||||
|     <file alias="applet_dual_joycon_midnight">applet_dual_joycon_midnight.png</file>	 | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/dual_joycon.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 36 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/dual_joycon_dark.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 35 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/dual_joycon_midnight.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 34 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/handheld.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 14 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/handheld_dark.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 13 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/handheld_midnight.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 13 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/pro_controller.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 36 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/pro_controller_dark.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 34 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/pro_controller_midnight.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 35 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/single_joycon_left.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 25 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/single_joycon_left_dark.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 25 KiB | 
| Before Width: | Height: | Size: 24 KiB | 
| Before Width: | Height: | Size: 24 KiB | 
| Before Width: | Height: | Size: 24 KiB | 
| Before Width: | Height: | Size: 23 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/single_joycon_right.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 28 KiB | 
							
								
								
									
										
											BIN
										
									
								
								dist/icons/controller/single_joycon_right_dark.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 28 KiB | 
| Before Width: | Height: | Size: 26 KiB | 
| Before Width: | Height: | Size: 27 KiB | 
| Before Width: | Height: | Size: 27 KiB | 
| Before Width: | Height: | Size: 26 KiB | 
| @@ -21,6 +21,11 @@ enum class AnalogDirection : u8 { | ||||
|     UP, | ||||
|     DOWN, | ||||
| }; | ||||
| struct AnalogProperties { | ||||
|     float deadzone; | ||||
|     float range; | ||||
|     float threshold; | ||||
| }; | ||||
|  | ||||
| /// An abstract class template for an input device (a button, an analog input, etc.). | ||||
| template <typename StatusType> | ||||
| @@ -30,6 +35,12 @@ public: | ||||
|     virtual StatusType GetStatus() const { | ||||
|         return {}; | ||||
|     } | ||||
|     virtual StatusType GetRawStatus() const { | ||||
|         return GetStatus(); | ||||
|     } | ||||
|     virtual AnalogProperties GetAnalogProperties() const { | ||||
|         return {}; | ||||
|     } | ||||
|     virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const { | ||||
|         return {}; | ||||
|     } | ||||
|   | ||||
| @@ -185,6 +185,16 @@ public: | ||||
|         return {0.0f, 0.0f}; | ||||
|     } | ||||
|  | ||||
|     std::tuple<float, float> GetRawStatus() const override { | ||||
|         const float x = GetAxis(axis_x); | ||||
|         const float y = GetAxis(axis_y); | ||||
|         return {x, y}; | ||||
|     } | ||||
|  | ||||
|     Input::AnalogProperties GetAnalogProperties() const override { | ||||
|         return {deadzone, range, 0.5f}; | ||||
|     } | ||||
|  | ||||
|     bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { | ||||
|         const auto [x, y] = GetStatus(); | ||||
|         const float directional_deadzone = 0.5f; | ||||
|   | ||||
| @@ -377,6 +377,16 @@ public: | ||||
|         return {}; | ||||
|     } | ||||
|  | ||||
|     std::tuple<float, float> GetRawStatus() const override { | ||||
|         const float x = joystick->GetAxis(axis_x, range); | ||||
|         const float y = joystick->GetAxis(axis_y, range); | ||||
|         return {x, -y}; | ||||
|     } | ||||
|  | ||||
|     Input::AnalogProperties GetAnalogProperties() const override { | ||||
|         return {deadzone, range, 0.5f}; | ||||
|     } | ||||
|  | ||||
|     bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { | ||||
|         const auto [x, y] = GetStatus(); | ||||
|         const float directional_deadzone = 0.5f; | ||||
|   | ||||
| @@ -71,6 +71,8 @@ add_executable(yuzu | ||||
|     configuration/configure_input_player.cpp | ||||
|     configuration/configure_input_player.h | ||||
|     configuration/configure_input_player.ui | ||||
|     configuration/configure_input_player_widget.cpp | ||||
|     configuration/configure_input_player_widget.h | ||||
|     configuration/configure_input_profile_dialog.cpp | ||||
|     configuration/configure_input_profile_dialog.h | ||||
|     configuration/configure_input_profile_dialog.ui | ||||
|   | ||||
| @@ -23,6 +23,7 @@ | ||||
| #include "ui_configure_input_player.h" | ||||
| #include "yuzu/configuration/config.h" | ||||
| #include "yuzu/configuration/configure_input_player.h" | ||||
| #include "yuzu/configuration/configure_input_player_widget.h" | ||||
| #include "yuzu/configuration/configure_vibration.h" | ||||
| #include "yuzu/configuration/input_profiles.h" | ||||
| #include "yuzu/util/limitable_input_dialog.h" | ||||
| @@ -254,11 +255,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|     analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup}; | ||||
|     analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange}; | ||||
|  | ||||
|     const auto ConfigureButtonClick = [&](QPushButton* button, Common::ParamPackage* param, | ||||
|                                           int default_val, InputCommon::Polling::DeviceType type) { | ||||
|     const auto ConfigureButtonClick = [&](QPushButton* button, std::size_t button_id, | ||||
|                                           Common::ParamPackage* param, int default_val, | ||||
|                                           InputCommon::Polling::DeviceType type) { | ||||
|         connect(button, &QPushButton::clicked, [=, this] { | ||||
|             HandleClick( | ||||
|                 button, | ||||
|                 button, button_id, | ||||
|                 [=, this](Common::ParamPackage params) { | ||||
|                     // Workaround for ZL & ZR for analog triggers like on XBOX | ||||
|                     // controllers. Analog triggers (from controllers like the XBOX | ||||
| @@ -286,12 +288,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         ConfigureButtonClick(button_map[button_id], &buttons_param[button_id], | ||||
|         ConfigureButtonClick(button_map[button_id], button_id, &buttons_param[button_id], | ||||
|                              Config::default_buttons[button_id], | ||||
|                              InputCommon::Polling::DeviceType::Button); | ||||
|  | ||||
|         button->setContextMenuPolicy(Qt::CustomContextMenu); | ||||
|  | ||||
|         connect(button, &QPushButton::customContextMenuRequested, | ||||
|                 [=, this](const QPoint& menu_location) { | ||||
|                     QMenu context_menu; | ||||
| @@ -300,6 +301,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|                         button_map[button_id]->setText(tr("[not set]")); | ||||
|                     }); | ||||
|                     context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); | ||||
|                     ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); | ||||
|                 }); | ||||
|     } | ||||
|  | ||||
| @@ -309,7 +311,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         ConfigureButtonClick(motion_map[motion_id], &motions_param[motion_id], | ||||
|         ConfigureButtonClick(motion_map[motion_id], motion_id, &motions_param[motion_id], | ||||
|                              Config::default_motions[motion_id], | ||||
|                              InputCommon::Polling::DeviceType::Motion); | ||||
|  | ||||
| @@ -348,7 +350,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|                     } | ||||
|                 } | ||||
|                 HandleClick( | ||||
|                     analog_map_buttons[analog_id][sub_button_id], | ||||
|                     analog_map_buttons[analog_id][sub_button_id], analog_id, | ||||
|                     [=, this](const Common::ParamPackage& params) { | ||||
|                         SetAnalogParam(params, analogs_param[analog_id], | ||||
|                                        analog_sub_buttons[sub_button_id]); | ||||
| @@ -358,41 +360,43 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|  | ||||
|             analog_button->setContextMenuPolicy(Qt::CustomContextMenu); | ||||
|  | ||||
|             connect(analog_button, &QPushButton::customContextMenuRequested, | ||||
|                     [=, this](const QPoint& menu_location) { | ||||
|                         QMenu context_menu; | ||||
|                         context_menu.addAction(tr("Clear"), [&] { | ||||
|                             analogs_param[analog_id].Clear(); | ||||
|                             analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); | ||||
|                         }); | ||||
|                         context_menu.addAction(tr("Invert axis"), [&] { | ||||
|                             if (sub_button_id == 2 || sub_button_id == 3) { | ||||
|                                 const bool invert_value = | ||||
|                                     analogs_param[analog_id].Get("invert_x", "+") == "-"; | ||||
|                                 const std::string invert_str = invert_value ? "+" : "-"; | ||||
|                                 analogs_param[analog_id].Set("invert_x", invert_str); | ||||
|                             } | ||||
|                             if (sub_button_id == 0 || sub_button_id == 1) { | ||||
|                                 const bool invert_value = | ||||
|                                     analogs_param[analog_id].Get("invert_y", "+") == "-"; | ||||
|                                 const std::string invert_str = invert_value ? "+" : "-"; | ||||
|                                 analogs_param[analog_id].Set("invert_y", invert_str); | ||||
|                             } | ||||
|                             for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; | ||||
|                                  ++sub_button_id) { | ||||
|                                 analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( | ||||
|                                     analogs_param[analog_id], analog_sub_buttons[sub_button_id])); | ||||
|                             } | ||||
|                         }); | ||||
|                         context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal( | ||||
|                             menu_location)); | ||||
|             connect( | ||||
|                 analog_button, &QPushButton::customContextMenuRequested, | ||||
|                 [=, this](const QPoint& menu_location) { | ||||
|                     QMenu context_menu; | ||||
|                     context_menu.addAction(tr("Clear"), [&] { | ||||
|                         analogs_param[analog_id].Clear(); | ||||
|                         analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); | ||||
|                     }); | ||||
|                     context_menu.addAction(tr("Invert axis"), [&] { | ||||
|                         if (sub_button_id == 2 || sub_button_id == 3) { | ||||
|                             const bool invert_value = | ||||
|                                 analogs_param[analog_id].Get("invert_x", "+") == "-"; | ||||
|                             const std::string invert_str = invert_value ? "+" : "-"; | ||||
|                             analogs_param[analog_id].Set("invert_x", invert_str); | ||||
|                         } | ||||
|                         if (sub_button_id == 0 || sub_button_id == 1) { | ||||
|                             const bool invert_value = | ||||
|                                 analogs_param[analog_id].Get("invert_y", "+") == "-"; | ||||
|                             const std::string invert_str = invert_value ? "+" : "-"; | ||||
|                             analogs_param[analog_id].Set("invert_y", invert_str); | ||||
|                         } | ||||
|                         for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; | ||||
|                              ++sub_button_id) { | ||||
|                             analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( | ||||
|                                 analogs_param[analog_id], analog_sub_buttons[sub_button_id])); | ||||
|                         } | ||||
|                     }); | ||||
|                     context_menu.exec( | ||||
|                         analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(menu_location)); | ||||
|                     ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); | ||||
|                 }); | ||||
|         } | ||||
|  | ||||
|         // Handle clicks for the modifier buttons as well. | ||||
|         connect(analog_map_modifier_button[analog_id], &QPushButton::clicked, [=, this] { | ||||
|             HandleClick( | ||||
|                 analog_map_modifier_button[analog_id], | ||||
|                 analog_map_modifier_button[analog_id], analog_id, | ||||
|                 [=, this](const Common::ParamPackage& params) { | ||||
|                     analogs_param[analog_id].Set("modifier", params.Serialize()); | ||||
|                 }, | ||||
| @@ -416,12 +420,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|                 [=, this] { | ||||
|                     const auto spinbox_value = analog_map_range_spinbox[analog_id]->value(); | ||||
|                     analogs_param[analog_id].Set("range", spinbox_value / 100.0f); | ||||
|                     ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); | ||||
|                 }); | ||||
|  | ||||
|         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); | ||||
|             ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); | ||||
|         }); | ||||
|  | ||||
|         connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] { | ||||
| @@ -433,8 +439,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|     } | ||||
|  | ||||
|     // Player Connected checkbox | ||||
|     connect(ui->groupConnectedController, &QGroupBox::toggled, | ||||
|             [this](bool checked) { emit Connected(checked); }); | ||||
|     connect(ui->groupConnectedController, &QGroupBox::toggled, [this](bool checked) { | ||||
|         emit Connected(checked); | ||||
|         ui->controllerFrame->SetConnectedStatus(checked); | ||||
|     }); | ||||
|  | ||||
|     if (player_index == 0) { | ||||
|         connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), | ||||
| @@ -553,6 +561,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | ||||
|  | ||||
|     // TODO(wwylele): enable this when we actually emulate it | ||||
|     ui->buttonHome->setEnabled(false); | ||||
|     ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); | ||||
|     ui->controllerFrame->SetConnectedStatus(ui->groupConnectedController->isChecked()); | ||||
| } | ||||
|  | ||||
| ConfigureInputPlayer::~ConfigureInputPlayer() = default; | ||||
| @@ -875,6 +885,7 @@ void ConfigureInputPlayer::UpdateUI() { | ||||
|         modifier_label->setVisible(!is_controller); | ||||
|         modifier_slider->setVisible(!is_controller); | ||||
|         range_groupbox->setVisible(is_controller); | ||||
|         ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -991,8 +1002,8 @@ void ConfigureInputPlayer::UpdateControllerIcon() { | ||||
|             return QString{}; | ||||
|         } | ||||
|     }(); | ||||
|  | ||||
|     ui->controllerFrame->setStyleSheet(stylesheet.arg(theme)); | ||||
|     ui->controllerFrame->SetControllerType( | ||||
|         GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())); | ||||
| } | ||||
|  | ||||
| void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | ||||
| @@ -1129,7 +1140,8 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() { | ||||
| } | ||||
|  | ||||
| void ConfigureInputPlayer::HandleClick( | ||||
|     QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, | ||||
|     QPushButton* button, std::size_t button_id, | ||||
|     std::function<void(const Common::ParamPackage&)> new_input_setter, | ||||
|     InputCommon::Polling::DeviceType type) { | ||||
|     if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) { | ||||
|         button->setText(tr("Shake!")); | ||||
| @@ -1173,6 +1185,12 @@ void ConfigureInputPlayer::HandleClick( | ||||
|         input_subsystem->GetMouseTouch()->BeginConfiguration(); | ||||
|     } | ||||
|  | ||||
|     if (type == InputCommon::Polling::DeviceType::Button) { | ||||
|         ui->controllerFrame->BeginMappingButton(button_id); | ||||
|     } else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) { | ||||
|         ui->controllerFrame->BeginMappingAnalog(button_id); | ||||
|     } | ||||
|  | ||||
|     timeout_timer->start(2500); // Cancel after 2.5 seconds | ||||
|     poll_timer->start(50);      // Check for new inputs every 50ms | ||||
| } | ||||
| @@ -1203,6 +1221,7 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, | ||||
|  | ||||
|     UpdateUI(); | ||||
|     UpdateInputDeviceCombobox(); | ||||
|     ui->controllerFrame->EndMapping(); | ||||
|  | ||||
|     input_setter = std::nullopt; | ||||
| } | ||||
|   | ||||
| @@ -106,7 +106,7 @@ private: | ||||
|     void LoadConfiguration(); | ||||
|  | ||||
|     /// Called when the button was pressed. | ||||
|     void HandleClick(QPushButton* button, | ||||
|     void HandleClick(QPushButton* button, std::size_t button_id, | ||||
|                      std::function<void(const Common::ParamPackage&)> new_input_setter, | ||||
|                      InputCommon::Polling::DeviceType type); | ||||
|  | ||||
|   | ||||
| @@ -1964,39 +1964,39 @@ | ||||
|              </item> | ||||
|             </layout> | ||||
|            </item> | ||||
|            <item> | ||||
|             <widget class="QFrame" name="controllerFrame"> | ||||
|              <property name="sizePolicy"> | ||||
|               <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||||
|                <horstretch>0</horstretch> | ||||
|                <verstretch>0</verstretch> | ||||
|               </sizepolicy> | ||||
|              </property> | ||||
|              <property name="font"> | ||||
|               <font> | ||||
|                <weight>75</weight> | ||||
|                <bold>true</bold> | ||||
|               </font> | ||||
|              </property> | ||||
|              <property name="styleSheet"> | ||||
|               <string notr="true">image: url(:/controller/pro);</string> | ||||
|              </property> | ||||
|              <layout class="QVBoxLayout" name="verticalLayout_4"> | ||||
|               <property name="leftMargin"> | ||||
|                <number>0</number> | ||||
|               </property> | ||||
|               <property name="topMargin"> | ||||
|                <number>0</number> | ||||
|               </property> | ||||
|               <property name="rightMargin"> | ||||
|                <number>0</number> | ||||
|               </property> | ||||
|               <property name="bottomMargin"> | ||||
|                <number>0</number> | ||||
|               </property> | ||||
|              </layout> | ||||
|             </widget> | ||||
|            </item> | ||||
|             <item> | ||||
|               <widget class="PlayerControlPreview" name="controllerFrame"> | ||||
|                 <property name="sizePolicy"> | ||||
|                   <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> | ||||
|                     <horstretch>0</horstretch> | ||||
|                     <verstretch>0</verstretch> | ||||
|                   </sizepolicy> | ||||
|                 </property> | ||||
|                 <property name="font"> | ||||
|                   <font> | ||||
|                     <weight>75</weight> | ||||
|                     <bold>true</bold> | ||||
|                   </font> | ||||
|                 </property> | ||||
|                 <property name="styleSheet"> | ||||
|                   <string notr="true">image: url(:/controller/pro);</string> | ||||
|                 </property> | ||||
|                 <layout class="QVBoxLayout" name="verticalLayout_4"> | ||||
|                   <property name="leftMargin"> | ||||
|                     <number>0</number> | ||||
|                   </property> | ||||
|                   <property name="topMargin"> | ||||
|                     <number>0</number> | ||||
|                   </property> | ||||
|                   <property name="rightMargin"> | ||||
|                     <number>0</number> | ||||
|                   </property> | ||||
|                   <property name="bottomMargin"> | ||||
|                     <number>0</number> | ||||
|                   </property> | ||||
|                 </layout> | ||||
|               </widget> | ||||
|             </item> | ||||
|            <item> | ||||
|             <layout class="QHBoxLayout" name="miscButtons"> | ||||
|              <property name="spacing"> | ||||
| @@ -3087,6 +3087,14 @@ | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|   <customwidgets> | ||||
|     <customwidget> | ||||
|       <class>PlayerControlPreview</class> | ||||
|       <extends>QFrame</extends> | ||||
|       <header>yuzu/configuration/configure_input_player_widget.h</header> | ||||
|       <container>1</container> | ||||
|     </customwidget> | ||||
|   </customwidgets> | ||||
|  <resources> | ||||
|   <include location="../../../dist/icons/controller/controller.qrc"/> | ||||
|  </resources> | ||||
|   | ||||
							
								
								
									
										1784
									
								
								src/yuzu/configuration/configure_input_player_widget.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										157
									
								
								src/yuzu/configuration/configure_input_player_widget.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,157 @@ | ||||
| // Copyright 2020 yuzu Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <array> | ||||
| #include <QFrame> | ||||
| #include <QPointer> | ||||
| #include "core/frontend/input.h" | ||||
| #include "core/settings.h" | ||||
|  | ||||
| class QLabel; | ||||
|  | ||||
| using AnalogParam = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>; | ||||
| using ButtonParam = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>; | ||||
|  | ||||
| // Widget for representing controller animations | ||||
| class PlayerControlPreview : public QFrame { | ||||
|     Q_OBJECT | ||||
|  | ||||
| public: | ||||
|     explicit PlayerControlPreview(QWidget* parent); | ||||
|     ~PlayerControlPreview() override; | ||||
|  | ||||
|     void SetPlayerInput(std::size_t index, const ButtonParam& buttons_param, | ||||
|                         const AnalogParam& analogs_param); | ||||
|     void SetConnectedStatus(bool checked); | ||||
|     void SetControllerType(Settings::ControllerType type); | ||||
|     void BeginMappingButton(std::size_t button_id); | ||||
|     void BeginMappingAnalog(std::size_t button_id); | ||||
|     void EndMapping(); | ||||
|  | ||||
| protected: | ||||
|     void paintEvent(QPaintEvent* event) override; | ||||
|  | ||||
| private: | ||||
|     enum class Direction : std::size_t { | ||||
|         None, | ||||
|         Up, | ||||
|         Right, | ||||
|         Down, | ||||
|         Left, | ||||
|     }; | ||||
|  | ||||
|     struct AxisValue { | ||||
|         QPointF value{}; | ||||
|         QPointF raw_value{}; | ||||
|         Input::AnalogProperties properties{}; | ||||
|         int size{}; | ||||
|         QPoint offset{}; | ||||
|         bool active{}; | ||||
|     }; | ||||
|  | ||||
|     struct LedPattern { | ||||
|         bool position1; | ||||
|         bool position2; | ||||
|         bool position3; | ||||
|         bool position4; | ||||
|     }; | ||||
|  | ||||
|     struct ColorMapping { | ||||
|         QColor outline{}; | ||||
|         QColor primary{}; | ||||
|         QColor left{}; | ||||
|         QColor right{}; | ||||
|         QColor button{}; | ||||
|         QColor button2{}; | ||||
|         QColor font{}; | ||||
|         QColor font2{}; | ||||
|         QColor highlight{}; | ||||
|         QColor highlight2{}; | ||||
|         QColor transparent{}; | ||||
|         QColor indicator{}; | ||||
|         QColor led_on{}; | ||||
|         QColor led_off{}; | ||||
|         QColor slider{}; | ||||
|         QColor slider_button{}; | ||||
|         QColor slider_arrow{}; | ||||
|         QColor deadzone{}; | ||||
|     }; | ||||
|  | ||||
|     static LedPattern GetColorPattern(std::size_t index, bool player_on); | ||||
|     void UpdateColors(); | ||||
|  | ||||
|     // Draw controller functions | ||||
|     void DrawHandheldController(QPainter& p, QPointF center); | ||||
|     void DrawDualController(QPainter& p, QPointF center); | ||||
|     void DrawLeftController(QPainter& p, QPointF center); | ||||
|     void DrawRightController(QPainter& p, QPointF center); | ||||
|     void DrawProController(QPainter& p, QPointF center); | ||||
|  | ||||
|     // Draw body functions | ||||
|     void DrawHandheldBody(QPainter& p, QPointF center); | ||||
|     void DrawDualBody(QPainter& p, QPointF center); | ||||
|     void DrawLeftBody(QPainter& p, QPointF center); | ||||
|     void DrawRightBody(QPainter& p, QPointF center); | ||||
|     void DrawProBody(QPainter& p, QPointF center); | ||||
|  | ||||
|     // Draw triggers functions | ||||
|     void DrawProTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); | ||||
|     void DrawHandheldTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); | ||||
|     void DrawDualTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); | ||||
|     void DrawDualZTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed); | ||||
|     void DrawLeftTriggers(QPainter& p, QPointF center, bool left_pressed); | ||||
|     void DrawLeftZTriggers(QPainter& p, QPointF center, bool left_pressed); | ||||
|     void DrawRightTriggers(QPainter& p, QPointF center, bool right_pressed); | ||||
|     void DrawRightZTriggers(QPainter& p, QPointF center, bool right_pressed); | ||||
|  | ||||
|     // Draw joystick functions | ||||
|     void DrawJoystick(QPainter& p, QPointF center, float size, bool pressed); | ||||
|     void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size, bool pressed); | ||||
|     void DrawRawJoystick(QPainter& p, QPointF center, const QPointF value, | ||||
|                          const Input::AnalogProperties properties); | ||||
|     void DrawProJoystick(QPainter& p, QPointF center, bool pressed); | ||||
|  | ||||
|     // Draw button functions | ||||
|     void DrawCircleButton(QPainter& p, QPointF center, bool pressed, int button_size); | ||||
|     void DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width, float height, | ||||
|                          Direction direction = Direction::None, float radius = 2); | ||||
|     void DrawMinusButton(QPainter& p, QPointF center, bool pressed, int button_size); | ||||
|     void DrawPlusButton(QPainter& p, QPointF center, bool pressed, int button_size); | ||||
|     void DrawArrowButton(QPainter& p, QPointF center, Direction direction, bool pressed); | ||||
|  | ||||
|     // Draw icon functions | ||||
|     void DrawHouseIcon(QPainter& p, QPointF center, float icon_size); | ||||
|     void DrawArrow(QPainter& p, QPointF center, Direction direction, float size); | ||||
|  | ||||
|     // Draw primitive types | ||||
|     template <size_t N> | ||||
|     void DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon); | ||||
|     void DrawCircle(QPainter& p, QPointF center, float size); | ||||
|     void DrawRectangle(QPainter& p, QPointF center, float width, float height); | ||||
|     void DrawRoundRectangle(QPainter& p, QPointF center, float width, float height, float round); | ||||
|     void DrawText(QPainter& p, QPointF center, float text_size, const QString& text); | ||||
|     void SetTextFont(QPainter& p, float text_size, | ||||
|                      const QString& font_family = QStringLiteral("sans-serif")); | ||||
|  | ||||
|     using ButtonArray = | ||||
|         std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::BUTTON_NS_END>; | ||||
|     using StickArray = | ||||
|         std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>; | ||||
|  | ||||
|     bool mapping_active{}; | ||||
|     int blink_counter{}; | ||||
|     QColor button_color{}; | ||||
|     ColorMapping colors{}; | ||||
|     std::array<QColor, 4> led_color{}; | ||||
|     ButtonArray buttons{}; | ||||
|     StickArray sticks{}; | ||||
|     std::size_t player_index{}; | ||||
|     std::size_t button_mapping_index{Settings::NativeButton::BUTTON_NS_END}; | ||||
|     std::size_t analog_mapping_index{Settings::NativeAnalog::NUM_STICKS_HID}; | ||||
|     std::array<AxisValue, Settings::NativeAnalog::NUM_STICKS_HID> axis_values{}; | ||||
|     std::array<bool, Settings::NativeButton::NumButtons> button_values{}; | ||||
|     Settings::ControllerType controller_type{Settings::ControllerType::ProController}; | ||||
| }; | ||||
 german
					german