First implementation of controller rumble

This commit is contained in:
german 2020-07-10 21:20:50 -05:00 committed by Morph
parent a8be822e8e
commit ab88c2f611
5 changed files with 63 additions and 14 deletions

View file

@ -5,6 +5,7 @@
#include <algorithm>
#include <array>
#include <atomic>
#include <chrono>
#include <cmath>
#include <functional>
#include <mutex>
@ -78,6 +79,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);
@ -139,6 +167,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;
@ -207,7 +238,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);
@ -303,6 +334,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;