summaryrefslogtreecommitdiff
path: root/src/input_common/sdl/sdl_impl.cpp
diff options
context:
space:
mode:
authorGravatar Morph2020-10-20 13:55:25 -0400
committerGravatar Morph2020-11-15 23:33:20 -0500
commite9e1876e821b8bd1bb5c8254ec93e2cc479e16dd (patch)
tree344b40a5a874cb188c6e7aa7d1622c77a215090d /src/input_common/sdl/sdl_impl.cpp
parentconfigure_input: Add per-player vibration (diff)
downloadyuzu-e9e1876e821b8bd1bb5c8254ec93e2cc479e16dd.tar.gz
yuzu-e9e1876e821b8bd1bb5c8254ec93e2cc479e16dd.tar.xz
yuzu-e9e1876e821b8bd1bb5c8254ec93e2cc479e16dd.zip
input_common: Add VibrationDevice and VibrationDeviceFactory
A vibration device is an input device that returns an unsigned byte as status. It represents whether the vibration device supports vibration or not. If the status returns 1, it supports vibration. Otherwise, it does not support vibration.
Diffstat (limited to '')
-rw-r--r--src/input_common/sdl/sdl_impl.cpp74
1 files changed, 58 insertions, 16 deletions
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index 18fb2ac5e..a2a83cdc9 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -85,16 +85,17 @@ public:
85 using std::chrono::milliseconds; 85 using std::chrono::milliseconds;
86 using std::chrono::steady_clock; 86 using std::chrono::steady_clock;
87 87
88 // Prevent vibrations less than 10ms apart from each other. 88 // Block non-zero vibrations less than 10ms apart from each other.
89 if (duration_cast<milliseconds>(steady_clock::now() - last_vibration) < milliseconds(10)) { 89 if ((amp_low != 0 || amp_high != 0) &&
90 duration_cast<milliseconds>(steady_clock::now() - last_vibration) < milliseconds(10)) {
90 return false; 91 return false;
91 }; 92 }
92 93
93 last_vibration = steady_clock::now(); 94 last_vibration = steady_clock::now();
94 95
95 if (sdl_controller != nullptr) { 96 if (sdl_controller) {
96 return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; 97 return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0;
97 } else if (sdl_joystick != nullptr) { 98 } else if (sdl_joystick) {
98 return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0; 99 return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0;
99 } 100 }
100 101
@@ -321,14 +322,6 @@ public:
321 return joystick->GetButton(button); 322 return joystick->GetButton(button);
322 } 323 }
323 324
324 bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
325 const u16 processed_amp_low =
326 static_cast<u16>(pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f)) * 0xFFFF);
327 const u16 processed_amp_high =
328 static_cast<u16>(pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f)) * 0xFFFF);
329 return joystick->RumblePlay(processed_amp_low, processed_amp_high);
330 }
331
332private: 325private:
333 std::shared_ptr<SDLJoystick> joystick; 326 std::shared_ptr<SDLJoystick> joystick;
334 int button; 327 int button;
@@ -412,6 +405,32 @@ private:
412 const float range; 405 const float range;
413}; 406};
414 407
408class SDLVibration final : public Input::VibrationDevice {
409public:
410 explicit SDLVibration(std::shared_ptr<SDLJoystick> joystick_)
411 : joystick(std::move(joystick_)) {}
412
413 u8 GetStatus() const override {
414 joystick->RumblePlay(1, 1);
415 return joystick->RumblePlay(0, 0);
416 }
417
418 bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
419 const auto process_amplitude = [](f32 amplitude) {
420 return static_cast<u16>(std::pow(amplitude, 0.5f) *
421 (3.0f - 2.0f * std::pow(amplitude, 0.15f)) * 0xFFFF);
422 };
423
424 const auto processed_amp_low = process_amplitude(amp_low);
425 const auto processed_amp_high = process_amplitude(amp_high);
426
427 return joystick->RumblePlay(processed_amp_low, processed_amp_high);
428 }
429
430private:
431 std::shared_ptr<SDLJoystick> joystick;
432};
433
415class SDLDirectionMotion final : public Input::MotionDevice { 434class SDLDirectionMotion final : public Input::MotionDevice {
416public: 435public:
417 explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) 436 explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
@@ -554,7 +573,7 @@ class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
554public: 573public:
555 explicit SDLAnalogFactory(SDLState& state_) : state(state_) {} 574 explicit SDLAnalogFactory(SDLState& state_) : state(state_) {}
556 /** 575 /**
557 * Creates analog device from joystick axes 576 * Creates an analog device from joystick axes
558 * @param params contains parameters for creating the device: 577 * @param params contains parameters for creating the device:
559 * - "guid": the guid of the joystick to bind 578 * - "guid": the guid of the joystick to bind
560 * - "port": the nth joystick of the same type 579 * - "port": the nth joystick of the same type
@@ -580,6 +599,26 @@ private:
580 SDLState& state; 599 SDLState& state;
581}; 600};
582 601
602/// An vibration device factory that creates vibration devices from SDL joystick
603class SDLVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
604public:
605 explicit SDLVibrationFactory(SDLState& state_) : state(state_) {}
606 /**
607 * Creates a vibration device from a joystick
608 * @param params contains parameters for creating the device:
609 * - "guid": the guid of the joystick to bind
610 * - "port": the nth joystick of the same type
611 */
612 std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override {
613 const std::string guid = params.Get("guid", "0");
614 const int port = params.Get("port", 0);
615 return std::make_unique<SDLVibration>(state.GetSDLJoystickByGUID(guid, port));
616 }
617
618private:
619 SDLState& state;
620};
621
583/// A motion device factory that creates motion devices from SDL joystick 622/// A motion device factory that creates motion devices from SDL joystick
584class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> { 623class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
585public: 624public:
@@ -646,11 +685,13 @@ private:
646 685
647SDLState::SDLState() { 686SDLState::SDLState() {
648 using namespace Input; 687 using namespace Input;
649 analog_factory = std::make_shared<SDLAnalogFactory>(*this);
650 button_factory = std::make_shared<SDLButtonFactory>(*this); 688 button_factory = std::make_shared<SDLButtonFactory>(*this);
689 analog_factory = std::make_shared<SDLAnalogFactory>(*this);
690 vibration_factory = std::make_shared<SDLVibrationFactory>(*this);
651 motion_factory = std::make_shared<SDLMotionFactory>(*this); 691 motion_factory = std::make_shared<SDLMotionFactory>(*this);
652 RegisterFactory<AnalogDevice>("sdl", analog_factory);
653 RegisterFactory<ButtonDevice>("sdl", button_factory); 692 RegisterFactory<ButtonDevice>("sdl", button_factory);
693 RegisterFactory<AnalogDevice>("sdl", analog_factory);
694 RegisterFactory<VibrationDevice>("sdl", vibration_factory);
654 RegisterFactory<MotionDevice>("sdl", motion_factory); 695 RegisterFactory<MotionDevice>("sdl", motion_factory);
655 696
656 // If the frontend is going to manage the event loop, then we don't start one here 697 // If the frontend is going to manage the event loop, then we don't start one here
@@ -687,6 +728,7 @@ SDLState::~SDLState() {
687 using namespace Input; 728 using namespace Input;
688 UnregisterFactory<ButtonDevice>("sdl"); 729 UnregisterFactory<ButtonDevice>("sdl");
689 UnregisterFactory<AnalogDevice>("sdl"); 730 UnregisterFactory<AnalogDevice>("sdl");
731 UnregisterFactory<VibrationDevice>("sdl");
690 UnregisterFactory<MotionDevice>("sdl"); 732 UnregisterFactory<MotionDevice>("sdl");
691 733
692 CloseJoysticks(); 734 CloseJoysticks();