controller_navigation.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/settings_input.h"
  4. #include "core/hid/emulated_controller.h"
  5. #include "core/hid/hid_core.h"
  6. #include "yuzu/util/controller_navigation.h"
  7. ControllerNavigation::ControllerNavigation(Core::HID::HIDCore& hid_core, QWidget* parent) {
  8. player1_controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
  9. handheld_controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
  10. Core::HID::ControllerUpdateCallback engine_callback{
  11. .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdateEvent(type); },
  12. .is_npad_service = false,
  13. };
  14. player1_callback_key = player1_controller->SetCallback(engine_callback);
  15. handheld_callback_key = handheld_controller->SetCallback(engine_callback);
  16. is_controller_set = true;
  17. }
  18. ControllerNavigation::~ControllerNavigation() {
  19. UnloadController();
  20. }
  21. void ControllerNavigation::UnloadController() {
  22. if (is_controller_set) {
  23. player1_controller->DeleteCallback(player1_callback_key);
  24. handheld_controller->DeleteCallback(handheld_callback_key);
  25. is_controller_set = false;
  26. }
  27. }
  28. void ControllerNavigation::TriggerButton(Settings::NativeButton::Values native_button,
  29. Qt::Key key) {
  30. if (button_values[native_button].value && !button_values[native_button].locked) {
  31. emit TriggerKeyboardEvent(key);
  32. }
  33. }
  34. void ControllerNavigation::ControllerUpdateEvent(Core::HID::ControllerTriggerType type) {
  35. std::scoped_lock lock{mutex};
  36. if (!Settings::values.controller_navigation) {
  37. return;
  38. }
  39. if (type == Core::HID::ControllerTriggerType::Button) {
  40. ControllerUpdateButton();
  41. return;
  42. }
  43. if (type == Core::HID::ControllerTriggerType::Stick) {
  44. ControllerUpdateStick();
  45. return;
  46. }
  47. }
  48. void ControllerNavigation::ControllerUpdateButton() {
  49. const auto controller_type = player1_controller->GetNpadStyleIndex();
  50. const auto& player1_buttons = player1_controller->GetButtonsValues();
  51. const auto& handheld_buttons = handheld_controller->GetButtonsValues();
  52. for (std::size_t i = 0; i < player1_buttons.size(); ++i) {
  53. const bool button = player1_buttons[i].value || handheld_buttons[i].value;
  54. // Trigger only once
  55. button_values[i].locked = button == button_values[i].value;
  56. button_values[i].value = button;
  57. }
  58. switch (controller_type) {
  59. case Core::HID::NpadStyleIndex::ProController:
  60. case Core::HID::NpadStyleIndex::JoyconDual:
  61. case Core::HID::NpadStyleIndex::Handheld:
  62. case Core::HID::NpadStyleIndex::GameCube:
  63. TriggerButton(Settings::NativeButton::A, Qt::Key_Enter);
  64. TriggerButton(Settings::NativeButton::B, Qt::Key_Escape);
  65. TriggerButton(Settings::NativeButton::DDown, Qt::Key_Down);
  66. TriggerButton(Settings::NativeButton::DLeft, Qt::Key_Left);
  67. TriggerButton(Settings::NativeButton::DRight, Qt::Key_Right);
  68. TriggerButton(Settings::NativeButton::DUp, Qt::Key_Up);
  69. break;
  70. case Core::HID::NpadStyleIndex::JoyconLeft:
  71. TriggerButton(Settings::NativeButton::DDown, Qt::Key_Enter);
  72. TriggerButton(Settings::NativeButton::DLeft, Qt::Key_Escape);
  73. break;
  74. case Core::HID::NpadStyleIndex::JoyconRight:
  75. TriggerButton(Settings::NativeButton::X, Qt::Key_Enter);
  76. TriggerButton(Settings::NativeButton::A, Qt::Key_Escape);
  77. break;
  78. default:
  79. break;
  80. }
  81. }
  82. void ControllerNavigation::ControllerUpdateStick() {
  83. const auto controller_type = player1_controller->GetNpadStyleIndex();
  84. const auto& player1_sticks = player1_controller->GetSticksValues();
  85. const auto& handheld_sticks = player1_controller->GetSticksValues();
  86. bool update = false;
  87. for (std::size_t i = 0; i < player1_sticks.size(); ++i) {
  88. const Common::Input::StickStatus stick{
  89. .left = player1_sticks[i].left || handheld_sticks[i].left,
  90. .right = player1_sticks[i].right || handheld_sticks[i].right,
  91. .up = player1_sticks[i].up || handheld_sticks[i].up,
  92. .down = player1_sticks[i].down || handheld_sticks[i].down,
  93. };
  94. // Trigger only once
  95. if (stick.down != stick_values[i].down || stick.left != stick_values[i].left ||
  96. stick.right != stick_values[i].right || stick.up != stick_values[i].up) {
  97. update = true;
  98. }
  99. stick_values[i] = stick;
  100. }
  101. if (!update) {
  102. return;
  103. }
  104. switch (controller_type) {
  105. case Core::HID::NpadStyleIndex::ProController:
  106. case Core::HID::NpadStyleIndex::JoyconDual:
  107. case Core::HID::NpadStyleIndex::Handheld:
  108. case Core::HID::NpadStyleIndex::GameCube:
  109. if (stick_values[Settings::NativeAnalog::LStick].down) {
  110. emit TriggerKeyboardEvent(Qt::Key_Down);
  111. return;
  112. }
  113. if (stick_values[Settings::NativeAnalog::LStick].left) {
  114. emit TriggerKeyboardEvent(Qt::Key_Left);
  115. return;
  116. }
  117. if (stick_values[Settings::NativeAnalog::LStick].right) {
  118. emit TriggerKeyboardEvent(Qt::Key_Right);
  119. return;
  120. }
  121. if (stick_values[Settings::NativeAnalog::LStick].up) {
  122. emit TriggerKeyboardEvent(Qt::Key_Up);
  123. return;
  124. }
  125. break;
  126. case Core::HID::NpadStyleIndex::JoyconLeft:
  127. if (stick_values[Settings::NativeAnalog::LStick].left) {
  128. emit TriggerKeyboardEvent(Qt::Key_Down);
  129. return;
  130. }
  131. if (stick_values[Settings::NativeAnalog::LStick].up) {
  132. emit TriggerKeyboardEvent(Qt::Key_Left);
  133. return;
  134. }
  135. if (stick_values[Settings::NativeAnalog::LStick].down) {
  136. emit TriggerKeyboardEvent(Qt::Key_Right);
  137. return;
  138. }
  139. if (stick_values[Settings::NativeAnalog::LStick].right) {
  140. emit TriggerKeyboardEvent(Qt::Key_Up);
  141. return;
  142. }
  143. break;
  144. case Core::HID::NpadStyleIndex::JoyconRight:
  145. if (stick_values[Settings::NativeAnalog::RStick].right) {
  146. emit TriggerKeyboardEvent(Qt::Key_Down);
  147. return;
  148. }
  149. if (stick_values[Settings::NativeAnalog::RStick].down) {
  150. emit TriggerKeyboardEvent(Qt::Key_Left);
  151. return;
  152. }
  153. if (stick_values[Settings::NativeAnalog::RStick].up) {
  154. emit TriggerKeyboardEvent(Qt::Key_Right);
  155. return;
  156. }
  157. if (stick_values[Settings::NativeAnalog::RStick].left) {
  158. emit TriggerKeyboardEvent(Qt::Key_Up);
  159. return;
  160. }
  161. break;
  162. default:
  163. break;
  164. }
  165. }