From fb512adc5ff397e50157c20dfc3e425e3bbd4abe Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 21 Jan 2025 19:19:01 -0600 Subject: [PATCH 1/2] InputCommon: Make SDL Motor L/R Outputs not fight each other. --- .../ControllerInterface/SDL/SDL.cpp | 64 ++++++++++++++----- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp index 7b68b96712..de8644e2e8 100644 --- a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp +++ b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp @@ -187,30 +187,55 @@ private: }; // Rumble - template - class GenericMotor : public Output + class Motor : public Output { public: - explicit GenericMotor(SDL_GameController* gc) : m_gc(gc) {} - std::string GetName() const override + Motor(const char* name, GameController& gc, Uint16* state) + : m_name{name}, m_gc{gc}, m_state{*state} { - return std::string("Motor") + motor_suffixes[SuffixIndex]; } + std::string GetName() const override { return m_name; } void SetState(ControlState state) override { - Uint16 rumble = state * std::numeric_limits::max(); - SDL_GameControllerRumble(m_gc, rumble * LowEnable, rumble * HighEnable, RUMBLE_LENGTH_MS); + const auto new_state = state * std::numeric_limits::max(); + if (m_state == new_state) + return; + + m_state = new_state; + m_gc.UpdateRumble(); } private: - SDL_GameController* const m_gc; + const char* const m_name; + GameController& m_gc; + Uint16& m_state; }; - static constexpr const char* motor_suffixes[] = {"", " L", " R"}; + class CombinedMotor : public Output + { + public: + CombinedMotor(const char* name, GameController& gc, Uint16* low_state, Uint16* high_state) + : m_name{name}, m_gc{gc}, m_low_state{*low_state}, m_high_state{*high_state} + { + } + std::string GetName() const override { return m_name; } + void SetState(ControlState state) override + { + const auto new_state = state * std::numeric_limits::max(); + if (m_low_state == new_state && m_high_state == new_state) + return; - using Motor = GenericMotor<1, 1, 0>; - using MotorL = GenericMotor<1, 0, 1>; - using MotorR = GenericMotor<0, 1, 2>; + m_low_state = new_state; + m_high_state = new_state; + m_gc.UpdateRumble(); + } + + private: + const char* const m_name; + GameController& m_gc; + Uint16& m_low_state; + Uint16& m_high_state; + }; class HapticEffect : public Output { @@ -364,6 +389,15 @@ public: } private: + void UpdateRumble() + { + SDL_GameControllerRumble(m_gamecontroller, m_low_freq_rumble, m_high_freq_rumble, + RUMBLE_LENGTH_MS); + } + + Uint16 m_low_freq_rumble = 0; + Uint16 m_high_freq_rumble = 0; + SDL_GameController* const m_gamecontroller; std::string m_name; SDL_Joystick* const m_joystick; @@ -754,9 +788,9 @@ GameController::GameController(SDL_GameController* const gamecontroller, // Rumble if (SDL_GameControllerHasRumble(m_gamecontroller)) { - AddOutput(new Motor(m_gamecontroller)); - AddOutput(new MotorL(m_gamecontroller)); - AddOutput(new MotorR(m_gamecontroller)); + AddOutput(new CombinedMotor("Motor", *this, &m_low_freq_rumble, &m_high_freq_rumble)); + AddOutput(new Motor("Motor L", *this, &m_low_freq_rumble)); + AddOutput(new Motor("Motor R", *this, &m_high_freq_rumble)); } // Touchpad From 8354279aae31a3eed1edb2fb6b3fd08cf97b12d4 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 21 Jan 2025 19:46:27 -0600 Subject: [PATCH 2/2] InputCommon: Add support for SDL gamecontroller rumble triggers. --- .../ControllerInterface/SDL/SDL.cpp | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp index de8644e2e8..04981e1011 100644 --- a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp +++ b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp @@ -187,11 +187,13 @@ private: }; // Rumble - class Motor : public Output + class Rumble : public Output { public: - Motor(const char* name, GameController& gc, Uint16* state) - : m_name{name}, m_gc{gc}, m_state{*state} + using UpdateCallback = void (GameController::*)(void); + + Rumble(const char* name, GameController& gc, Uint16* state, UpdateCallback update_callback) + : m_name{name}, m_gc{gc}, m_state{*state}, m_update_callback{update_callback} { } std::string GetName() const override { return m_name; } @@ -202,23 +204,24 @@ private: return; m_state = new_state; - m_gc.UpdateRumble(); + (m_gc.*m_update_callback)(); } private: const char* const m_name; GameController& m_gc; Uint16& m_state; + UpdateCallback const m_update_callback; }; class CombinedMotor : public Output { public: - CombinedMotor(const char* name, GameController& gc, Uint16* low_state, Uint16* high_state) - : m_name{name}, m_gc{gc}, m_low_state{*low_state}, m_high_state{*high_state} + CombinedMotor(GameController& gc, Uint16* low_state, Uint16* high_state) + : m_gc{gc}, m_low_state{*low_state}, m_high_state{*high_state} { } - std::string GetName() const override { return m_name; } + std::string GetName() const override { return "Motor"; } void SetState(ControlState state) override { const auto new_state = state * std::numeric_limits::max(); @@ -231,7 +234,6 @@ private: } private: - const char* const m_name; GameController& m_gc; Uint16& m_low_state; Uint16& m_high_state; @@ -395,9 +397,18 @@ private: RUMBLE_LENGTH_MS); } + void UpdateRumbleTriggers() + { + SDL_GameControllerRumbleTriggers(m_gamecontroller, m_trigger_l_rumble, m_trigger_r_rumble, + RUMBLE_LENGTH_MS); + } + Uint16 m_low_freq_rumble = 0; Uint16 m_high_freq_rumble = 0; + Uint16 m_trigger_l_rumble = 0; + Uint16 m_trigger_r_rumble = 0; + SDL_GameController* const m_gamecontroller; std::string m_name; SDL_Joystick* const m_joystick; @@ -788,9 +799,16 @@ GameController::GameController(SDL_GameController* const gamecontroller, // Rumble if (SDL_GameControllerHasRumble(m_gamecontroller)) { - AddOutput(new CombinedMotor("Motor", *this, &m_low_freq_rumble, &m_high_freq_rumble)); - AddOutput(new Motor("Motor L", *this, &m_low_freq_rumble)); - AddOutput(new Motor("Motor R", *this, &m_high_freq_rumble)); + AddOutput(new CombinedMotor(*this, &m_low_freq_rumble, &m_high_freq_rumble)); + AddOutput(new Rumble("Motor L", *this, &m_low_freq_rumble, &GameController::UpdateRumble)); + AddOutput(new Rumble("Motor R", *this, &m_high_freq_rumble, &GameController::UpdateRumble)); + } + if (SDL_GameControllerHasRumbleTriggers(m_gamecontroller)) + { + AddOutput(new Rumble("Trigger L", *this, &m_trigger_l_rumble, + &GameController::UpdateRumbleTriggers)); + AddOutput(new Rumble("Trigger R", *this, &m_trigger_r_rumble, + &GameController::UpdateRumbleTriggers)); } // Touchpad