mouse_poller.cpp 9.3 KB

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