summaryrefslogtreecommitdiff
path: root/src/input_common
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common')
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp6
-rw-r--r--src/input_common/gcadapter/gc_adapter.h4
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp50
-rw-r--r--src/input_common/gcadapter/gc_poller.h11
-rw-r--r--src/input_common/main.cpp15
-rw-r--r--src/input_common/motion_input.h23
-rw-r--r--src/input_common/sdl/sdl_impl.cpp137
-rw-r--r--src/input_common/sdl/sdl_impl.h2
-rw-r--r--src/input_common/settings.cpp21
-rw-r--r--src/input_common/settings.h35
-rw-r--r--src/input_common/udp/client.cpp2
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
233bool Adapter::RumblePlay(std::size_t port, f32 amplitude) { 233bool 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
16class GCButton final : public Input::ButtonDevice { 16class GCButton final : public Input::ButtonDevice {
17public: 17public:
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
38private: 30private:
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
44class GCAxisButton final : public Input::ButtonDevice { 36class GCAxisButton final : public Input::ButtonDevice {
@@ -299,4 +291,42 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
299 return params; 291 return params;
300} 292}
301 293
294class GCVibration final : public Input::VibrationDevice {
295public:
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
311private:
312 const u32 port;
313 GCAdapter::Adapter* gcadapter;
314};
315
316/// An vibration device factory that creates vibration devices from GC Adapter
317GCVibrationFactory::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 */
325std::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
68class GCVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
69public:
70 explicit GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_);
71
72 std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override;
73
74private:
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
14class MotionInput { 14class MotionInput {
15public: 15public:
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
47private: 48private:
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
336private: 310private:
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
393class SDLVibration final : public Input::VibrationDevice {
394public:
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
414private:
415 std::shared_ptr<SDLJoystick> joystick;
416};
417
419class SDLDirectionMotion final : public Input::MotionDevice { 418class SDLDirectionMotion final : public Input::MotionDevice {
420public: 419public:
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> {
558public: 557public:
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
587class SDLVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
588public:
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
602private:
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
588class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> { 607class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
589public: 608public:
@@ -650,11 +669,13 @@ private:
650 669
651SDLState::SDLState() { 670SDLState::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 {
22class SDLAnalogFactory; 22class SDLAnalogFactory;
23class SDLButtonFactory; 23class SDLButtonFactory;
24class SDLMotionFactory; 24class SDLMotionFactory;
25class SDLVibrationFactory;
25class SDLJoystick; 26class SDLJoystick;
26 27
27class SDLState : public State { 28class 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
17namespace NativeMotion {
18const std::array<const char*, NumMotions> mapping = {{
19 "motionleft",
20 "motionright",
21}};
22}
23
24namespace NativeAnalog { 17namespace NativeAnalog {
25const std::array<const char*, NumAnalogs> mapping = {{ 18const 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
24namespace NativeVibration {
25const std::array<const char*, NumVibrations> mapping = {{
26 "left_vibration_device",
27 "right_vibration_device",
28}};
29}
30
31namespace NativeMotion {
32const std::array<const char*, NumMotions> mapping = {{
33 "motionleft",
34 "motionright",
35}};
36}
37
31namespace NativeMouseButton { 38namespace NativeMouseButton {
32const std::array<const char*, NumMouseButtons> mapping = {{ 39const 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;
66extern const std::array<const char*, NumAnalogs> mapping; 66extern const std::array<const char*, NumAnalogs> mapping;
67} // namespace NativeAnalog 67} // namespace NativeAnalog
68 68
69namespace NativeVibration {
70enum Values : int {
71 LeftVibrationDevice,
72 RightVibrationDevice,
73
74 NumVibrations,
75};
76
77constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice;
78constexpr int VIBRATION_HID_END = NumVibrations;
79constexpr int NUM_VIBRATIONS_HID = NumVibrations;
80
81extern const std::array<const char*, NumVibrations> mapping;
82}; // namespace NativeVibration
83
69namespace NativeMotion { 84namespace NativeMotion {
70enum Values : int { 85enum Values : int {
71 MOTIONLEFT, 86 MotionLeft,
72 MOTIONRIGHT, 87 MotionRight,
73 88
74 NumMotions, 89 NumMotions,
75}; 90};
76 91
77constexpr int MOTION_HID_BEGIN = MOTIONLEFT; 92constexpr int MOTION_HID_BEGIN = MotionLeft;
78constexpr int MOTION_HID_END = NumMotions; 93constexpr int MOTION_HID_END = NumMotions;
79constexpr int NUM_MOTION_HID = NumMotions; 94constexpr int NUM_MOTIONS_HID = NumMotions;
80 95
81extern const std::array<const char*, NumMotions> mapping; 96extern 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
308using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
309using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; 323using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
310using MotionRaw = std::array<std::string, NativeMotion::NumMotions>; 324using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
325using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
326using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>;
327
311using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; 328using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
312using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; 329using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
313using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; 330using 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) {