configure_input.cpp 8.4 KB

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