mouse.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <thread>
  4. #include <fmt/format.h>
  5. #include <math.h>
  6. #include "common/param_package.h"
  7. #include "common/settings.h"
  8. #include "common/thread.h"
  9. #include "input_common/drivers/mouse.h"
  10. namespace InputCommon {
  11. constexpr int update_time = 10;
  12. constexpr float default_stick_sensitivity = 0.0044f;
  13. constexpr float default_motion_sensitivity = 0.0003f;
  14. constexpr float maximum_rotation_speed = 2.0f;
  15. constexpr int mouse_axis_x = 0;
  16. constexpr int mouse_axis_y = 1;
  17. constexpr int wheel_axis_x = 2;
  18. constexpr int wheel_axis_y = 3;
  19. constexpr PadIdentifier identifier = {
  20. .guid = Common::UUID{},
  21. .port = 0,
  22. .pad = 0,
  23. };
  24. constexpr PadIdentifier motion_identifier = {
  25. .guid = Common::UUID{},
  26. .port = 0,
  27. .pad = 1,
  28. };
  29. constexpr PadIdentifier real_mouse_identifier = {
  30. .guid = Common::UUID{},
  31. .port = 1,
  32. .pad = 0,
  33. };
  34. constexpr PadIdentifier touch_identifier = {
  35. .guid = Common::UUID{},
  36. .port = 2,
  37. .pad = 0,
  38. };
  39. Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
  40. PreSetController(identifier);
  41. PreSetController(real_mouse_identifier);
  42. PreSetController(touch_identifier);
  43. PreSetController(motion_identifier);
  44. // Initialize all mouse axis
  45. PreSetAxis(identifier, mouse_axis_x);
  46. PreSetAxis(identifier, mouse_axis_y);
  47. PreSetAxis(identifier, wheel_axis_x);
  48. PreSetAxis(identifier, wheel_axis_y);
  49. PreSetAxis(real_mouse_identifier, mouse_axis_x);
  50. PreSetAxis(real_mouse_identifier, mouse_axis_y);
  51. PreSetAxis(touch_identifier, mouse_axis_x);
  52. PreSetAxis(touch_identifier, mouse_axis_y);
  53. // Initialize variables
  54. mouse_origin = {};
  55. last_mouse_position = {};
  56. wheel_position = {};
  57. last_mouse_change = {};
  58. last_motion_change = {};
  59. update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); });
  60. }
  61. void Mouse::UpdateThread(std::stop_token stop_token) {
  62. Common::SetCurrentThreadName("Mouse");
  63. while (!stop_token.stop_requested()) {
  64. UpdateStickInput();
  65. UpdateMotionInput();
  66. if (mouse_panning_timeout++ > 20) {
  67. StopPanning();
  68. }
  69. std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
  70. }
  71. }
  72. void Mouse::UpdateStickInput() {
  73. if (!Settings::values.mouse_panning) {
  74. return;
  75. }
  76. const float sensitivity =
  77. Settings::values.mouse_panning_sensitivity.GetValue() * default_stick_sensitivity;
  78. // Slow movement by 4%
  79. last_mouse_change *= 0.96f;
  80. SetAxis(identifier, mouse_axis_x, last_mouse_change.x * sensitivity);
  81. SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity);
  82. }
  83. void Mouse::UpdateMotionInput() {
  84. const float sensitivity =
  85. Settings::values.mouse_panning_sensitivity.GetValue() * default_motion_sensitivity;
  86. const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x +
  87. last_motion_change.y * last_motion_change.y);
  88. if (rotation_velocity > maximum_rotation_speed / sensitivity) {
  89. const float multiplier = maximum_rotation_speed / rotation_velocity / sensitivity;
  90. last_motion_change.x = last_motion_change.x * multiplier;
  91. last_motion_change.y = last_motion_change.y * multiplier;
  92. }
  93. const BasicMotion motion_data{
  94. .gyro_x = last_motion_change.x * sensitivity,
  95. .gyro_y = last_motion_change.y * sensitivity,
  96. .gyro_z = last_motion_change.z * sensitivity,
  97. .accel_x = 0,
  98. .accel_y = 0,
  99. .accel_z = 0,
  100. .delta_timestamp = update_time * 1000,
  101. };
  102. if (Settings::values.mouse_panning) {
  103. last_motion_change.x = 0;
  104. last_motion_change.y = 0;
  105. }
  106. last_motion_change.z = 0;
  107. SetMotion(motion_identifier, 0, motion_data);
  108. }
  109. void Mouse::Move(int x, int y, int center_x, int center_y) {
  110. if (Settings::values.mouse_panning) {
  111. mouse_panning_timeout = 0;
  112. auto mouse_change =
  113. (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>();
  114. last_motion_change += {-mouse_change.y, -mouse_change.x, 0};
  115. const auto move_distance = mouse_change.Length();
  116. if (move_distance == 0) {
  117. return;
  118. }
  119. // Make slow movements at least 3 units on length
  120. if (move_distance < 3.0f) {
  121. // Normalize value
  122. mouse_change /= move_distance;
  123. mouse_change *= 3.0f;
  124. }
  125. // Average mouse movements
  126. last_mouse_change = (last_mouse_change * 0.91f) + (mouse_change * 0.09f);
  127. const auto last_move_distance = last_mouse_change.Length();
  128. // Make fast movements clamp to 8 units on length
  129. if (last_move_distance > 8.0f) {
  130. // Normalize value
  131. last_mouse_change /= last_move_distance;
  132. last_mouse_change *= 8.0f;
  133. }
  134. // Ignore average if it's less than 1 unit and use current movement value
  135. if (last_move_distance < 1.0f) {
  136. last_mouse_change = mouse_change / mouse_change.Length();
  137. }
  138. return;
  139. }
  140. if (button_pressed) {
  141. const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin;
  142. const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.0012f;
  143. SetAxis(identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * sensitivity);
  144. SetAxis(identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * sensitivity);
  145. last_motion_change = {
  146. static_cast<float>(-mouse_move.y) / 50.0f,
  147. static_cast<float>(-mouse_move.x) / 50.0f,
  148. last_motion_change.z,
  149. };
  150. }
  151. }
  152. void Mouse::MouseMove(f32 touch_x, f32 touch_y) {
  153. SetAxis(real_mouse_identifier, mouse_axis_x, touch_x);
  154. SetAxis(real_mouse_identifier, mouse_axis_y, touch_y);
  155. }
  156. void Mouse::TouchMove(f32 touch_x, f32 touch_y) {
  157. SetAxis(touch_identifier, mouse_axis_x, touch_x);
  158. SetAxis(touch_identifier, mouse_axis_y, touch_y);
  159. }
  160. void Mouse::PressButton(int x, int y, MouseButton button) {
  161. SetButton(identifier, static_cast<int>(button), true);
  162. // Set initial analog parameters
  163. mouse_origin = {x, y};
  164. last_mouse_position = {x, y};
  165. button_pressed = true;
  166. }
  167. void Mouse::PressMouseButton(MouseButton button) {
  168. SetButton(real_mouse_identifier, static_cast<int>(button), true);
  169. }
  170. void Mouse::PressTouchButton(f32 touch_x, f32 touch_y, MouseButton button) {
  171. SetAxis(touch_identifier, mouse_axis_x, touch_x);
  172. SetAxis(touch_identifier, mouse_axis_y, touch_y);
  173. SetButton(touch_identifier, static_cast<int>(button), true);
  174. }
  175. void Mouse::ReleaseButton(MouseButton button) {
  176. SetButton(identifier, static_cast<int>(button), false);
  177. SetButton(real_mouse_identifier, static_cast<int>(button), false);
  178. SetButton(touch_identifier, static_cast<int>(button), false);
  179. if (!Settings::values.mouse_panning) {
  180. SetAxis(identifier, mouse_axis_x, 0);
  181. SetAxis(identifier, mouse_axis_y, 0);
  182. }
  183. last_motion_change.x = 0;
  184. last_motion_change.y = 0;
  185. button_pressed = false;
  186. }
  187. void Mouse::MouseWheelChange(int x, int y) {
  188. wheel_position.x += x;
  189. wheel_position.y += y;
  190. last_motion_change.z += static_cast<f32>(y) / 100.0f;
  191. SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x));
  192. SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y));
  193. }
  194. void Mouse::ReleaseAllButtons() {
  195. ResetButtonState();
  196. button_pressed = false;
  197. }
  198. void Mouse::StopPanning() {
  199. last_mouse_change = {};
  200. }
  201. std::vector<Common::ParamPackage> Mouse::GetInputDevices() const {
  202. std::vector<Common::ParamPackage> devices;
  203. devices.emplace_back(Common::ParamPackage{
  204. {"engine", GetEngineName()},
  205. {"display", "Keyboard/Mouse"},
  206. });
  207. return devices;
  208. }
  209. AnalogMapping Mouse::GetAnalogMappingForDevice(
  210. [[maybe_unused]] const Common::ParamPackage& params) {
  211. // Only overwrite different buttons from default
  212. AnalogMapping mapping = {};
  213. Common::ParamPackage right_analog_params;
  214. right_analog_params.Set("engine", GetEngineName());
  215. right_analog_params.Set("axis_x", 0);
  216. right_analog_params.Set("axis_y", 1);
  217. right_analog_params.Set("threshold", 0.5f);
  218. right_analog_params.Set("range", 1.0f);
  219. right_analog_params.Set("deadzone", 0.0f);
  220. mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params));
  221. return mapping;
  222. }
  223. Common::Input::ButtonNames Mouse::GetUIButtonName(const Common::ParamPackage& params) const {
  224. const auto button = static_cast<MouseButton>(params.Get("button", 0));
  225. switch (button) {
  226. case MouseButton::Left:
  227. return Common::Input::ButtonNames::ButtonLeft;
  228. case MouseButton::Right:
  229. return Common::Input::ButtonNames::ButtonRight;
  230. case MouseButton::Wheel:
  231. return Common::Input::ButtonNames::ButtonMouseWheel;
  232. case MouseButton::Backward:
  233. return Common::Input::ButtonNames::ButtonBackward;
  234. case MouseButton::Forward:
  235. return Common::Input::ButtonNames::ButtonForward;
  236. case MouseButton::Task:
  237. return Common::Input::ButtonNames::ButtonTask;
  238. case MouseButton::Extra:
  239. return Common::Input::ButtonNames::ButtonExtra;
  240. case MouseButton::Undefined:
  241. default:
  242. return Common::Input::ButtonNames::Undefined;
  243. }
  244. }
  245. Common::Input::ButtonNames Mouse::GetUIName(const Common::ParamPackage& params) const {
  246. if (params.Has("button")) {
  247. return GetUIButtonName(params);
  248. }
  249. if (params.Has("axis")) {
  250. return Common::Input::ButtonNames::Value;
  251. }
  252. if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) {
  253. return Common::Input::ButtonNames::Engine;
  254. }
  255. if (params.Has("motion")) {
  256. return Common::Input::ButtonNames::Engine;
  257. }
  258. return Common::Input::ButtonNames::Invalid;
  259. }
  260. } // namespace InputCommon