Skip to content

Commit

Permalink
sdl: don't run null haptic effects. Stop effects instead
Browse files Browse the repository at this point in the history
Tentative fix for Issue #1766
  • Loading branch information
flyinghead committed Dec 7, 2024
1 parent 89abb79 commit a99aa52
Showing 1 changed file with 85 additions and 55 deletions.
140 changes: 85 additions & 55 deletions core/sdl/sdl_gamepad.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,15 +311,21 @@ class SDLGamepad : public GamepadDevice
const u16 intensity = getRumbleIntensity(power);
if (hapticRumble)
{
SDL_HapticEffect effect{};
effect.type = SDL_HAPTIC_SINE;
effect.periodic.direction.type = SDL_HAPTIC_CARTESIAN;
effect.periodic.direction.dir[0] = (vib_stop_time & 1) ? -1 : 1; // west or east randomly
effect.periodic.period = 40; // 25 Hz
effect.periodic.magnitude = intensity / 4; // scale by an additional 0.5 to soften it
effect.periodic.length = duration_ms;
SDL_HapticUpdateEffect(haptic, sineEffectId, &effect);
SDL_HapticRunEffect(haptic, sineEffectId, 1);
if (intensity != 0 && duration_ms != 0)
{
SDL_HapticEffect effect{};
effect.type = SDL_HAPTIC_SINE;
effect.periodic.direction.type = SDL_HAPTIC_CARTESIAN;
effect.periodic.direction.dir[0] = (vib_stop_time & 1) ? -1 : 1; // west or east randomly
effect.periodic.period = 40; // 25 Hz
effect.periodic.magnitude = intensity / 4; // scale by an additional 0.5 to soften it
effect.periodic.length = duration_ms;
SDL_HapticUpdateEffect(haptic, sineEffectId, &effect);
SDL_HapticRunEffect(haptic, sineEffectId, 1);
}
else {
SDL_HapticStopEffect(haptic, sineEffectId);
}
}
else {
SDL_JoystickRumble(sdl_joystick, intensity, intensity, duration_ms);
Expand Down Expand Up @@ -360,14 +366,20 @@ class SDLGamepad : public GamepadDevice
{
if (haptic == nullptr || constEffectId == -1)
return;
SDL_HapticEffect effect{};
effect.type = SDL_HAPTIC_CONSTANT;
effect.constant.direction.type = SDL_HAPTIC_CARTESIAN;
effect.constant.direction.dir[0] = torque < 0 ? -1 : 1; // west/cw if torque < 0
effect.constant.length = SDL_HAPTIC_INFINITY;
effect.constant.level = std::abs(torque) * 32767.f * rumblePower / 100.f;
SDL_HapticUpdateEffect(haptic, constEffectId, &effect);
SDL_HapticRunEffect(haptic, constEffectId, 1);
if (torque != 0.f && rumblePower != 0)
{
SDL_HapticEffect effect{};
effect.type = SDL_HAPTIC_CONSTANT;
effect.constant.direction.type = SDL_HAPTIC_CARTESIAN;
effect.constant.direction.dir[0] = torque < 0 ? -1 : 1; // west/cw if torque < 0
effect.constant.length = SDL_HAPTIC_INFINITY;
effect.constant.level = std::abs(torque) * 32767.f * rumblePower / 100.f;
SDL_HapticUpdateEffect(haptic, constEffectId, &effect);
SDL_HapticRunEffect(haptic, constEffectId, 1);
}
else {
SDL_HapticStopEffect(haptic, constEffectId);
}
}

void stopHaptic()
Expand All @@ -378,46 +390,66 @@ class SDLGamepad : public GamepadDevice
if (hasAutocenter)
SDL_HapticSetAutocenter(haptic, 0);
}
if (!hapticRumble)
rumble(0, 0, 0);
}

void setSpring(float saturation, float speed)
{
if (haptic == nullptr)
return;
if (springEffectId == -1) {
if (springEffectId == -1)
{
// Spring not supported so use autocenter if available
if (hasAutocenter)
SDL_HapticSetAutocenter(haptic, saturation * rumblePower);
{
if (speed != 0.f)
SDL_HapticSetAutocenter(haptic, saturation * rumblePower);
else
SDL_HapticSetAutocenter(haptic, 0);
}
}
else
{
SDL_HapticEffect effect{};
effect.type = SDL_HAPTIC_SPRING;
effect.condition.length = SDL_HAPTIC_INFINITY;
effect.condition.direction.type = SDL_HAPTIC_CARTESIAN;
// effect level at full deflection
effect.condition.left_sat[0] = effect.condition.right_sat[0] = (saturation * rumblePower / 100.f) * 0xffff;
// how fast to increase the force
effect.condition.left_coeff[0] = effect.condition.right_coeff[0] = speed * 0x7fff;
SDL_HapticUpdateEffect(haptic, springEffectId, &effect);
SDL_HapticRunEffect(haptic, springEffectId, 1);
if (saturation != 0.f && speed != 0.f && rumblePower != 0)
{
SDL_HapticEffect effect{};
effect.type = SDL_HAPTIC_SPRING;
effect.condition.length = SDL_HAPTIC_INFINITY;
effect.condition.direction.type = SDL_HAPTIC_CARTESIAN;
// effect level at full deflection
effect.condition.left_sat[0] = effect.condition.right_sat[0] = (saturation * rumblePower / 100.f) * 0xffff;
// how fast to increase the force
effect.condition.left_coeff[0] = effect.condition.right_coeff[0] = speed * 0x7fff;
SDL_HapticUpdateEffect(haptic, springEffectId, &effect);
SDL_HapticRunEffect(haptic, springEffectId, 1);
}
else {
SDL_HapticStopEffect(haptic, springEffectId);
}
}
}

void setDamper(float param, float speed)
{
if (haptic == nullptr || damperEffectId == -1)
return;
SDL_HapticEffect effect{};
effect.type = SDL_HAPTIC_DAMPER;
effect.condition.length = SDL_HAPTIC_INFINITY;
effect.condition.direction.type = SDL_HAPTIC_CARTESIAN;
// max effect level
effect.condition.left_sat[0] = effect.condition.right_sat[0] = (param * rumblePower / 100.f) * 0xffff;
// how fast to increase the force
effect.condition.left_coeff[0] = effect.condition.right_coeff[0] = speed * 0x7fff;
SDL_HapticUpdateEffect(haptic, damperEffectId, &effect);
SDL_HapticRunEffect(haptic, damperEffectId, 1);
if (param != 0.f && speed != 0.f && rumblePower != 0)
{
SDL_HapticEffect effect{};
effect.type = SDL_HAPTIC_DAMPER;
effect.condition.length = SDL_HAPTIC_INFINITY;
effect.condition.direction.type = SDL_HAPTIC_CARTESIAN;
// max effect level
effect.condition.left_sat[0] = effect.condition.right_sat[0] = (param * rumblePower / 100.f) * 0xffff;
// how fast to increase the force
effect.condition.left_coeff[0] = effect.condition.right_coeff[0] = speed * 0x7fff;
SDL_HapticUpdateEffect(haptic, damperEffectId, &effect);
SDL_HapticRunEffect(haptic, damperEffectId, 1);
}
else {
SDL_HapticStopEffect(haptic, damperEffectId);
}
}

void close()
Expand Down Expand Up @@ -601,31 +633,29 @@ class SDLGamepad : public GamepadDevice
while (!sdl_gamepads.empty())
sdl_gamepads.begin()->second->close();
}
static void UpdateRumble()
{
for (auto& pair : sdl_gamepads)
pair.second->update_rumble();
static void UpdateRumble() {
for (auto &[k, gamepad] : sdl_gamepads)
gamepad->update_rumble();
}

template<typename Func, typename... Args>
static void applyToPort(int port, Func func, Args&&... args)
{
for (auto &[k, gamepad] : sdl_gamepads)
if (gamepad->maple_port() == port)
((*gamepad).*func)(std::forward<Args>(args)...);
}
static void SetTorque(int port, float torque) {
for (auto& pair : sdl_gamepads)
if (pair.second->maple_port() == port)
pair.second->setTorque(torque);
applyToPort(port, &SDLGamepad::setTorque, torque);
}
static void SetSpring(int port, float saturation, float speed) {
for (auto& pair : sdl_gamepads)
if (pair.second->maple_port() == port)
pair.second->setSpring(saturation, speed);
applyToPort(port, &SDLGamepad::setSpring, saturation, speed);
}
static void SetDamper(int port, float param, float speed) {
for (auto& pair : sdl_gamepads)
if (pair.second->maple_port() == port)
pair.second->setDamper(param, speed);
applyToPort(port, &SDLGamepad::setDamper, param, speed);
}
static void StopHaptic(int port) {
for (auto& pair : sdl_gamepads)
if (pair.second->maple_port() == port)
pair.second->stopHaptic();
applyToPort(port, &SDLGamepad::stopHaptic);
}

protected:
Expand Down

0 comments on commit a99aa52

Please sign in to comment.