controller_navigation.cpp 6.7 KB

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