mouse_poller.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <mutex>
  5. #include <utility>
  6. #include "common/threadsafe_queue.h"
  7. #include "core/settings.h"
  8. #include "input_common/mouse/mouse_input.h"
  9. #include "input_common/mouse/mouse_poller.h"
  10. namespace InputCommon {
  11. class MouseButton final : public Input::ButtonDevice {
  12. public:
  13. explicit MouseButton(u32 button_, const MouseInput::Mouse* mouse_input_)
  14. : button(button_), mouse_input(mouse_input_) {}
  15. bool GetStatus() const override {
  16. return mouse_input->GetMouseState(button).pressed;
  17. }
  18. private:
  19. const u32 button;
  20. const MouseInput::Mouse* mouse_input;
  21. };
  22. MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
  23. : mouse_input(std::move(mouse_input_)) {}
  24. std::unique_ptr<Input::ButtonDevice> MouseButtonFactory::Create(
  25. const Common::ParamPackage& params) {
  26. const auto button_id = params.Get("button", 0);
  27. return std::make_unique<MouseButton>(button_id, mouse_input.get());
  28. }
  29. Common::ParamPackage MouseButtonFactory::GetNextInput() const {
  30. MouseInput::MouseStatus pad;
  31. Common::ParamPackage params;
  32. auto& queue = mouse_input->GetMouseQueue();
  33. while (queue.Pop(pad)) {
  34. // This while loop will break on the earliest detected button
  35. if (pad.button != MouseInput::MouseButton::Undefined) {
  36. params.Set("engine", "mouse");
  37. params.Set("button", static_cast<u16>(pad.button));
  38. return params;
  39. }
  40. }
  41. return params;
  42. }
  43. void MouseButtonFactory::BeginConfiguration() {
  44. polling = true;
  45. mouse_input->BeginConfiguration();
  46. }
  47. void MouseButtonFactory::EndConfiguration() {
  48. polling = false;
  49. mouse_input->EndConfiguration();
  50. }
  51. class MouseAnalog final : public Input::AnalogDevice {
  52. public:
  53. explicit MouseAnalog(u32 port_, u32 axis_x_, u32 axis_y_, bool invert_x_, bool invert_y_,
  54. float deadzone_, float range_, const MouseInput::Mouse* mouse_input_)
  55. : button(port_), axis_x(axis_x_), axis_y(axis_y_), invert_x(invert_x_), invert_y(invert_y_),
  56. deadzone(deadzone_), range(range_), mouse_input(mouse_input_) {}
  57. float GetAxis(u32 axis) const {
  58. std::lock_guard lock{mutex};
  59. const auto axis_value =
  60. static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis));
  61. return axis_value * Settings::values.mouse_panning_sensitivity / (100.0f * range);
  62. }
  63. std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
  64. float x = GetAxis(analog_axis_x);
  65. float y = GetAxis(analog_axis_y);
  66. if (invert_x) {
  67. x = -x;
  68. }
  69. if (invert_y) {
  70. y = -y;
  71. }
  72. // Make sure the coordinates are in the unit circle,
  73. // otherwise normalize it.
  74. float r = x * x + y * y;
  75. if (r > 1.0f) {
  76. r = std::sqrt(r);
  77. x /= r;
  78. y /= r;
  79. }
  80. return {x, y};
  81. }
  82. std::tuple<float, float> GetStatus() const override {
  83. const auto [x, y] = GetAnalog(axis_x, axis_y);
  84. const float r = std::sqrt((x * x) + (y * y));
  85. if (r > deadzone) {
  86. return {x / r * (r - deadzone) / (1 - deadzone),
  87. y / r * (r - deadzone) / (1 - deadzone)};
  88. }
  89. return {0.0f, 0.0f};
  90. }
  91. private:
  92. const u32 button;
  93. const u32 axis_x;
  94. const u32 axis_y;
  95. const bool invert_x;
  96. const bool invert_y;
  97. const float deadzone;
  98. const float range;
  99. const MouseInput::Mouse* mouse_input;
  100. mutable std::mutex mutex;
  101. };
  102. /// An analog device factory that creates analog devices from GC Adapter
  103. MouseAnalogFactory::MouseAnalogFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
  104. : mouse_input(std::move(mouse_input_)) {}
  105. /**
  106. * Creates analog device from joystick axes
  107. * @param params contains parameters for creating the device:
  108. * - "port": the nth gcpad on the adapter
  109. * - "axis_x": the index of the axis to be bind as x-axis
  110. * - "axis_y": the index of the axis to be bind as y-axis
  111. */
  112. std::unique_ptr<Input::AnalogDevice> MouseAnalogFactory::Create(
  113. const Common::ParamPackage& params) {
  114. const auto port = static_cast<u32>(params.Get("port", 0));
  115. const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
  116. const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
  117. const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
  118. const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
  119. const std::string invert_x_value = params.Get("invert_x", "+");
  120. const std::string invert_y_value = params.Get("invert_y", "+");
  121. const bool invert_x = invert_x_value == "-";
  122. const bool invert_y = invert_y_value == "-";
  123. return std::make_unique<MouseAnalog>(port, axis_x, axis_y, invert_x, invert_y, deadzone, range,
  124. mouse_input.get());
  125. }
  126. void MouseAnalogFactory::BeginConfiguration() {
  127. polling = true;
  128. mouse_input->BeginConfiguration();
  129. }
  130. void MouseAnalogFactory::EndConfiguration() {
  131. polling = false;
  132. mouse_input->EndConfiguration();
  133. }
  134. Common::ParamPackage MouseAnalogFactory::GetNextInput() const {
  135. MouseInput::MouseStatus pad;
  136. Common::ParamPackage params;
  137. auto& queue = mouse_input->GetMouseQueue();
  138. while (queue.Pop(pad)) {
  139. // This while loop will break on the earliest detected button
  140. if (pad.button != MouseInput::MouseButton::Undefined) {
  141. params.Set("engine", "mouse");
  142. params.Set("port", static_cast<u16>(pad.button));
  143. params.Set("axis_x", 0);
  144. params.Set("axis_y", 1);
  145. params.Set("invert_x", "+");
  146. params.Set("invert_y", "+");
  147. return params;
  148. }
  149. }
  150. return params;
  151. }
  152. class MouseMotion final : public Input::MotionDevice {
  153. public:
  154. explicit MouseMotion(u32 button_, const MouseInput::Mouse* mouse_input_)
  155. : button(button_), mouse_input(mouse_input_) {}
  156. Input::MotionStatus GetStatus() const override {
  157. return mouse_input->GetMouseState(button).motion;
  158. }
  159. private:
  160. const u32 button;
  161. const MouseInput::Mouse* mouse_input;
  162. };
  163. MouseMotionFactory::MouseMotionFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
  164. : mouse_input(std::move(mouse_input_)) {}
  165. std::unique_ptr<Input::MotionDevice> MouseMotionFactory::Create(
  166. const Common::ParamPackage& params) {
  167. const auto button_id = params.Get("button", 0);
  168. return std::make_unique<MouseMotion>(button_id, mouse_input.get());
  169. }
  170. Common::ParamPackage MouseMotionFactory::GetNextInput() const {
  171. MouseInput::MouseStatus pad;
  172. Common::ParamPackage params;
  173. auto& queue = mouse_input->GetMouseQueue();
  174. while (queue.Pop(pad)) {
  175. // This while loop will break on the earliest detected button
  176. if (pad.button != MouseInput::MouseButton::Undefined) {
  177. params.Set("engine", "mouse");
  178. params.Set("button", static_cast<u16>(pad.button));
  179. return params;
  180. }
  181. }
  182. return params;
  183. }
  184. void MouseMotionFactory::BeginConfiguration() {
  185. polling = true;
  186. mouse_input->BeginConfiguration();
  187. }
  188. void MouseMotionFactory::EndConfiguration() {
  189. polling = false;
  190. mouse_input->EndConfiguration();
  191. }
  192. class MouseTouch final : public Input::TouchDevice {
  193. public:
  194. explicit MouseTouch(u32 button_, const MouseInput::Mouse* mouse_input_)
  195. : button(button_), mouse_input(mouse_input_) {}
  196. Input::TouchStatus GetStatus() const override {
  197. return mouse_input->GetMouseState(button).touch;
  198. }
  199. private:
  200. const u32 button;
  201. const MouseInput::Mouse* mouse_input;
  202. };
  203. MouseTouchFactory::MouseTouchFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
  204. : mouse_input(std::move(mouse_input_)) {}
  205. std::unique_ptr<Input::TouchDevice> MouseTouchFactory::Create(const Common::ParamPackage& params) {
  206. const auto button_id = params.Get("button", 0);
  207. return std::make_unique<MouseTouch>(button_id, mouse_input.get());
  208. }
  209. Common::ParamPackage MouseTouchFactory::GetNextInput() const {
  210. MouseInput::MouseStatus pad;
  211. Common::ParamPackage params;
  212. auto& queue = mouse_input->GetMouseQueue();
  213. while (queue.Pop(pad)) {
  214. // This while loop will break on the earliest detected button
  215. if (pad.button != MouseInput::MouseButton::Undefined) {
  216. params.Set("engine", "mouse");
  217. params.Set("button", static_cast<u16>(pad.button));
  218. return params;
  219. }
  220. }
  221. return params;
  222. }
  223. void MouseTouchFactory::BeginConfiguration() {
  224. polling = true;
  225. mouse_input->BeginConfiguration();
  226. }
  227. void MouseTouchFactory::EndConfiguration() {
  228. polling = false;
  229. mouse_input->EndConfiguration();
  230. }
  231. } // namespace InputCommon