diff options
Diffstat (limited to 'src/input_common')
| -rw-r--r-- | src/input_common/gcadapter/gc_adapter.cpp | 6 | ||||
| -rw-r--r-- | src/input_common/gcadapter/gc_adapter.h | 4 | ||||
| -rw-r--r-- | src/input_common/gcadapter/gc_poller.cpp | 50 | ||||
| -rw-r--r-- | src/input_common/gcadapter/gc_poller.h | 11 | ||||
| -rw-r--r-- | src/input_common/main.cpp | 15 | ||||
| -rw-r--r-- | src/input_common/motion_input.h | 23 | ||||
| -rw-r--r-- | src/input_common/sdl/sdl_impl.cpp | 137 | ||||
| -rw-r--r-- | src/input_common/sdl/sdl_impl.h | 2 | ||||
| -rw-r--r-- | src/input_common/settings.cpp | 21 | ||||
| -rw-r--r-- | src/input_common/settings.h | 35 | ||||
| -rw-r--r-- | src/input_common/udp/client.cpp | 2 |
11 files changed, 188 insertions, 118 deletions
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp index b912188b6..d80195c82 100644 --- a/src/input_common/gcadapter/gc_adapter.cpp +++ b/src/input_common/gcadapter/gc_adapter.cpp | |||
| @@ -230,10 +230,8 @@ void Adapter::SendVibrations() { | |||
| 230 | vibration_changed = false; | 230 | vibration_changed = false; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | bool Adapter::RumblePlay(std::size_t port, f32 amplitude) { | 233 | bool Adapter::RumblePlay(std::size_t port, u8 amplitude) { |
| 234 | amplitude = std::clamp(amplitude, 0.0f, 1.0f); | 234 | pads[port].rumble_amplitude = amplitude; |
| 235 | const auto raw_amp = static_cast<u8>(amplitude * 0x8); | ||
| 236 | pads[port].rumble_amplitude = raw_amp; | ||
| 237 | 235 | ||
| 238 | return rumble_enabled; | 236 | return rumble_enabled; |
| 239 | } | 237 | } |
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h index d28dcfad3..f1256c9da 100644 --- a/src/input_common/gcadapter/gc_adapter.h +++ b/src/input_common/gcadapter/gc_adapter.h | |||
| @@ -77,8 +77,8 @@ public: | |||
| 77 | Adapter(); | 77 | Adapter(); |
| 78 | ~Adapter(); | 78 | ~Adapter(); |
| 79 | 79 | ||
| 80 | /// Request a vibration for a controlelr | 80 | /// Request a vibration for a controller |
| 81 | bool RumblePlay(std::size_t port, f32 amplitude); | 81 | bool RumblePlay(std::size_t port, u8 amplitude); |
| 82 | 82 | ||
| 83 | /// Used for polling | 83 | /// Used for polling |
| 84 | void BeginConfiguration(); | 84 | void BeginConfiguration(); |
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp index 6bd6f57fc..d95574bb5 100644 --- a/src/input_common/gcadapter/gc_poller.cpp +++ b/src/input_common/gcadapter/gc_poller.cpp | |||
| @@ -15,7 +15,7 @@ namespace InputCommon { | |||
| 15 | 15 | ||
| 16 | class GCButton final : public Input::ButtonDevice { | 16 | class GCButton final : public Input::ButtonDevice { |
| 17 | public: | 17 | public: |
| 18 | explicit GCButton(u32 port_, s32 button_, GCAdapter::Adapter* adapter) | 18 | explicit GCButton(u32 port_, s32 button_, const GCAdapter::Adapter* adapter) |
| 19 | : port(port_), button(button_), gcadapter(adapter) {} | 19 | : port(port_), button(button_), gcadapter(adapter) {} |
| 20 | 20 | ||
| 21 | ~GCButton() override; | 21 | ~GCButton() override; |
| @@ -27,18 +27,10 @@ public: | |||
| 27 | return false; | 27 | return false; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { | ||
| 31 | const float amplitude = amp_high + amp_low > 2.0f ? 1.0f : (amp_high + amp_low) * 0.5f; | ||
| 32 | const auto new_amp = | ||
| 33 | static_cast<f32>(pow(amplitude, 0.5f) * (3.0f - 2.0f * pow(amplitude, 0.15f))); | ||
| 34 | |||
| 35 | return gcadapter->RumblePlay(port, new_amp); | ||
| 36 | } | ||
| 37 | |||
| 38 | private: | 30 | private: |
| 39 | const u32 port; | 31 | const u32 port; |
| 40 | const s32 button; | 32 | const s32 button; |
| 41 | GCAdapter::Adapter* gcadapter; | 33 | const GCAdapter::Adapter* gcadapter; |
| 42 | }; | 34 | }; |
| 43 | 35 | ||
| 44 | class GCAxisButton final : public Input::ButtonDevice { | 36 | class GCAxisButton final : public Input::ButtonDevice { |
| @@ -299,4 +291,42 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() { | |||
| 299 | return params; | 291 | return params; |
| 300 | } | 292 | } |
| 301 | 293 | ||
| 294 | class GCVibration final : public Input::VibrationDevice { | ||
| 295 | public: | ||
| 296 | explicit GCVibration(u32 port_, GCAdapter::Adapter* adapter) | ||
| 297 | : port(port_), gcadapter(adapter) {} | ||
| 298 | |||
| 299 | u8 GetStatus() const override { | ||
| 300 | return gcadapter->RumblePlay(port, 0); | ||
| 301 | } | ||
| 302 | |||
| 303 | bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override { | ||
| 304 | const auto mean_amplitude = (amp_low + amp_high) * 0.5f; | ||
| 305 | const auto processed_amplitude = | ||
| 306 | static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8); | ||
| 307 | |||
| 308 | return gcadapter->RumblePlay(port, processed_amplitude); | ||
| 309 | } | ||
| 310 | |||
| 311 | private: | ||
| 312 | const u32 port; | ||
| 313 | GCAdapter::Adapter* gcadapter; | ||
| 314 | }; | ||
| 315 | |||
| 316 | /// An vibration device factory that creates vibration devices from GC Adapter | ||
| 317 | GCVibrationFactory::GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_) | ||
| 318 | : adapter(std::move(adapter_)) {} | ||
| 319 | |||
| 320 | /** | ||
| 321 | * Creates a vibration device from a joystick | ||
| 322 | * @param params contains parameters for creating the device: | ||
| 323 | * - "port": the nth gcpad on the adapter | ||
| 324 | */ | ||
| 325 | std::unique_ptr<Input::VibrationDevice> GCVibrationFactory::Create( | ||
| 326 | const Common::ParamPackage& params) { | ||
| 327 | const auto port = static_cast<u32>(params.Get("port", 0)); | ||
| 328 | |||
| 329 | return std::make_unique<GCVibration>(port, adapter.get()); | ||
| 330 | } | ||
| 331 | |||
| 302 | } // namespace InputCommon | 332 | } // namespace InputCommon |
diff --git a/src/input_common/gcadapter/gc_poller.h b/src/input_common/gcadapter/gc_poller.h index 0527f328f..d1271e3ea 100644 --- a/src/input_common/gcadapter/gc_poller.h +++ b/src/input_common/gcadapter/gc_poller.h | |||
| @@ -64,4 +64,15 @@ private: | |||
| 64 | bool polling = false; | 64 | bool polling = false; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | /// A vibration device factory creates vibration devices from GC Adapter | ||
| 68 | class GCVibrationFactory final : public Input::Factory<Input::VibrationDevice> { | ||
| 69 | public: | ||
| 70 | explicit GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_); | ||
| 71 | |||
| 72 | std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override; | ||
| 73 | |||
| 74 | private: | ||
| 75 | std::shared_ptr<GCAdapter::Adapter> adapter; | ||
| 76 | }; | ||
| 77 | |||
| 67 | } // namespace InputCommon | 78 | } // namespace InputCommon |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index d32fd8b81..e59ad4ff5 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -28,6 +28,8 @@ struct InputSubsystem::Impl { | |||
| 28 | Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); | 28 | Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); |
| 29 | gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); | 29 | gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); |
| 30 | Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); | 30 | Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); |
| 31 | gcvibration = std::make_shared<GCVibrationFactory>(gcadapter); | ||
| 32 | Input::RegisterFactory<Input::VibrationDevice>("gcpad", gcvibration); | ||
| 31 | 33 | ||
| 32 | keyboard = std::make_shared<Keyboard>(); | 34 | keyboard = std::make_shared<Keyboard>(); |
| 33 | Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); | 35 | Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); |
| @@ -64,9 +66,11 @@ struct InputSubsystem::Impl { | |||
| 64 | #endif | 66 | #endif |
| 65 | Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); | 67 | Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); |
| 66 | Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); | 68 | Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); |
| 69 | Input::UnregisterFactory<Input::VibrationDevice>("gcpad"); | ||
| 67 | 70 | ||
| 68 | gcbuttons.reset(); | 71 | gcbuttons.reset(); |
| 69 | gcanalog.reset(); | 72 | gcanalog.reset(); |
| 73 | gcvibration.reset(); | ||
| 70 | 74 | ||
| 71 | Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); | 75 | Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); |
| 72 | Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp"); | 76 | Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp"); |
| @@ -78,7 +82,7 @@ struct InputSubsystem::Impl { | |||
| 78 | [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { | 82 | [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { |
| 79 | std::vector<Common::ParamPackage> devices = { | 83 | std::vector<Common::ParamPackage> devices = { |
| 80 | Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, | 84 | Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, |
| 81 | Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}}, | 85 | Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "keyboard"}}, |
| 82 | }; | 86 | }; |
| 83 | #ifdef HAVE_SDL2 | 87 | #ifdef HAVE_SDL2 |
| 84 | auto sdl_devices = sdl->GetInputDevices(); | 88 | auto sdl_devices = sdl->GetInputDevices(); |
| @@ -96,10 +100,6 @@ struct InputSubsystem::Impl { | |||
| 96 | if (!params.Has("class") || params.Get("class", "") == "any") { | 100 | if (!params.Has("class") || params.Get("class", "") == "any") { |
| 97 | return {}; | 101 | return {}; |
| 98 | } | 102 | } |
| 99 | if (params.Get("class", "") == "key") { | ||
| 100 | // TODO consider returning the SDL key codes for the default keybindings | ||
| 101 | return {}; | ||
| 102 | } | ||
| 103 | if (params.Get("class", "") == "gcpad") { | 103 | if (params.Get("class", "") == "gcpad") { |
| 104 | return gcadapter->GetAnalogMappingForDevice(params); | 104 | return gcadapter->GetAnalogMappingForDevice(params); |
| 105 | } | 105 | } |
| @@ -116,10 +116,6 @@ struct InputSubsystem::Impl { | |||
| 116 | if (!params.Has("class") || params.Get("class", "") == "any") { | 116 | if (!params.Has("class") || params.Get("class", "") == "any") { |
| 117 | return {}; | 117 | return {}; |
| 118 | } | 118 | } |
| 119 | if (params.Get("class", "") == "key") { | ||
| 120 | // TODO consider returning the SDL key codes for the default keybindings | ||
| 121 | return {}; | ||
| 122 | } | ||
| 123 | if (params.Get("class", "") == "gcpad") { | 119 | if (params.Get("class", "") == "gcpad") { |
| 124 | return gcadapter->GetButtonMappingForDevice(params); | 120 | return gcadapter->GetButtonMappingForDevice(params); |
| 125 | } | 121 | } |
| @@ -150,6 +146,7 @@ struct InputSubsystem::Impl { | |||
| 150 | #endif | 146 | #endif |
| 151 | std::shared_ptr<GCButtonFactory> gcbuttons; | 147 | std::shared_ptr<GCButtonFactory> gcbuttons; |
| 152 | std::shared_ptr<GCAnalogFactory> gcanalog; | 148 | std::shared_ptr<GCAnalogFactory> gcanalog; |
| 149 | std::shared_ptr<GCVibrationFactory> gcvibration; | ||
| 153 | std::shared_ptr<UDPMotionFactory> udpmotion; | 150 | std::shared_ptr<UDPMotionFactory> udpmotion; |
| 154 | std::shared_ptr<UDPTouchFactory> udptouch; | 151 | std::shared_ptr<UDPTouchFactory> udptouch; |
| 155 | std::shared_ptr<CemuhookUDP::Client> udp; | 152 | std::shared_ptr<CemuhookUDP::Client> udp; |
diff --git a/src/input_common/motion_input.h b/src/input_common/motion_input.h index abb957f04..efe74cf19 100644 --- a/src/input_common/motion_input.h +++ b/src/input_common/motion_input.h | |||
| @@ -13,7 +13,7 @@ namespace InputCommon { | |||
| 13 | 13 | ||
| 14 | class MotionInput { | 14 | class MotionInput { |
| 15 | public: | 15 | public: |
| 16 | MotionInput(f32 new_kp, f32 new_ki, f32 new_kd); | 16 | explicit MotionInput(f32 new_kp, f32 new_ki, f32 new_kd); |
| 17 | 17 | ||
| 18 | MotionInput(const MotionInput&) = default; | 18 | MotionInput(const MotionInput&) = default; |
| 19 | MotionInput& operator=(const MotionInput&) = default; | 19 | MotionInput& operator=(const MotionInput&) = default; |
| @@ -33,16 +33,17 @@ public: | |||
| 33 | void UpdateRotation(u64 elapsed_time); | 33 | void UpdateRotation(u64 elapsed_time); |
| 34 | void UpdateOrientation(u64 elapsed_time); | 34 | void UpdateOrientation(u64 elapsed_time); |
| 35 | 35 | ||
| 36 | std::array<Common::Vec3f, 3> GetOrientation() const; | 36 | [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const; |
| 37 | Common::Vec3f GetAcceleration() const; | 37 | [[nodiscard]] Common::Vec3f GetAcceleration() const; |
| 38 | Common::Vec3f GetGyroscope() const; | 38 | [[nodiscard]] Common::Vec3f GetGyroscope() const; |
| 39 | Common::Vec3f GetRotations() const; | 39 | [[nodiscard]] Common::Vec3f GetRotations() const; |
| 40 | Common::Quaternion<f32> GetQuaternion() const; | 40 | [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const; |
| 41 | Input::MotionStatus GetMotion() const; | 41 | [[nodiscard]] Input::MotionStatus GetMotion() const; |
| 42 | Input::MotionStatus GetRandomMotion(int accel_magnitude, int gyro_magnitude) const; | 42 | [[nodiscard]] Input::MotionStatus GetRandomMotion(int accel_magnitude, |
| 43 | 43 | int gyro_magnitude) const; | |
| 44 | bool IsMoving(f32 sensitivity) const; | 44 | |
| 45 | bool IsCalibrated(f32 sensitivity) const; | 45 | [[nodiscard]] bool IsMoving(f32 sensitivity) const; |
| 46 | [[nodiscard]] bool IsCalibrated(f32 sensitivity) const; | ||
| 46 | 47 | ||
| 47 | private: | 48 | private: |
| 48 | void ResetOrientation(); | 49 | void ResetOrientation(); |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 10883e2d9..c395d96cf 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -80,30 +80,13 @@ public: | |||
| 80 | return static_cast<float>(state.axes.at(axis)) / (32767.0f * range); | 80 | return static_cast<float>(state.axes.at(axis)) / (32767.0f * range); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | bool RumblePlay(f32 amp_low, f32 amp_high, u32 time) { | 83 | bool RumblePlay(u16 amp_low, u16 amp_high) { |
| 84 | const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF); | 84 | if (sdl_controller) { |
| 85 | const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF); | 85 | return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; |
| 86 | // Lower drastically the number of state changes | 86 | } else if (sdl_joystick) { |
| 87 | if (raw_amp_low >> 11 == last_state_rumble_low >> 11 && | 87 | return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0; |
| 88 | raw_amp_high >> 11 == last_state_rumble_high >> 11) { | ||
| 89 | if (raw_amp_low + raw_amp_high != 0 || | ||
| 90 | last_state_rumble_low + last_state_rumble_high == 0) { | ||
| 91 | return false; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | // Don't change state if last vibration was < 20ms | ||
| 95 | const auto now = std::chrono::system_clock::now(); | ||
| 96 | if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) < | ||
| 97 | std::chrono::milliseconds(20)) { | ||
| 98 | return raw_amp_low + raw_amp_high == 0; | ||
| 99 | } | 88 | } |
| 100 | 89 | ||
| 101 | last_vibration = now; | ||
| 102 | last_state_rumble_low = raw_amp_low; | ||
| 103 | last_state_rumble_high = raw_amp_high; | ||
| 104 | if (sdl_joystick) { | ||
| 105 | SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time); | ||
| 106 | } | ||
| 107 | return false; | 90 | return false; |
| 108 | } | 91 | } |
| 109 | 92 | ||
| @@ -172,9 +155,6 @@ private: | |||
| 172 | } state; | 155 | } state; |
| 173 | std::string guid; | 156 | std::string guid; |
| 174 | int port; | 157 | int port; |
| 175 | u16 last_state_rumble_high = 0; | ||
| 176 | u16 last_state_rumble_low = 0; | ||
| 177 | std::chrono::time_point<std::chrono::system_clock> last_vibration; | ||
| 178 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; | 158 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; |
| 179 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | 159 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; |
| 180 | mutable std::mutex mutex; | 160 | mutable std::mutex mutex; |
| @@ -327,12 +307,6 @@ public: | |||
| 327 | return joystick->GetButton(button); | 307 | return joystick->GetButton(button); |
| 328 | } | 308 | } |
| 329 | 309 | ||
| 330 | bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { | ||
| 331 | const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f)); | ||
| 332 | const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f)); | ||
| 333 | return joystick->RumblePlay(new_amp_low, new_amp_high, 250); | ||
| 334 | } | ||
| 335 | |||
| 336 | private: | 310 | private: |
| 337 | std::shared_ptr<SDLJoystick> joystick; | 311 | std::shared_ptr<SDLJoystick> joystick; |
| 338 | int button; | 312 | int button; |
| @@ -416,6 +390,31 @@ private: | |||
| 416 | const float range; | 390 | const float range; |
| 417 | }; | 391 | }; |
| 418 | 392 | ||
| 393 | class SDLVibration final : public Input::VibrationDevice { | ||
| 394 | public: | ||
| 395 | explicit SDLVibration(std::shared_ptr<SDLJoystick> joystick_) | ||
| 396 | : joystick(std::move(joystick_)) {} | ||
| 397 | |||
| 398 | u8 GetStatus() const override { | ||
| 399 | joystick->RumblePlay(1, 1); | ||
| 400 | return joystick->RumblePlay(0, 0); | ||
| 401 | } | ||
| 402 | |||
| 403 | bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override { | ||
| 404 | const auto process_amplitude = [](f32 amplitude) { | ||
| 405 | return static_cast<u16>((amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF); | ||
| 406 | }; | ||
| 407 | |||
| 408 | const auto processed_amp_low = process_amplitude(amp_low); | ||
| 409 | const auto processed_amp_high = process_amplitude(amp_high); | ||
| 410 | |||
| 411 | return joystick->RumblePlay(processed_amp_low, processed_amp_high); | ||
| 412 | } | ||
| 413 | |||
| 414 | private: | ||
| 415 | std::shared_ptr<SDLJoystick> joystick; | ||
| 416 | }; | ||
| 417 | |||
| 419 | class SDLDirectionMotion final : public Input::MotionDevice { | 418 | class SDLDirectionMotion final : public Input::MotionDevice { |
| 420 | public: | 419 | public: |
| 421 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) | 420 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) |
| @@ -558,7 +557,7 @@ class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> { | |||
| 558 | public: | 557 | public: |
| 559 | explicit SDLAnalogFactory(SDLState& state_) : state(state_) {} | 558 | explicit SDLAnalogFactory(SDLState& state_) : state(state_) {} |
| 560 | /** | 559 | /** |
| 561 | * Creates analog device from joystick axes | 560 | * Creates an analog device from joystick axes |
| 562 | * @param params contains parameters for creating the device: | 561 | * @param params contains parameters for creating the device: |
| 563 | * - "guid": the guid of the joystick to bind | 562 | * - "guid": the guid of the joystick to bind |
| 564 | * - "port": the nth joystick of the same type | 563 | * - "port": the nth joystick of the same type |
| @@ -584,6 +583,26 @@ private: | |||
| 584 | SDLState& state; | 583 | SDLState& state; |
| 585 | }; | 584 | }; |
| 586 | 585 | ||
| 586 | /// An vibration device factory that creates vibration devices from SDL joystick | ||
| 587 | class SDLVibrationFactory final : public Input::Factory<Input::VibrationDevice> { | ||
| 588 | public: | ||
| 589 | explicit SDLVibrationFactory(SDLState& state_) : state(state_) {} | ||
| 590 | /** | ||
| 591 | * Creates a vibration device from a joystick | ||
| 592 | * @param params contains parameters for creating the device: | ||
| 593 | * - "guid": the guid of the joystick to bind | ||
| 594 | * - "port": the nth joystick of the same type | ||
| 595 | */ | ||
| 596 | std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override { | ||
| 597 | const std::string guid = params.Get("guid", "0"); | ||
| 598 | const int port = params.Get("port", 0); | ||
| 599 | return std::make_unique<SDLVibration>(state.GetSDLJoystickByGUID(guid, port)); | ||
| 600 | } | ||
| 601 | |||
| 602 | private: | ||
| 603 | SDLState& state; | ||
| 604 | }; | ||
| 605 | |||
| 587 | /// A motion device factory that creates motion devices from SDL joystick | 606 | /// A motion device factory that creates motion devices from SDL joystick |
| 588 | class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> { | 607 | class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> { |
| 589 | public: | 608 | public: |
| @@ -650,11 +669,13 @@ private: | |||
| 650 | 669 | ||
| 651 | SDLState::SDLState() { | 670 | SDLState::SDLState() { |
| 652 | using namespace Input; | 671 | using namespace Input; |
| 653 | analog_factory = std::make_shared<SDLAnalogFactory>(*this); | ||
| 654 | button_factory = std::make_shared<SDLButtonFactory>(*this); | 672 | button_factory = std::make_shared<SDLButtonFactory>(*this); |
| 673 | analog_factory = std::make_shared<SDLAnalogFactory>(*this); | ||
| 674 | vibration_factory = std::make_shared<SDLVibrationFactory>(*this); | ||
| 655 | motion_factory = std::make_shared<SDLMotionFactory>(*this); | 675 | motion_factory = std::make_shared<SDLMotionFactory>(*this); |
| 656 | RegisterFactory<AnalogDevice>("sdl", analog_factory); | ||
| 657 | RegisterFactory<ButtonDevice>("sdl", button_factory); | 676 | RegisterFactory<ButtonDevice>("sdl", button_factory); |
| 677 | RegisterFactory<AnalogDevice>("sdl", analog_factory); | ||
| 678 | RegisterFactory<VibrationDevice>("sdl", vibration_factory); | ||
| 658 | RegisterFactory<MotionDevice>("sdl", motion_factory); | 679 | RegisterFactory<MotionDevice>("sdl", motion_factory); |
| 659 | 680 | ||
| 660 | // If the frontend is going to manage the event loop, then we don't start one here | 681 | // If the frontend is going to manage the event loop, then we don't start one here |
| @@ -676,7 +697,7 @@ SDLState::SDLState() { | |||
| 676 | using namespace std::chrono_literals; | 697 | using namespace std::chrono_literals; |
| 677 | while (initialized) { | 698 | while (initialized) { |
| 678 | SDL_PumpEvents(); | 699 | SDL_PumpEvents(); |
| 679 | std::this_thread::sleep_for(5ms); | 700 | std::this_thread::sleep_for(1ms); |
| 680 | } | 701 | } |
| 681 | }); | 702 | }); |
| 682 | } | 703 | } |
| @@ -691,6 +712,7 @@ SDLState::~SDLState() { | |||
| 691 | using namespace Input; | 712 | using namespace Input; |
| 692 | UnregisterFactory<ButtonDevice>("sdl"); | 713 | UnregisterFactory<ButtonDevice>("sdl"); |
| 693 | UnregisterFactory<AnalogDevice>("sdl"); | 714 | UnregisterFactory<AnalogDevice>("sdl"); |
| 715 | UnregisterFactory<VibrationDevice>("sdl"); | ||
| 694 | UnregisterFactory<MotionDevice>("sdl"); | 716 | UnregisterFactory<MotionDevice>("sdl"); |
| 695 | 717 | ||
| 696 | CloseJoysticks(); | 718 | CloseJoysticks(); |
| @@ -1045,7 +1067,6 @@ public: | |||
| 1045 | 1067 | ||
| 1046 | void Start(const std::string& device_id) override { | 1068 | void Start(const std::string& device_id) override { |
| 1047 | SDLPoller::Start(device_id); | 1069 | SDLPoller::Start(device_id); |
| 1048 | // Load the game controller | ||
| 1049 | // Reset stored axes | 1070 | // Reset stored axes |
| 1050 | analog_x_axis = -1; | 1071 | analog_x_axis = -1; |
| 1051 | analog_y_axis = -1; | 1072 | analog_y_axis = -1; |
| @@ -1058,40 +1079,21 @@ public: | |||
| 1058 | if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) { | 1079 | if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) { |
| 1059 | continue; | 1080 | continue; |
| 1060 | } | 1081 | } |
| 1061 | // Simplify controller config by testing if game controller support is enabled. | ||
| 1062 | if (event.type == SDL_JOYAXISMOTION) { | 1082 | if (event.type == SDL_JOYAXISMOTION) { |
| 1063 | const auto axis = event.jaxis.axis; | 1083 | const auto axis = event.jaxis.axis; |
| 1064 | if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | 1084 | // In order to return a complete analog param, we need inputs for both axes. |
| 1065 | auto* const controller = joystick->GetSDLGameController()) { | 1085 | // First we take the x-axis (horizontal) input, then the y-axis (vertical) input. |
| 1066 | const auto axis_left_x = | 1086 | if (analog_x_axis == -1) { |
| 1067 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) | 1087 | analog_x_axis = axis; |
| 1068 | .value.axis; | 1088 | } else if (analog_y_axis == -1 && analog_x_axis != axis) { |
| 1069 | const auto axis_left_y = | 1089 | analog_y_axis = axis; |
| 1070 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) | 1090 | } |
| 1071 | .value.axis; | 1091 | } else { |
| 1072 | const auto axis_right_x = | 1092 | // If the press wasn't accepted as a joy axis, check for a button press |
| 1073 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX) | 1093 | auto button_press = button_poller.FromEvent(event); |
| 1074 | .value.axis; | 1094 | if (button_press) { |
| 1075 | const auto axis_right_y = | 1095 | return *button_press; |
| 1076 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY) | ||
| 1077 | .value.axis; | ||
| 1078 | |||
| 1079 | if (axis == axis_left_x || axis == axis_left_y) { | ||
| 1080 | analog_x_axis = axis_left_x; | ||
| 1081 | analog_y_axis = axis_left_y; | ||
| 1082 | break; | ||
| 1083 | } else if (axis == axis_right_x || axis == axis_right_y) { | ||
| 1084 | analog_x_axis = axis_right_x; | ||
| 1085 | analog_y_axis = axis_right_y; | ||
| 1086 | break; | ||
| 1087 | } | ||
| 1088 | } | 1096 | } |
| 1089 | } | ||
| 1090 | |||
| 1091 | // If the press wasn't accepted as a joy axis, check for a button press | ||
| 1092 | auto button_press = button_poller.FromEvent(event); | ||
| 1093 | if (button_press) { | ||
| 1094 | return *button_press; | ||
| 1095 | } | 1097 | } |
| 1096 | } | 1098 | } |
| 1097 | 1099 | ||
| @@ -1104,6 +1106,7 @@ public: | |||
| 1104 | return params; | 1106 | return params; |
| 1105 | } | 1107 | } |
| 1106 | } | 1108 | } |
| 1109 | |||
| 1107 | return {}; | 1110 | return {}; |
| 1108 | } | 1111 | } |
| 1109 | 1112 | ||
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index b9bb4dc56..08044b00d 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h | |||
| @@ -22,6 +22,7 @@ namespace InputCommon::SDL { | |||
| 22 | class SDLAnalogFactory; | 22 | class SDLAnalogFactory; |
| 23 | class SDLButtonFactory; | 23 | class SDLButtonFactory; |
| 24 | class SDLMotionFactory; | 24 | class SDLMotionFactory; |
| 25 | class SDLVibrationFactory; | ||
| 25 | class SDLJoystick; | 26 | class SDLJoystick; |
| 26 | 27 | ||
| 27 | class SDLState : public State { | 28 | class SDLState : public State { |
| @@ -72,6 +73,7 @@ private: | |||
| 72 | 73 | ||
| 73 | std::shared_ptr<SDLButtonFactory> button_factory; | 74 | std::shared_ptr<SDLButtonFactory> button_factory; |
| 74 | std::shared_ptr<SDLAnalogFactory> analog_factory; | 75 | std::shared_ptr<SDLAnalogFactory> analog_factory; |
| 76 | std::shared_ptr<SDLVibrationFactory> vibration_factory; | ||
| 75 | std::shared_ptr<SDLMotionFactory> motion_factory; | 77 | std::shared_ptr<SDLMotionFactory> motion_factory; |
| 76 | 78 | ||
| 77 | bool start_thread = false; | 79 | bool start_thread = false; |
diff --git a/src/input_common/settings.cpp b/src/input_common/settings.cpp index b66c05856..557e7a9a0 100644 --- a/src/input_common/settings.cpp +++ b/src/input_common/settings.cpp | |||
| @@ -14,13 +14,6 @@ const std::array<const char*, NumButtons> mapping = {{ | |||
| 14 | }}; | 14 | }}; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace NativeMotion { | ||
| 18 | const std::array<const char*, NumMotions> mapping = {{ | ||
| 19 | "motionleft", | ||
| 20 | "motionright", | ||
| 21 | }}; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace NativeAnalog { | 17 | namespace NativeAnalog { |
| 25 | const std::array<const char*, NumAnalogs> mapping = {{ | 18 | const std::array<const char*, NumAnalogs> mapping = {{ |
| 26 | "lstick", | 19 | "lstick", |
| @@ -28,6 +21,20 @@ const std::array<const char*, NumAnalogs> mapping = {{ | |||
| 28 | }}; | 21 | }}; |
| 29 | } | 22 | } |
| 30 | 23 | ||
| 24 | namespace NativeVibration { | ||
| 25 | const std::array<const char*, NumVibrations> mapping = {{ | ||
| 26 | "left_vibration_device", | ||
| 27 | "right_vibration_device", | ||
| 28 | }}; | ||
| 29 | } | ||
| 30 | |||
| 31 | namespace NativeMotion { | ||
| 32 | const std::array<const char*, NumMotions> mapping = {{ | ||
| 33 | "motionleft", | ||
| 34 | "motionright", | ||
| 35 | }}; | ||
| 36 | } | ||
| 37 | |||
| 31 | namespace NativeMouseButton { | 38 | namespace NativeMouseButton { |
| 32 | const std::array<const char*, NumMouseButtons> mapping = {{ | 39 | const std::array<const char*, NumMouseButtons> mapping = {{ |
| 33 | "left", | 40 | "left", |
diff --git a/src/input_common/settings.h b/src/input_common/settings.h index f52d28540..75486554b 100644 --- a/src/input_common/settings.h +++ b/src/input_common/settings.h | |||
| @@ -66,17 +66,32 @@ constexpr int NUM_STICKS_HID = NumAnalogs; | |||
| 66 | extern const std::array<const char*, NumAnalogs> mapping; | 66 | extern const std::array<const char*, NumAnalogs> mapping; |
| 67 | } // namespace NativeAnalog | 67 | } // namespace NativeAnalog |
| 68 | 68 | ||
| 69 | namespace NativeVibration { | ||
| 70 | enum Values : int { | ||
| 71 | LeftVibrationDevice, | ||
| 72 | RightVibrationDevice, | ||
| 73 | |||
| 74 | NumVibrations, | ||
| 75 | }; | ||
| 76 | |||
| 77 | constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice; | ||
| 78 | constexpr int VIBRATION_HID_END = NumVibrations; | ||
| 79 | constexpr int NUM_VIBRATIONS_HID = NumVibrations; | ||
| 80 | |||
| 81 | extern const std::array<const char*, NumVibrations> mapping; | ||
| 82 | }; // namespace NativeVibration | ||
| 83 | |||
| 69 | namespace NativeMotion { | 84 | namespace NativeMotion { |
| 70 | enum Values : int { | 85 | enum Values : int { |
| 71 | MOTIONLEFT, | 86 | MotionLeft, |
| 72 | MOTIONRIGHT, | 87 | MotionRight, |
| 73 | 88 | ||
| 74 | NumMotions, | 89 | NumMotions, |
| 75 | }; | 90 | }; |
| 76 | 91 | ||
| 77 | constexpr int MOTION_HID_BEGIN = MOTIONLEFT; | 92 | constexpr int MOTION_HID_BEGIN = MotionLeft; |
| 78 | constexpr int MOTION_HID_END = NumMotions; | 93 | constexpr int MOTION_HID_END = NumMotions; |
| 79 | constexpr int NUM_MOTION_HID = NumMotions; | 94 | constexpr int NUM_MOTIONS_HID = NumMotions; |
| 80 | 95 | ||
| 81 | extern const std::array<const char*, NumMotions> mapping; | 96 | extern const std::array<const char*, NumMotions> mapping; |
| 82 | } // namespace NativeMotion | 97 | } // namespace NativeMotion |
| @@ -305,9 +320,11 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; | |||
| 305 | 320 | ||
| 306 | } // namespace NativeKeyboard | 321 | } // namespace NativeKeyboard |
| 307 | 322 | ||
| 308 | using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; | ||
| 309 | using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; | 323 | using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; |
| 310 | using MotionRaw = std::array<std::string, NativeMotion::NumMotions>; | 324 | using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; |
| 325 | using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>; | ||
| 326 | using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>; | ||
| 327 | |||
| 311 | using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; | 328 | using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; |
| 312 | using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; | 329 | using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; |
| 313 | using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; | 330 | using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; |
| @@ -330,7 +347,11 @@ struct PlayerInput { | |||
| 330 | ControllerType controller_type; | 347 | ControllerType controller_type; |
| 331 | ButtonsRaw buttons; | 348 | ButtonsRaw buttons; |
| 332 | AnalogsRaw analogs; | 349 | AnalogsRaw analogs; |
| 333 | MotionRaw motions; | 350 | VibrationsRaw vibrations; |
| 351 | MotionsRaw motions; | ||
| 352 | |||
| 353 | bool vibration_enabled; | ||
| 354 | int vibration_strength; | ||
| 334 | 355 | ||
| 335 | u32 body_color_left; | 356 | u32 body_color_left; |
| 336 | u32 body_color_right; | 357 | u32 body_color_right; |
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index 7039d6fc3..3677e79ca 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -344,7 +344,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | |||
| 344 | }; | 344 | }; |
| 345 | Socket socket{host, port, pad_index, client_id, std::move(callback)}; | 345 | Socket socket{host, port, pad_index, client_id, std::move(callback)}; |
| 346 | std::thread worker_thread{SocketLoop, &socket}; | 346 | std::thread worker_thread{SocketLoop, &socket}; |
| 347 | const bool result = success_event.WaitFor(std::chrono::seconds(8)); | 347 | const bool result = success_event.WaitFor(std::chrono::seconds(5)); |
| 348 | socket.Stop(); | 348 | socket.Stop(); |
| 349 | worker_thread.join(); | 349 | worker_thread.join(); |
| 350 | if (result) { | 350 | if (result) { |