sdl: don't run null haptic effects. Stop effects instead

Tentative fix for Issue #1766
This commit is contained in:
Flyinghead 2024-12-07 18:57:40 +01:00
parent 89abb7925b
commit a99aa5217b
1 changed files with 85 additions and 55 deletions

View File

@ -311,15 +311,21 @@ public:
const u16 intensity = getRumbleIntensity(power); const u16 intensity = getRumbleIntensity(power);
if (hapticRumble) if (hapticRumble)
{ {
SDL_HapticEffect effect{}; if (intensity != 0 && duration_ms != 0)
effect.type = SDL_HAPTIC_SINE; {
effect.periodic.direction.type = SDL_HAPTIC_CARTESIAN; SDL_HapticEffect effect{};
effect.periodic.direction.dir[0] = (vib_stop_time & 1) ? -1 : 1; // west or east randomly effect.type = SDL_HAPTIC_SINE;
effect.periodic.period = 40; // 25 Hz effect.periodic.direction.type = SDL_HAPTIC_CARTESIAN;
effect.periodic.magnitude = intensity / 4; // scale by an additional 0.5 to soften it effect.periodic.direction.dir[0] = (vib_stop_time & 1) ? -1 : 1; // west or east randomly
effect.periodic.length = duration_ms; effect.periodic.period = 40; // 25 Hz
SDL_HapticUpdateEffect(haptic, sineEffectId, &effect); effect.periodic.magnitude = intensity / 4; // scale by an additional 0.5 to soften it
SDL_HapticRunEffect(haptic, sineEffectId, 1); effect.periodic.length = duration_ms;
SDL_HapticUpdateEffect(haptic, sineEffectId, &effect);
SDL_HapticRunEffect(haptic, sineEffectId, 1);
}
else {
SDL_HapticStopEffect(haptic, sineEffectId);
}
} }
else { else {
SDL_JoystickRumble(sdl_joystick, intensity, intensity, duration_ms); SDL_JoystickRumble(sdl_joystick, intensity, intensity, duration_ms);
@ -360,14 +366,20 @@ public:
{ {
if (haptic == nullptr || constEffectId == -1) if (haptic == nullptr || constEffectId == -1)
return; return;
SDL_HapticEffect effect{}; if (torque != 0.f && rumblePower != 0)
effect.type = SDL_HAPTIC_CONSTANT; {
effect.constant.direction.type = SDL_HAPTIC_CARTESIAN; SDL_HapticEffect effect{};
effect.constant.direction.dir[0] = torque < 0 ? -1 : 1; // west/cw if torque < 0 effect.type = SDL_HAPTIC_CONSTANT;
effect.constant.length = SDL_HAPTIC_INFINITY; effect.constant.direction.type = SDL_HAPTIC_CARTESIAN;
effect.constant.level = std::abs(torque) * 32767.f * rumblePower / 100.f; effect.constant.direction.dir[0] = torque < 0 ? -1 : 1; // west/cw if torque < 0
SDL_HapticUpdateEffect(haptic, constEffectId, &effect); effect.constant.length = SDL_HAPTIC_INFINITY;
SDL_HapticRunEffect(haptic, constEffectId, 1); 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() void stopHaptic()
@ -378,29 +390,43 @@ public:
if (hasAutocenter) if (hasAutocenter)
SDL_HapticSetAutocenter(haptic, 0); SDL_HapticSetAutocenter(haptic, 0);
} }
if (!hapticRumble)
rumble(0, 0, 0);
} }
void setSpring(float saturation, float speed) void setSpring(float saturation, float speed)
{ {
if (haptic == nullptr) if (haptic == nullptr)
return; return;
if (springEffectId == -1) { if (springEffectId == -1)
{
// Spring not supported so use autocenter if available // Spring not supported so use autocenter if available
if (hasAutocenter) if (hasAutocenter)
SDL_HapticSetAutocenter(haptic, saturation * rumblePower); {
if (speed != 0.f)
SDL_HapticSetAutocenter(haptic, saturation * rumblePower);
else
SDL_HapticSetAutocenter(haptic, 0);
}
} }
else else
{ {
SDL_HapticEffect effect{}; if (saturation != 0.f && speed != 0.f && rumblePower != 0)
effect.type = SDL_HAPTIC_SPRING; {
effect.condition.length = SDL_HAPTIC_INFINITY; SDL_HapticEffect effect{};
effect.condition.direction.type = SDL_HAPTIC_CARTESIAN; effect.type = SDL_HAPTIC_SPRING;
// effect level at full deflection effect.condition.length = SDL_HAPTIC_INFINITY;
effect.condition.left_sat[0] = effect.condition.right_sat[0] = (saturation * rumblePower / 100.f) * 0xffff; effect.condition.direction.type = SDL_HAPTIC_CARTESIAN;
// how fast to increase the force // effect level at full deflection
effect.condition.left_coeff[0] = effect.condition.right_coeff[0] = speed * 0x7fff; effect.condition.left_sat[0] = effect.condition.right_sat[0] = (saturation * rumblePower / 100.f) * 0xffff;
SDL_HapticUpdateEffect(haptic, springEffectId, &effect); // how fast to increase the force
SDL_HapticRunEffect(haptic, springEffectId, 1); 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);
}
} }
} }
@ -408,16 +434,22 @@ public:
{ {
if (haptic == nullptr || damperEffectId == -1) if (haptic == nullptr || damperEffectId == -1)
return; return;
SDL_HapticEffect effect{}; if (param != 0.f && speed != 0.f && rumblePower != 0)
effect.type = SDL_HAPTIC_DAMPER; {
effect.condition.length = SDL_HAPTIC_INFINITY; SDL_HapticEffect effect{};
effect.condition.direction.type = SDL_HAPTIC_CARTESIAN; effect.type = SDL_HAPTIC_DAMPER;
// max effect level effect.condition.length = SDL_HAPTIC_INFINITY;
effect.condition.left_sat[0] = effect.condition.right_sat[0] = (param * rumblePower / 100.f) * 0xffff; effect.condition.direction.type = SDL_HAPTIC_CARTESIAN;
// how fast to increase the force // max effect level
effect.condition.left_coeff[0] = effect.condition.right_coeff[0] = speed * 0x7fff; effect.condition.left_sat[0] = effect.condition.right_sat[0] = (param * rumblePower / 100.f) * 0xffff;
SDL_HapticUpdateEffect(haptic, damperEffectId, &effect); // how fast to increase the force
SDL_HapticRunEffect(haptic, damperEffectId, 1); 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() void close()
@ -601,31 +633,29 @@ public:
while (!sdl_gamepads.empty()) while (!sdl_gamepads.empty())
sdl_gamepads.begin()->second->close(); sdl_gamepads.begin()->second->close();
} }
static void UpdateRumble() static void UpdateRumble() {
{ for (auto &[k, gamepad] : sdl_gamepads)
for (auto& pair : sdl_gamepads) gamepad->update_rumble();
pair.second->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) { static void SetTorque(int port, float torque) {
for (auto& pair : sdl_gamepads) applyToPort(port, &SDLGamepad::setTorque, torque);
if (pair.second->maple_port() == port)
pair.second->setTorque(torque);
} }
static void SetSpring(int port, float saturation, float speed) { static void SetSpring(int port, float saturation, float speed) {
for (auto& pair : sdl_gamepads) applyToPort(port, &SDLGamepad::setSpring, saturation, speed);
if (pair.second->maple_port() == port)
pair.second->setSpring(saturation, speed);
} }
static void SetDamper(int port, float param, float speed) { static void SetDamper(int port, float param, float speed) {
for (auto& pair : sdl_gamepads) applyToPort(port, &SDLGamepad::setDamper, param, speed);
if (pair.second->maple_port() == port)
pair.second->setDamper(param, speed);
} }
static void StopHaptic(int port) { static void StopHaptic(int port) {
for (auto& pair : sdl_gamepads) applyToPort(port, &SDLGamepad::stopHaptic);
if (pair.second->maple_port() == port)
pair.second->stopHaptic();
} }
protected: protected: