diff options
Diffstat (limited to 'src/input_common/drivers/mouse.cpp')
| -rw-r--r-- | src/input_common/drivers/mouse.cpp | 231 |
1 files changed, 164 insertions, 67 deletions
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index faf9cbdc3..f07cf8a0e 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <thread> | 4 | #include <thread> |
| 5 | #include <fmt/format.h> | 5 | #include <fmt/format.h> |
| 6 | #include <math.h> | ||
| 6 | 7 | ||
| 7 | #include "common/param_package.h" | 8 | #include "common/param_package.h" |
| 8 | #include "common/settings.h" | 9 | #include "common/settings.h" |
| @@ -10,135 +11,232 @@ | |||
| 10 | #include "input_common/drivers/mouse.h" | 11 | #include "input_common/drivers/mouse.h" |
| 11 | 12 | ||
| 12 | namespace InputCommon { | 13 | namespace InputCommon { |
| 14 | constexpr int update_time = 10; | ||
| 15 | constexpr float default_stick_sensitivity = 0.0044f; | ||
| 16 | constexpr float default_motion_sensitivity = 0.0003f; | ||
| 17 | constexpr float maximum_rotation_speed = 2.0f; | ||
| 13 | constexpr int mouse_axis_x = 0; | 18 | constexpr int mouse_axis_x = 0; |
| 14 | constexpr int mouse_axis_y = 1; | 19 | constexpr int mouse_axis_y = 1; |
| 15 | constexpr int wheel_axis_x = 2; | 20 | constexpr int wheel_axis_x = 2; |
| 16 | constexpr int wheel_axis_y = 3; | 21 | constexpr int wheel_axis_y = 3; |
| 17 | constexpr int motion_wheel_y = 4; | ||
| 18 | constexpr int touch_axis_x = 10; | ||
| 19 | constexpr int touch_axis_y = 11; | ||
| 20 | constexpr PadIdentifier identifier = { | 22 | constexpr PadIdentifier identifier = { |
| 21 | .guid = Common::UUID{}, | 23 | .guid = Common::UUID{}, |
| 22 | .port = 0, | 24 | .port = 0, |
| 23 | .pad = 0, | 25 | .pad = 0, |
| 24 | }; | 26 | }; |
| 25 | 27 | ||
| 28 | constexpr PadIdentifier motion_identifier = { | ||
| 29 | .guid = Common::UUID{}, | ||
| 30 | .port = 0, | ||
| 31 | .pad = 1, | ||
| 32 | }; | ||
| 33 | |||
| 34 | constexpr PadIdentifier real_mouse_identifier = { | ||
| 35 | .guid = Common::UUID{}, | ||
| 36 | .port = 1, | ||
| 37 | .pad = 0, | ||
| 38 | }; | ||
| 39 | |||
| 40 | constexpr PadIdentifier touch_identifier = { | ||
| 41 | .guid = Common::UUID{}, | ||
| 42 | .port = 2, | ||
| 43 | .pad = 0, | ||
| 44 | }; | ||
| 45 | |||
| 26 | Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) { | 46 | Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) { |
| 27 | PreSetController(identifier); | 47 | PreSetController(identifier); |
| 48 | PreSetController(real_mouse_identifier); | ||
| 49 | PreSetController(touch_identifier); | ||
| 50 | PreSetController(motion_identifier); | ||
| 51 | |||
| 52 | // Initialize all mouse axis | ||
| 28 | PreSetAxis(identifier, mouse_axis_x); | 53 | PreSetAxis(identifier, mouse_axis_x); |
| 29 | PreSetAxis(identifier, mouse_axis_y); | 54 | PreSetAxis(identifier, mouse_axis_y); |
| 30 | PreSetAxis(identifier, wheel_axis_x); | 55 | PreSetAxis(identifier, wheel_axis_x); |
| 31 | PreSetAxis(identifier, wheel_axis_y); | 56 | PreSetAxis(identifier, wheel_axis_y); |
| 32 | PreSetAxis(identifier, motion_wheel_y); | 57 | PreSetAxis(real_mouse_identifier, mouse_axis_x); |
| 33 | PreSetAxis(identifier, touch_axis_x); | 58 | PreSetAxis(real_mouse_identifier, mouse_axis_y); |
| 34 | PreSetAxis(identifier, touch_axis_y); | 59 | PreSetAxis(touch_identifier, mouse_axis_x); |
| 60 | PreSetAxis(touch_identifier, mouse_axis_y); | ||
| 61 | |||
| 62 | // Initialize variables | ||
| 63 | mouse_origin = {}; | ||
| 64 | last_mouse_position = {}; | ||
| 65 | wheel_position = {}; | ||
| 66 | last_mouse_change = {}; | ||
| 67 | last_motion_change = {}; | ||
| 68 | |||
| 35 | update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); }); | 69 | update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); }); |
| 36 | } | 70 | } |
| 37 | 71 | ||
| 38 | void Mouse::UpdateThread(std::stop_token stop_token) { | 72 | void Mouse::UpdateThread(std::stop_token stop_token) { |
| 39 | Common::SetCurrentThreadName("Mouse"); | 73 | Common::SetCurrentThreadName("Mouse"); |
| 40 | constexpr int update_time = 10; | 74 | |
| 41 | while (!stop_token.stop_requested()) { | 75 | while (!stop_token.stop_requested()) { |
| 42 | if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) { | 76 | UpdateStickInput(); |
| 43 | // Slow movement by 4% | 77 | UpdateMotionInput(); |
| 44 | last_mouse_change *= 0.96f; | 78 | |
| 45 | const float sensitivity = | ||
| 46 | Settings::values.mouse_panning_sensitivity.GetValue() * 0.022f; | ||
| 47 | SetAxis(identifier, mouse_axis_x, last_mouse_change.x * sensitivity); | ||
| 48 | SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity); | ||
| 49 | } | ||
| 50 | |||
| 51 | SetAxis(identifier, motion_wheel_y, 0.0f); | ||
| 52 | |||
| 53 | if (mouse_panning_timout++ > 20) { | ||
| 54 | StopPanning(); | ||
| 55 | } | ||
| 56 | std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); | 79 | std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); |
| 57 | } | 80 | } |
| 58 | } | 81 | } |
| 59 | 82 | ||
| 60 | void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int center_y) { | 83 | void Mouse::UpdateStickInput() { |
| 61 | // If native mouse is enabled just set the screen coordinates | 84 | if (!Settings::values.mouse_panning) { |
| 62 | if (Settings::values.mouse_enabled) { | ||
| 63 | SetAxis(identifier, mouse_axis_x, touch_x); | ||
| 64 | SetAxis(identifier, mouse_axis_y, touch_y); | ||
| 65 | return; | 85 | return; |
| 66 | } | 86 | } |
| 67 | 87 | ||
| 68 | SetAxis(identifier, touch_axis_x, touch_x); | 88 | const float length = last_mouse_change.Length(); |
| 69 | SetAxis(identifier, touch_axis_y, touch_y); | ||
| 70 | 89 | ||
| 71 | if (Settings::values.mouse_panning) { | 90 | // Prevent input from exceeding the max range (1.0f) too much, |
| 72 | auto mouse_change = | 91 | // but allow some room to make it easier to sustain |
| 73 | (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>(); | 92 | if (length > 1.2f) { |
| 74 | mouse_panning_timout = 0; | 93 | last_mouse_change /= length; |
| 94 | last_mouse_change *= 1.2f; | ||
| 95 | } | ||
| 96 | |||
| 97 | auto mouse_change = last_mouse_change; | ||
| 98 | |||
| 99 | // Bind the mouse change to [0 <= deadzone_counterweight <= 1,1] | ||
| 100 | if (length < 1.0f) { | ||
| 101 | const float deadzone_h_counterweight = | ||
| 102 | Settings::values.mouse_panning_deadzone_x_counterweight.GetValue(); | ||
| 103 | const float deadzone_v_counterweight = | ||
| 104 | Settings::values.mouse_panning_deadzone_y_counterweight.GetValue(); | ||
| 105 | mouse_change /= length; | ||
| 106 | mouse_change.x *= length + (1 - length) * deadzone_h_counterweight * 0.01f; | ||
| 107 | mouse_change.y *= length + (1 - length) * deadzone_v_counterweight * 0.01f; | ||
| 108 | } | ||
| 109 | |||
| 110 | SetAxis(identifier, mouse_axis_x, mouse_change.x); | ||
| 111 | SetAxis(identifier, mouse_axis_y, -mouse_change.y); | ||
| 112 | |||
| 113 | // Decay input over time | ||
| 114 | const float clamped_length = std::min(1.0f, length); | ||
| 115 | const float decay_strength = Settings::values.mouse_panning_decay_strength.GetValue(); | ||
| 116 | const float decay = 1 - clamped_length * clamped_length * decay_strength * 0.01f; | ||
| 117 | const float min_decay = Settings::values.mouse_panning_min_decay.GetValue(); | ||
| 118 | const float clamped_decay = std::min(1 - min_decay / 100.0f, decay); | ||
| 119 | last_mouse_change *= clamped_decay; | ||
| 120 | } | ||
| 75 | 121 | ||
| 76 | const auto move_distance = mouse_change.Length(); | 122 | void Mouse::UpdateMotionInput() { |
| 77 | if (move_distance == 0) { | 123 | // This may need its own sensitivity instead of using the average |
| 78 | return; | 124 | const float sensitivity = (Settings::values.mouse_panning_x_sensitivity.GetValue() + |
| 79 | } | 125 | Settings::values.mouse_panning_y_sensitivity.GetValue()) / |
| 126 | 2.0f * default_motion_sensitivity; | ||
| 80 | 127 | ||
| 81 | // Make slow movements at least 3 units on lenght | 128 | const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x + |
| 82 | if (move_distance < 3.0f) { | 129 | last_motion_change.y * last_motion_change.y); |
| 83 | // Normalize value | ||
| 84 | mouse_change /= move_distance; | ||
| 85 | mouse_change *= 3.0f; | ||
| 86 | } | ||
| 87 | 130 | ||
| 88 | // Average mouse movements | 131 | if (rotation_velocity > maximum_rotation_speed / sensitivity) { |
| 89 | last_mouse_change = (last_mouse_change * 0.91f) + (mouse_change * 0.09f); | 132 | const float multiplier = maximum_rotation_speed / rotation_velocity / sensitivity; |
| 133 | last_motion_change.x = last_motion_change.x * multiplier; | ||
| 134 | last_motion_change.y = last_motion_change.y * multiplier; | ||
| 135 | } | ||
| 90 | 136 | ||
| 91 | const auto last_move_distance = last_mouse_change.Length(); | 137 | const BasicMotion motion_data{ |
| 138 | .gyro_x = last_motion_change.x * sensitivity, | ||
| 139 | .gyro_y = last_motion_change.y * sensitivity, | ||
| 140 | .gyro_z = last_motion_change.z * sensitivity, | ||
| 141 | .accel_x = 0, | ||
| 142 | .accel_y = 0, | ||
| 143 | .accel_z = 0, | ||
| 144 | .delta_timestamp = update_time * 1000, | ||
| 145 | }; | ||
| 92 | 146 | ||
| 93 | // Make fast movements clamp to 8 units on lenght | 147 | if (Settings::values.mouse_panning) { |
| 94 | if (last_move_distance > 8.0f) { | 148 | last_motion_change.x = 0; |
| 95 | // Normalize value | 149 | last_motion_change.y = 0; |
| 96 | last_mouse_change /= last_move_distance; | 150 | } |
| 97 | last_mouse_change *= 8.0f; | 151 | last_motion_change.z = 0; |
| 98 | } | ||
| 99 | 152 | ||
| 100 | // Ignore average if it's less than 1 unit and use current movement value | 153 | SetMotion(motion_identifier, 0, motion_data); |
| 101 | if (last_move_distance < 1.0f) { | 154 | } |
| 102 | last_mouse_change = mouse_change / mouse_change.Length(); | 155 | |
| 103 | } | 156 | void Mouse::Move(int x, int y, int center_x, int center_y) { |
| 157 | if (Settings::values.mouse_panning) { | ||
| 158 | const auto mouse_change = | ||
| 159 | (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>(); | ||
| 160 | const float x_sensitivity = | ||
| 161 | Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity; | ||
| 162 | const float y_sensitivity = | ||
| 163 | Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity; | ||
| 164 | |||
| 165 | last_motion_change += {-mouse_change.y, -mouse_change.x, 0}; | ||
| 166 | last_mouse_change.x += mouse_change.x * x_sensitivity * 0.09f; | ||
| 167 | last_mouse_change.y += mouse_change.y * y_sensitivity * 0.09f; | ||
| 104 | 168 | ||
| 105 | return; | 169 | return; |
| 106 | } | 170 | } |
| 107 | 171 | ||
| 108 | if (button_pressed) { | 172 | if (button_pressed) { |
| 109 | const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin; | 173 | const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin; |
| 110 | const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.0012f; | 174 | const float x_sensitivity = Settings::values.mouse_panning_x_sensitivity.GetValue(); |
| 111 | SetAxis(identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * sensitivity); | 175 | const float y_sensitivity = Settings::values.mouse_panning_y_sensitivity.GetValue(); |
| 112 | SetAxis(identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * sensitivity); | 176 | SetAxis(identifier, mouse_axis_x, |
| 177 | static_cast<float>(mouse_move.x) * x_sensitivity * 0.0012f); | ||
| 178 | SetAxis(identifier, mouse_axis_y, | ||
| 179 | static_cast<float>(-mouse_move.y) * y_sensitivity * 0.0012f); | ||
| 180 | |||
| 181 | last_motion_change = { | ||
| 182 | static_cast<float>(-mouse_move.y) / 50.0f, | ||
| 183 | static_cast<float>(-mouse_move.x) / 50.0f, | ||
| 184 | last_motion_change.z, | ||
| 185 | }; | ||
| 113 | } | 186 | } |
| 114 | } | 187 | } |
| 115 | 188 | ||
| 116 | void Mouse::PressButton(int x, int y, f32 touch_x, f32 touch_y, MouseButton button) { | 189 | void Mouse::MouseMove(f32 touch_x, f32 touch_y) { |
| 117 | SetAxis(identifier, touch_axis_x, touch_x); | 190 | SetAxis(real_mouse_identifier, mouse_axis_x, touch_x); |
| 118 | SetAxis(identifier, touch_axis_y, touch_y); | 191 | SetAxis(real_mouse_identifier, mouse_axis_y, touch_y); |
| 192 | } | ||
| 193 | |||
| 194 | void Mouse::TouchMove(f32 touch_x, f32 touch_y) { | ||
| 195 | SetAxis(touch_identifier, mouse_axis_x, touch_x); | ||
| 196 | SetAxis(touch_identifier, mouse_axis_y, touch_y); | ||
| 197 | } | ||
| 198 | |||
| 199 | void Mouse::PressButton(int x, int y, MouseButton button) { | ||
| 119 | SetButton(identifier, static_cast<int>(button), true); | 200 | SetButton(identifier, static_cast<int>(button), true); |
| 201 | |||
| 120 | // Set initial analog parameters | 202 | // Set initial analog parameters |
| 121 | mouse_origin = {x, y}; | 203 | mouse_origin = {x, y}; |
| 122 | last_mouse_position = {x, y}; | 204 | last_mouse_position = {x, y}; |
| 123 | button_pressed = true; | 205 | button_pressed = true; |
| 124 | } | 206 | } |
| 125 | 207 | ||
| 208 | void Mouse::PressMouseButton(MouseButton button) { | ||
| 209 | SetButton(real_mouse_identifier, static_cast<int>(button), true); | ||
| 210 | } | ||
| 211 | |||
| 212 | void Mouse::PressTouchButton(f32 touch_x, f32 touch_y, MouseButton button) { | ||
| 213 | SetAxis(touch_identifier, mouse_axis_x, touch_x); | ||
| 214 | SetAxis(touch_identifier, mouse_axis_y, touch_y); | ||
| 215 | SetButton(touch_identifier, static_cast<int>(button), true); | ||
| 216 | } | ||
| 217 | |||
| 126 | void Mouse::ReleaseButton(MouseButton button) { | 218 | void Mouse::ReleaseButton(MouseButton button) { |
| 127 | SetButton(identifier, static_cast<int>(button), false); | 219 | SetButton(identifier, static_cast<int>(button), false); |
| 220 | SetButton(real_mouse_identifier, static_cast<int>(button), false); | ||
| 221 | SetButton(touch_identifier, static_cast<int>(button), false); | ||
| 128 | 222 | ||
| 129 | if (!Settings::values.mouse_panning && !Settings::values.mouse_enabled) { | 223 | if (!Settings::values.mouse_panning) { |
| 130 | SetAxis(identifier, mouse_axis_x, 0); | 224 | SetAxis(identifier, mouse_axis_x, 0); |
| 131 | SetAxis(identifier, mouse_axis_y, 0); | 225 | SetAxis(identifier, mouse_axis_y, 0); |
| 132 | } | 226 | } |
| 227 | |||
| 228 | last_motion_change.x = 0; | ||
| 229 | last_motion_change.y = 0; | ||
| 230 | |||
| 133 | button_pressed = false; | 231 | button_pressed = false; |
| 134 | } | 232 | } |
| 135 | 233 | ||
| 136 | void Mouse::MouseWheelChange(int x, int y) { | 234 | void Mouse::MouseWheelChange(int x, int y) { |
| 137 | wheel_position.x += x; | 235 | wheel_position.x += x; |
| 138 | wheel_position.y += y; | 236 | wheel_position.y += y; |
| 237 | last_motion_change.z += static_cast<f32>(y) / 100.0f; | ||
| 139 | SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x)); | 238 | SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x)); |
| 140 | SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y)); | 239 | SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y)); |
| 141 | SetAxis(identifier, motion_wheel_y, static_cast<f32>(y) / 100.0f); | ||
| 142 | } | 240 | } |
| 143 | 241 | ||
| 144 | void Mouse::ReleaseAllButtons() { | 242 | void Mouse::ReleaseAllButtons() { |
| @@ -146,10 +244,6 @@ void Mouse::ReleaseAllButtons() { | |||
| 146 | button_pressed = false; | 244 | button_pressed = false; |
| 147 | } | 245 | } |
| 148 | 246 | ||
| 149 | void Mouse::StopPanning() { | ||
| 150 | last_mouse_change = {}; | ||
| 151 | } | ||
| 152 | |||
| 153 | std::vector<Common::ParamPackage> Mouse::GetInputDevices() const { | 247 | std::vector<Common::ParamPackage> Mouse::GetInputDevices() const { |
| 154 | std::vector<Common::ParamPackage> devices; | 248 | std::vector<Common::ParamPackage> devices; |
| 155 | devices.emplace_back(Common::ParamPackage{ | 249 | devices.emplace_back(Common::ParamPackage{ |
| @@ -207,6 +301,9 @@ Common::Input::ButtonNames Mouse::GetUIName(const Common::ParamPackage& params) | |||
| 207 | if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) { | 301 | if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) { |
| 208 | return Common::Input::ButtonNames::Engine; | 302 | return Common::Input::ButtonNames::Engine; |
| 209 | } | 303 | } |
| 304 | if (params.Has("motion")) { | ||
| 305 | return Common::Input::ButtonNames::Engine; | ||
| 306 | } | ||
| 210 | 307 | ||
| 211 | return Common::Input::ButtonNames::Invalid; | 308 | return Common::Input::ButtonNames::Invalid; |
| 212 | } | 309 | } |