input_mapping.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/settings.h"
  4. #include "input_common/input_engine.h"
  5. #include "input_common/input_mapping.h"
  6. namespace InputCommon {
  7. MappingFactory::MappingFactory() = default;
  8. void MappingFactory::BeginMapping(Polling::InputType type) {
  9. is_enabled = true;
  10. input_type = type;
  11. input_queue.Clear();
  12. first_axis = -1;
  13. second_axis = -1;
  14. }
  15. Common::ParamPackage MappingFactory::GetNextInput() {
  16. Common::ParamPackage input;
  17. input_queue.Pop(input);
  18. return input;
  19. }
  20. void MappingFactory::RegisterInput(const MappingData& data) {
  21. if (!is_enabled) {
  22. return;
  23. }
  24. if (!IsDriverValid(data)) {
  25. return;
  26. }
  27. switch (input_type) {
  28. case Polling::InputType::Button:
  29. RegisterButton(data);
  30. return;
  31. case Polling::InputType::Stick:
  32. RegisterStick(data);
  33. return;
  34. case Polling::InputType::Motion:
  35. RegisterMotion(data);
  36. return;
  37. default:
  38. return;
  39. }
  40. }
  41. void MappingFactory::StopMapping() {
  42. is_enabled = false;
  43. input_type = Polling::InputType::None;
  44. input_queue.Clear();
  45. }
  46. void MappingFactory::RegisterButton(const MappingData& data) {
  47. Common::ParamPackage new_input;
  48. new_input.Set("engine", data.engine);
  49. if (data.pad.guid.IsValid()) {
  50. new_input.Set("guid", data.pad.guid.RawString());
  51. }
  52. new_input.Set("port", static_cast<int>(data.pad.port));
  53. new_input.Set("pad", static_cast<int>(data.pad.pad));
  54. switch (data.type) {
  55. case EngineInputType::Button:
  56. // Workaround for old compatibility
  57. if (data.engine == "keyboard") {
  58. new_input.Set("code", data.index);
  59. break;
  60. }
  61. new_input.Set("button", data.index);
  62. break;
  63. case EngineInputType::HatButton:
  64. new_input.Set("hat", data.index);
  65. new_input.Set("direction", data.hat_name);
  66. break;
  67. case EngineInputType::Analog:
  68. // Ignore mouse axis when mapping buttons
  69. if (data.engine == "mouse" && data.index != 4) {
  70. return;
  71. }
  72. new_input.Set("axis", data.index);
  73. new_input.Set("threshold", 0.5f);
  74. break;
  75. default:
  76. return;
  77. }
  78. input_queue.Push(new_input);
  79. }
  80. void MappingFactory::RegisterStick(const MappingData& data) {
  81. Common::ParamPackage new_input;
  82. new_input.Set("engine", data.engine);
  83. if (data.pad.guid.IsValid()) {
  84. new_input.Set("guid", data.pad.guid.RawString());
  85. }
  86. new_input.Set("port", static_cast<int>(data.pad.port));
  87. new_input.Set("pad", static_cast<int>(data.pad.pad));
  88. // If engine is mouse map the mouse position as a joystick
  89. if (data.engine == "mouse") {
  90. new_input.Set("axis_x", 0);
  91. new_input.Set("axis_y", 1);
  92. new_input.Set("threshold", 0.5f);
  93. new_input.Set("range", 1.0f);
  94. new_input.Set("deadzone", 0.0f);
  95. input_queue.Push(new_input);
  96. return;
  97. }
  98. switch (data.type) {
  99. case EngineInputType::Button:
  100. case EngineInputType::HatButton:
  101. RegisterButton(data);
  102. return;
  103. case EngineInputType::Analog:
  104. if (first_axis == data.index) {
  105. return;
  106. }
  107. if (first_axis == -1) {
  108. first_axis = data.index;
  109. return;
  110. }
  111. new_input.Set("axis_x", first_axis);
  112. new_input.Set("axis_y", data.index);
  113. new_input.Set("threshold", 0.5f);
  114. new_input.Set("range", 0.95f);
  115. new_input.Set("deadzone", 0.15f);
  116. break;
  117. default:
  118. return;
  119. }
  120. input_queue.Push(new_input);
  121. }
  122. void MappingFactory::RegisterMotion(const MappingData& data) {
  123. Common::ParamPackage new_input;
  124. new_input.Set("engine", data.engine);
  125. if (data.pad.guid.IsValid()) {
  126. new_input.Set("guid", data.pad.guid.RawString());
  127. }
  128. new_input.Set("port", static_cast<int>(data.pad.port));
  129. new_input.Set("pad", static_cast<int>(data.pad.pad));
  130. // If engine is mouse map it automatically to mouse motion
  131. if (data.engine == "mouse") {
  132. new_input.Set("motion", 0);
  133. new_input.Set("pad", 1);
  134. new_input.Set("threshold", 0.001f);
  135. input_queue.Push(new_input);
  136. return;
  137. }
  138. switch (data.type) {
  139. case EngineInputType::Button:
  140. case EngineInputType::HatButton:
  141. RegisterButton(data);
  142. return;
  143. case EngineInputType::Analog:
  144. if (first_axis == data.index) {
  145. return;
  146. }
  147. if (second_axis == data.index) {
  148. return;
  149. }
  150. if (first_axis == -1) {
  151. first_axis = data.index;
  152. return;
  153. }
  154. if (second_axis == -1) {
  155. second_axis = data.index;
  156. return;
  157. }
  158. new_input.Set("axis_x", first_axis);
  159. new_input.Set("axis_y", second_axis);
  160. new_input.Set("axis_z", data.index);
  161. new_input.Set("range", 1.0f);
  162. new_input.Set("deadzone", 0.20f);
  163. break;
  164. case EngineInputType::Motion:
  165. new_input.Set("motion", data.index);
  166. break;
  167. default:
  168. return;
  169. }
  170. input_queue.Push(new_input);
  171. }
  172. bool MappingFactory::IsDriverValid(const MappingData& data) const {
  173. // Only port 0 can be mapped on the keyboard
  174. if (data.engine == "keyboard" && data.pad.port != 0) {
  175. return false;
  176. }
  177. // Only port 0 can be mapped on the mouse
  178. if (data.engine == "mouse" && data.pad.port != 0) {
  179. return false;
  180. }
  181. // To prevent mapping with two devices we disable any UDP except motion
  182. if (!Settings::values.enable_udp_controller && data.engine == "cemuhookudp" &&
  183. data.type != EngineInputType::Motion) {
  184. return false;
  185. }
  186. // The following drivers don't need to be mapped
  187. if (data.engine == "touch_from_button") {
  188. return false;
  189. }
  190. if (data.engine == "analog_from_button") {
  191. return false;
  192. }
  193. return true;
  194. }
  195. } // namespace InputCommon