summaryrefslogtreecommitdiff
path: root/src/yuzu/applets
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu/applets')
-rw-r--r--src/yuzu/applets/controller.cpp154
-rw-r--r--src/yuzu/applets/controller.h19
-rw-r--r--src/yuzu/applets/controller.ui49
3 files changed, 124 insertions, 98 deletions
diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp
index c6fa3e4f6..8ecfec770 100644
--- a/src/yuzu/applets/controller.cpp
+++ b/src/yuzu/applets/controller.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <thread>
#include "common/assert.h"
#include "common/string_util.h"
@@ -13,11 +14,16 @@
#include "core/hle/service/sm/sm.h"
#include "ui_controller.h"
#include "yuzu/applets/controller.h"
-#include "yuzu/configuration/configure_input_dialog.h"
+#include "yuzu/configuration/configure_input.h"
+#include "yuzu/configuration/configure_input_profile_dialog.h"
+#include "yuzu/configuration/configure_vibration.h"
+#include "yuzu/configuration/input_profiles.h"
#include "yuzu/main.h"
namespace {
+constexpr std::size_t HANDHELD_INDEX = 8;
+
constexpr std::array<std::array<bool, 4>, 8> led_patterns{{
{true, false, false, false},
{true, true, false, false},
@@ -106,7 +112,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
QWidget* parent, Core::Frontend::ControllerParameters parameters_,
InputCommon::InputSubsystem* input_subsystem_)
: QDialog(parent), ui(std::make_unique<Ui::QtControllerSelectorDialog>()),
- parameters(std::move(parameters_)), input_subsystem(input_subsystem_) {
+ parameters(std::move(parameters_)), input_subsystem{input_subsystem_},
+ input_profiles(std::make_unique<InputProfiles>()) {
ui->setupUi(this);
player_widgets = {
@@ -223,12 +230,22 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
}
}
+ connect(ui->vibrationButton, &QPushButton::clicked, this,
+ &QtControllerSelectorDialog::CallConfigureVibrationDialog);
+
connect(ui->inputConfigButton, &QPushButton::clicked, this,
- &QtControllerSelectorDialog::CallConfigureInputDialog);
+ &QtControllerSelectorDialog::CallConfigureInputProfileDialog);
connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
&QtControllerSelectorDialog::ApplyConfiguration);
+ // Enhancement: Check if the parameters have already been met before disconnecting controllers.
+ // If all the parameters are met AND only allows a single player,
+ // stop the constructor here as we do not need to continue.
+ if (CheckIfParametersMet() && parameters.enable_single_mode) {
+ return;
+ }
+
// If keep_controllers_connected is false, forcefully disconnect all controllers
if (!parameters.keep_controllers_connected) {
for (auto player : player_groupboxes) {
@@ -236,58 +253,66 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
}
}
- CheckIfParametersMet();
-
resize(0, 0);
}
QtControllerSelectorDialog::~QtControllerSelectorDialog() = default;
-void QtControllerSelectorDialog::ApplyConfiguration() {
- // Update the controller state once more, just to be sure they are properly applied.
- for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
- UpdateControllerState(index);
+int QtControllerSelectorDialog::exec() {
+ if (parameters_met && parameters.enable_single_mode) {
+ return QDialog::Accepted;
}
+ return QDialog::exec();
+}
- const bool pre_docked_mode = Settings::values.use_docked_mode;
- Settings::values.use_docked_mode = ui->radioDocked->isChecked();
- OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode);
+void QtControllerSelectorDialog::ApplyConfiguration() {
+ const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
+ Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
+ OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue());
- Settings::values.vibration_enabled = ui->vibrationGroup->isChecked();
+ Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
+ Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
}
void QtControllerSelectorDialog::LoadConfiguration() {
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
- const auto connected = Settings::values.players[index].connected ||
- (index == 0 && Settings::values.players[8].connected);
+ const auto connected =
+ Settings::values.players.GetValue()[index].connected ||
+ (index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
player_groupboxes[index]->setChecked(connected);
connected_controller_checkboxes[index]->setChecked(connected);
emulated_controllers[index]->setCurrentIndex(
- GetIndexFromControllerType(Settings::values.players[index].controller_type));
+ GetIndexFromControllerType(Settings::values.players.GetValue()[index].controller_type));
}
- UpdateDockedState(Settings::values.players[8].connected);
+ UpdateDockedState(Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
- ui->vibrationGroup->setChecked(Settings::values.vibration_enabled);
+ ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
+ ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
}
-void QtControllerSelectorDialog::CallConfigureInputDialog() {
- const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
-
- ConfigureInputDialog dialog(this, max_supported_players, input_subsystem);
+void QtControllerSelectorDialog::CallConfigureVibrationDialog() {
+ ConfigureVibration dialog(this);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint);
dialog.setWindowModality(Qt::WindowModal);
- dialog.exec();
- dialog.ApplyConfiguration();
+ if (dialog.exec() == QDialog::Accepted) {
+ dialog.ApplyConfiguration();
+ }
+}
- LoadConfiguration();
- CheckIfParametersMet();
+void QtControllerSelectorDialog::CallConfigureInputProfileDialog() {
+ ConfigureInputProfileDialog dialog(this, input_subsystem, input_profiles.get());
+
+ dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
+ Qt::WindowSystemMenuHint);
+ dialog.setWindowModality(Qt::WindowModal);
+ dialog.exec();
}
-void QtControllerSelectorDialog::CheckIfParametersMet() {
+bool QtControllerSelectorDialog::CheckIfParametersMet() {
// Here, we check and validate the current configuration against all applicable parameters.
const auto num_connected_players = static_cast<int>(
std::count_if(player_groupboxes.begin(), player_groupboxes.end(),
@@ -301,7 +326,7 @@ void QtControllerSelectorDialog::CheckIfParametersMet() {
num_connected_players > max_supported_players) {
parameters_met = false;
ui->buttonBox->setEnabled(parameters_met);
- return;
+ return parameters_met;
}
// Next, check against all connected controllers.
@@ -326,18 +351,13 @@ void QtControllerSelectorDialog::CheckIfParametersMet() {
return true;
}();
- if (!all_controllers_compatible) {
- parameters_met = false;
- ui->buttonBox->setEnabled(parameters_met);
- return;
- }
-
- parameters_met = true;
+ parameters_met = all_controllers_compatible;
ui->buttonBox->setEnabled(parameters_met);
+ return parameters_met;
}
void QtControllerSelectorDialog::SetSupportedControllers() {
- const QString theme = [this] {
+ const QString theme = [] {
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
return QStringLiteral("_dark");
} else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
@@ -426,7 +446,7 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
}
}();
- const QString theme = [this] {
+ const QString theme = [] {
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
return QStringLiteral("_dark");
} else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
@@ -441,32 +461,48 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
}
void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) {
- auto& player = Settings::values.players[player_index];
+ auto& player = Settings::values.players.GetValue()[player_index];
- player.controller_type =
+ const auto controller_type =
GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex());
- player.connected = player_groupboxes[player_index]->isChecked();
+ const auto player_connected = player_groupboxes[player_index]->isChecked() &&
+ controller_type != Settings::ControllerType::Handheld;
- // Player 2-8
- if (player_index != 0) {
- UpdateController(player.controller_type, player_index, player.connected);
+ if (player.controller_type == controller_type && player.connected == player_connected) {
+ // Set vibration devices in the event that the input device has changed.
+ ConfigureVibration::SetVibrationDevices(player_index);
return;
}
- // Player 1 and Handheld
- auto& handheld = Settings::values.players[8];
- // If Handheld is selected, copy all the settings from Player 1 to Handheld.
- if (player.controller_type == Settings::ControllerType::Handheld) {
- handheld = player;
- handheld.connected = player_groupboxes[player_index]->isChecked();
- player.connected = false; // Disconnect Player 1
- } else {
- player.connected = player_groupboxes[player_index]->isChecked();
- handheld.connected = false; // Disconnect Handheld
+ // Disconnect the controller first.
+ UpdateController(controller_type, player_index, false);
+
+ player.controller_type = controller_type;
+ player.connected = player_connected;
+
+ ConfigureVibration::SetVibrationDevices(player_index);
+
+ // Handheld
+ if (player_index == 0) {
+ auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
+ if (controller_type == Settings::ControllerType::Handheld) {
+ handheld = player;
+ }
+ handheld.connected = player_groupboxes[player_index]->isChecked() &&
+ controller_type == Settings::ControllerType::Handheld;
+ UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected);
}
- UpdateController(player.controller_type, player_index, player.connected);
- UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected);
+ if (!player.connected) {
+ return;
+ }
+
+ // This emulates a delay between disconnecting and reconnecting controllers as some games
+ // do not respond to a change in controller type if it was instantaneous.
+ using namespace std::chrono_literals;
+ std::this_thread::sleep_for(20ms);
+
+ UpdateController(controller_type, player_index, player_connected);
}
void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) {
@@ -520,8 +556,8 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) {
ui->radioDocked->setEnabled(!is_handheld);
ui->radioUndocked->setEnabled(!is_handheld);
- ui->radioDocked->setChecked(Settings::values.use_docked_mode);
- ui->radioUndocked->setChecked(!Settings::values.use_docked_mode);
+ ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
+ ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
// Also force into undocked mode if the controller type is handheld.
if (is_handheld) {
@@ -564,8 +600,8 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) {
// Disconnect any unsupported players here and disable or hide them if applicable.
- Settings::values.players[index].connected = false;
- UpdateController(Settings::values.players[index].controller_type, index, false);
+ Settings::values.players.GetValue()[index].connected = false;
+ UpdateController(Settings::values.players.GetValue()[index].controller_type, index, false);
// Hide the player widgets when max_supported_controllers is less than or equal to 4.
if (max_supported_players <= 4) {
player_widgets[index]->hide();
diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h
index 729ecc831..4344e1dd0 100644
--- a/src/yuzu/applets/controller.h
+++ b/src/yuzu/applets/controller.h
@@ -16,6 +16,8 @@ class QDialogButtonBox;
class QGroupBox;
class QLabel;
+class InputProfiles;
+
namespace InputCommon {
class InputSubsystem;
}
@@ -33,6 +35,8 @@ public:
InputCommon::InputSubsystem* input_subsystem_);
~QtControllerSelectorDialog() override;
+ int exec() override;
+
private:
// Applies the current configuration.
void ApplyConfiguration();
@@ -40,12 +44,15 @@ private:
// Loads the current input configuration into the frontend applet.
void LoadConfiguration();
- // Initializes the "Configure Input" Dialog.
- void CallConfigureInputDialog();
+ // Initializes the "Configure Vibration" Dialog.
+ void CallConfigureVibrationDialog();
- // Checks the current configuration against the given parameters and
- // sets the value of parameters_met.
- void CheckIfParametersMet();
+ // Initializes the "Create Input Profile" Dialog.
+ void CallConfigureInputProfileDialog();
+
+ // Checks the current configuration against the given parameters.
+ // This sets and returns the value of parameters_met.
+ bool CheckIfParametersMet();
// Sets the controller icons for "Supported Controller Types".
void SetSupportedControllers();
@@ -78,6 +85,8 @@ private:
InputCommon::InputSubsystem* input_subsystem;
+ std::unique_ptr<InputProfiles> input_profiles;
+
// This is true if and only if all parameters are met. Otherwise, this is false.
// This determines whether the "OK" button can be clicked to exit the applet.
bool parameters_met{false};
diff --git a/src/yuzu/applets/controller.ui b/src/yuzu/applets/controller.ui
index c4108a979..c8cb6bcf3 100644
--- a/src/yuzu/applets/controller.ui
+++ b/src/yuzu/applets/controller.ui
@@ -1217,9 +1217,6 @@
</item>
<item>
<widget class="QComboBox" name="comboPlayer3Emulated">
- <property name="editable">
- <bool>false</bool>
- </property>
<item>
<property name="text">
<string>Pro Controller</string>
@@ -2279,7 +2276,7 @@
<number>6</number>
</property>
<property name="leftMargin">
- <number>6</number>
+ <number>8</number>
</property>
<property name="topMargin">
<number>6</number>
@@ -2332,30 +2329,24 @@
<number>3</number>
</property>
<item>
- <widget class="QSpinBox" name="vibrationSpin">
+ <widget class="QPushButton" name="vibrationButton">
<property name="minimumSize">
<size>
- <width>65</width>
+ <width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
- <width>65</width>
+ <width>68</width>
<height>16777215</height>
</size>
</property>
- <property name="suffix">
- <string>%</string>
- </property>
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>200</number>
+ <property name="styleSheet">
+ <string notr="true">min-width: 68px;</string>
</property>
- <property name="value">
- <number>100</number>
+ <property name="text">
+ <string>Configure</string>
</property>
</widget>
</item>
@@ -2387,18 +2378,18 @@
<widget class="QPushButton" name="motionButton">
<property name="minimumSize">
<size>
- <width>57</width>
+ <width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
- <width>55</width>
+ <width>68</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
- <string notr="true">min-width: 55px;</string>
+ <string notr="true">min-width: 68px;</string>
</property>
<property name="text">
<string>Configure</string>
@@ -2411,7 +2402,7 @@
<item>
<widget class="QGroupBox" name="inputConfigGroup">
<property name="title">
- <string>Input Config</string>
+ <string>Profiles</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
@@ -2430,15 +2421,15 @@
<widget class="QPushButton" name="inputConfigButton">
<property name="maximumSize">
<size>
- <width>65</width>
+ <width>68</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
- <string notr="true">min-width: 55px;</string>
+ <string notr="true">min-width: 68px;</string>
</property>
<property name="text">
- <string>Open</string>
+ <string>Create</string>
</property>
</widget>
</item>
@@ -2657,16 +2648,6 @@
<signal>accepted()</signal>
<receiver>QtControllerSelectorDialog</receiver>
<slot>accept()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>20</x>
- <y>20</y>
- </hint>
- <hint type="destinationlabel">
- <x>20</x>
- <y>20</y>
- </hint>
- </hints>
</connection>
</connections>
</ui>