diff options
Diffstat (limited to 'src/input_common/sdl/sdl_impl.cpp')
-rw-r--r-- | src/input_common/sdl/sdl_impl.cpp | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 0b0095978..bd480570a 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -5,6 +5,7 @@ #include <algorithm> #include <array> #include <atomic> +#include <chrono> #include <cmath> #include <functional> #include <mutex> @@ -79,6 +80,33 @@ public: return state.axes.at(axis) / (32767.0f * range); } + bool RumblePlay(f32 amp_low, f32 amp_high, int time) { + const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF); + const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF); + // Lower drastically the number of state changes + if (raw_amp_low >> 11 == last_state_rumble_low >> 11 && + raw_amp_high >> 11 == last_state_rumble_high >> 11) { + if (raw_amp_low + raw_amp_high != 0 || + last_state_rumble_low + last_state_rumble_high == 0) { + return false; + } + } + // Don't change state if last vibration was < 20ms + const auto now = std::chrono::system_clock::now(); + if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) < + std::chrono::milliseconds(20)) { + return raw_amp_low + raw_amp_high == 0; + } + + last_vibration = now; + last_state_rumble_low = raw_amp_low; + last_state_rumble_high = raw_amp_high; + if (sdl_joystick) { + SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time); + } + return false; + } + std::tuple<float, float> GetAnalog(int axis_x, int axis_y, float range) const { float x = GetAxis(axis_x, range); float y = GetAxis(axis_y, range); @@ -144,6 +172,9 @@ private: } state; std::string guid; int port; + u16 last_state_rumble_high; + u16 last_state_rumble_low; + std::chrono::time_point<std::chrono::system_clock> last_vibration; std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; mutable std::mutex mutex; @@ -215,7 +246,7 @@ void SDLState::InitJoystick(int joystick_index) { sdl_gamecontroller = SDL_GameControllerOpen(joystick_index); } if (!sdl_joystick) { - LOG_ERROR(Input, "failed to open joystick {}", joystick_index); + LOG_ERROR(Input, "Failed to open joystick {}", joystick_index); return; } const std::string guid = GetGUID(sdl_joystick); @@ -311,6 +342,12 @@ public: return joystick->GetButton(button); } + bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { + const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f)); + const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f)); + return joystick->RumblePlay(new_amp_low, new_amp_high, 250); + } + private: std::shared_ptr<SDLJoystick> joystick; int button; |