input_mapping.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. case EngineInputType::Motion:
  76. new_input.Set("motion", data.index);
  77. break;
  78. default:
  79. return;
  80. }
  81. input_queue.Push(new_input);
  82. }
  83. void MappingFactory::RegisterStick(const MappingData& data) {
  84. Common::ParamPackage new_input;
  85. new_input.Set("engine", data.engine);
  86. if (data.pad.guid.IsValid()) {
  87. new_input.Set("guid", data.pad.guid.RawString());
  88. }
  89. new_input.Set("port", static_cast<int>(data.pad.port));
  90. new_input.Set("pad", static_cast<int>(data.pad.pad));
  91. // If engine is mouse map the mouse position as a joystick
  92. if (data.engine == "mouse") {
  93. new_input.Set("axis_x", 0);
  94. new_input.Set("axis_y", 1);
  95. new_input.Set("threshold", 0.5f);
  96. new_input.Set("range", 1.0f);
  97. new_input.Set("deadzone", 0.0f);
  98. input_queue.Push(new_input);
  99. return;
  100. }
  101. switch (data.type) {
  102. case EngineInputType::Button:
  103. case EngineInputType::HatButton:
  104. RegisterButton(data);
  105. return;
  106. case EngineInputType::Analog:
  107. if (first_axis == data.index) {
  108. return;
  109. }
  110. if (first_axis == -1) {
  111. first_axis = data.index;
  112. return;
  113. }
  114. new_input.Set("axis_x", first_axis);
  115. new_input.Set("axis_y", data.index);
  116. new_input.Set("threshold", 0.5f);
  117. new_input.Set("range", 0.95f);
  118. new_input.Set("deadzone", 0.15f);
  119. break;
  120. default:
  121. return;
  122. }
  123. input_queue.Push(new_input);
  124. }
  125. void MappingFactory::RegisterMotion(const MappingData& data) {
  126. Common::ParamPackage new_input;
  127. new_input.Set("engine", data.engine);
  128. if (data.pad.guid.IsValid()) {
  129. new_input.Set("guid", data.pad.guid.RawString());
  130. }
  131. new_input.Set("port", static_cast<int>(data.pad.port));
  132. new_input.Set("pad", static_cast<int>(data.pad.pad));
  133. // If engine is mouse map it automatically to mouse motion
  134. if (data.engine == "mouse") {
  135. new_input.Set("motion", 0);
  136. new_input.Set("pad", 1);
  137. new_input.Set("threshold", 0.001f);
  138. input_queue.Push(new_input);
  139. return;
  140. }
  141. switch (data.type) {
  142. case EngineInputType::Button:
  143. case EngineInputType::HatButton:
  144. RegisterButton(data);
  145. return;
  146. case EngineInputType::Analog:
  147. if (first_axis == data.index) {
  148. return;
  149. }
  150. if (second_axis == data.index) {
  151. return;
  152. }
  153. if (first_axis == -1) {
  154. first_axis = data.index;
  155. return;
  156. }
  157. if (second_axis == -1) {
  158. second_axis = data.index;
  159. return;
  160. }
  161. new_input.Set("axis_x", first_axis);
  162. new_input.Set("axis_y", second_axis);
  163. new_input.Set("axis_z", data.index);
  164. new_input.Set("range", 1.0f);
  165. new_input.Set("deadzone", 0.20f);
  166. break;
  167. case EngineInputType::Motion:
  168. new_input.Set("motion", data.index);
  169. break;
  170. default:
  171. return;
  172. }
  173. input_queue.Push(new_input);
  174. }
  175. bool MappingFactory::IsDriverValid(const MappingData& data) const {
  176. // Only port 0 can be mapped on the keyboard
  177. if (data.engine == "keyboard" && data.pad.port != 0) {
  178. return false;
  179. }
  180. // Only port 0 can be mapped on the mouse
  181. if (data.engine == "mouse" && data.pad.port != 0) {
  182. return false;
  183. }
  184. // To prevent mapping with two devices we disable any UDP except motion
  185. if (!Settings::values.enable_udp_controller && data.engine == "cemuhookudp" &&
  186. data.type != EngineInputType::Motion) {
  187. return false;
  188. }
  189. // The following drivers don't need to be mapped
  190. if (data.engine == "touch_from_button") {
  191. return false;
  192. }
  193. if (data.engine == "analog_from_button") {
  194. return false;
  195. }
  196. if (data.engine == "virtual_gamepad") {
  197. return false;
  198. }
  199. return true;
  200. }
  201. } // namespace InputCommon