configure_input.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // Copyright 2016 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <memory>
  6. #include <utility>
  7. #include <QMenu>
  8. #include <QMessageBox>
  9. #include <QTimer>
  10. #include "common/param_package.h"
  11. #include "configuration/configure_touchscreen_advanced.h"
  12. #include "core/core.h"
  13. #include "core/hle/service/am/am.h"
  14. #include "core/hle/service/am/applet_ae.h"
  15. #include "core/hle/service/am/applet_oe.h"
  16. #include "core/hle/service/hid/controllers/npad.h"
  17. #include "core/hle/service/sm/sm.h"
  18. #include "input_common/main.h"
  19. #include "ui_configure_input.h"
  20. #include "ui_configure_input_player.h"
  21. #include "ui_configure_mouse_advanced.h"
  22. #include "ui_configure_touchscreen_advanced.h"
  23. #include "yuzu/configuration/config.h"
  24. #include "yuzu/configuration/configure_input.h"
  25. #include "yuzu/configuration/configure_input_player.h"
  26. #include "yuzu/configuration/configure_mouse_advanced.h"
  27. ConfigureInput::ConfigureInput(QWidget* parent)
  28. : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
  29. ui->setupUi(this);
  30. players_controller = {
  31. ui->player1_combobox, ui->player2_combobox, ui->player3_combobox, ui->player4_combobox,
  32. ui->player5_combobox, ui->player6_combobox, ui->player7_combobox, ui->player8_combobox,
  33. };
  34. players_configure = {
  35. ui->player1_configure, ui->player2_configure, ui->player3_configure, ui->player4_configure,
  36. ui->player5_configure, ui->player6_configure, ui->player7_configure, ui->player8_configure,
  37. };
  38. for (auto* controller_box : players_controller) {
  39. controller_box->addItems({"None", "Pro Controller", "Dual Joycons", "Single Right Joycon",
  40. "Single Left Joycon"});
  41. }
  42. this->loadConfiguration();
  43. updateUIEnabled();
  44. connect(ui->restore_defaults_button, &QPushButton::pressed, this,
  45. &ConfigureInput::restoreDefaults);
  46. for (auto* enabled : players_controller)
  47. connect(enabled, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
  48. &ConfigureInput::updateUIEnabled);
  49. connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled);
  50. connect(ui->handheld_connected, &QCheckBox::stateChanged, this,
  51. &ConfigureInput::updateUIEnabled);
  52. connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled);
  53. connect(ui->keyboard_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled);
  54. connect(ui->debug_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled);
  55. connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this,
  56. &ConfigureInput::updateUIEnabled);
  57. for (std::size_t i = 0; i < players_configure.size(); ++i) {
  58. connect(players_configure[i], &QPushButton::pressed, this,
  59. [this, i]() { CallConfigureDialog<ConfigureInputPlayer>(i, false); });
  60. }
  61. connect(ui->handheld_configure, &QPushButton::pressed, this,
  62. [this]() { CallConfigureDialog<ConfigureInputPlayer>(8, false); });
  63. connect(ui->debug_configure, &QPushButton::pressed, this,
  64. [this]() { CallConfigureDialog<ConfigureInputPlayer>(9, true); });
  65. connect(ui->mouse_advanced, &QPushButton::pressed, this,
  66. [this]() { CallConfigureDialog<ConfigureMouseAdvanced>(); });
  67. connect(ui->touchscreen_advanced, &QPushButton::pressed, this,
  68. [this]() { CallConfigureDialog<ConfigureTouchscreenAdvanced>(); });
  69. }
  70. template <typename Dialog, typename... Args>
  71. void ConfigureInput::CallConfigureDialog(Args&&... args) {
  72. this->applyConfiguration();
  73. Dialog dialog(this, std::forward<Args>(args)...);
  74. const auto res = dialog.exec();
  75. if (res == QDialog::Accepted) {
  76. dialog.applyConfiguration();
  77. }
  78. }
  79. void ConfigureInput::OnDockedModeChanged(bool last_state, bool new_state) {
  80. if (last_state == new_state) {
  81. return;
  82. }
  83. Core::System& system{Core::System::GetInstance()};
  84. if (!system.IsPoweredOn()) {
  85. return;
  86. }
  87. Service::SM::ServiceManager& sm = system.ServiceManager();
  88. // Message queue is shared between these services, we just need to signal an operation
  89. // change to one and it will handle both automatically
  90. auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
  91. auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
  92. bool has_signalled = false;
  93. if (applet_oe != nullptr) {
  94. applet_oe->GetMessageQueue()->OperationModeChanged();
  95. has_signalled = true;
  96. }
  97. if (applet_ae != nullptr && !has_signalled) {
  98. applet_ae->GetMessageQueue()->OperationModeChanged();
  99. }
  100. }
  101. void ConfigureInput::applyConfiguration() {
  102. for (std::size_t i = 0; i < players_controller.size(); ++i) {
  103. const auto controller_type_index = players_controller[i]->currentIndex();
  104. Settings::values.players[i].connected = controller_type_index != 0;
  105. if (controller_type_index > 0) {
  106. Settings::values.players[i].type =
  107. static_cast<Settings::ControllerType>(controller_type_index - 1);
  108. } else {
  109. Settings::values.players[i].type = Settings::ControllerType::DualJoycon;
  110. }
  111. }
  112. const bool pre_docked_mode = Settings::values.use_docked_mode;
  113. Settings::values.use_docked_mode = ui->use_docked_mode->isChecked();
  114. OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode);
  115. Settings::values
  116. .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)]
  117. .connected = ui->handheld_connected->isChecked();
  118. Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked();
  119. Settings::values.mouse_enabled = ui->mouse_enabled->isChecked();
  120. Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked();
  121. Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked();
  122. }
  123. void ConfigureInput::updateUIEnabled() {
  124. bool hit_disabled = false;
  125. for (auto* player : players_controller) {
  126. player->setDisabled(hit_disabled);
  127. if (hit_disabled)
  128. player->setCurrentIndex(0);
  129. if (!hit_disabled && player->currentIndex() == 0)
  130. hit_disabled = true;
  131. }
  132. for (std::size_t i = 0; i < players_controller.size(); ++i) {
  133. players_configure[i]->setEnabled(players_controller[i]->currentIndex() != 0);
  134. }
  135. ui->handheld_connected->setEnabled(!ui->use_docked_mode->isChecked());
  136. ui->handheld_configure->setEnabled(ui->handheld_connected->isChecked() &&
  137. !ui->use_docked_mode->isChecked());
  138. ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked());
  139. ui->debug_configure->setEnabled(ui->debug_enabled->isChecked());
  140. ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked());
  141. }
  142. void ConfigureInput::loadConfiguration() {
  143. std::stable_partition(
  144. Settings::values.players.begin(),
  145. Settings::values.players.begin() +
  146. Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD),
  147. [](const auto& player) { return player.connected; });
  148. for (std::size_t i = 0; i < players_controller.size(); ++i) {
  149. const auto connected = Settings::values.players[i].connected;
  150. players_controller[i]->setCurrentIndex(
  151. connected ? static_cast<u8>(Settings::values.players[i].type) + 1 : 0);
  152. }
  153. ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
  154. ui->handheld_connected->setChecked(
  155. Settings::values
  156. .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)]
  157. .connected);
  158. ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled);
  159. ui->mouse_enabled->setChecked(Settings::values.mouse_enabled);
  160. ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled);
  161. ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled);
  162. updateUIEnabled();
  163. }
  164. void ConfigureInput::restoreDefaults() {
  165. players_controller[0]->setCurrentIndex(2);
  166. for (std::size_t i = 1; i < players_controller.size(); ++i) {
  167. players_controller[i]->setCurrentIndex(0);
  168. }
  169. ui->use_docked_mode->setCheckState(Qt::Unchecked);
  170. ui->handheld_connected->setCheckState(Qt::Unchecked);
  171. ui->mouse_enabled->setCheckState(Qt::Unchecked);
  172. ui->keyboard_enabled->setCheckState(Qt::Unchecked);
  173. ui->debug_enabled->setCheckState(Qt::Unchecked);
  174. ui->touchscreen_enabled->setCheckState(Qt::Checked);
  175. updateUIEnabled();
  176. }