diff --git a/src/main/java/dev/isxander/controlify/controller/AbstractController.java b/src/main/java/dev/isxander/controlify/controller/AbstractController.java index b910582..0853d72 100644 --- a/src/main/java/dev/isxander/controlify/controller/AbstractController.java +++ b/src/main/java/dev/isxander/controlify/controller/AbstractController.java @@ -8,6 +8,8 @@ import dev.isxander.controlify.ControllerManager; import dev.isxander.controlify.bindings.ControllerBindings; import dev.isxander.controlify.hid.ControllerHIDService; import dev.isxander.controlify.rumble.RumbleCapable; +import dev.isxander.controlify.rumble.RumbleSource; +import dev.isxander.controlify.rumble.RumbleState; import dev.isxander.controlify.utils.Log; import org.apache.commons.lang3.SerializationUtils; import org.lwjgl.glfw.GLFW; @@ -128,6 +130,14 @@ public abstract class AbstractController bindings = new ControllerBindings<>(this); private final RumbleManager rumbleManager = new RumbleManager(new RumbleCapable() { @Override - public boolean setRumble(float strongMagnitude, float weakMagnitude, RumbleSource source) { + public boolean setRumble(float strongMagnitude, float weakMagnitude) { return false; } @@ -62,6 +63,11 @@ public interface Controller e.effect().isFinished()); effectQueue.forEach(e -> e.effect().tick()); - if (silent) { - if (!wasSilent) { - controller.setRumble(0f, 0f, RumbleSource.MASTER); - wasSilent = true; - } - } else { - RumbleState state = effect.effect().currentState(); - controller.setRumble(state.strong(), state.weak(), effect.source()); + if (effectQueue.isEmpty()) { + clearRumble(); + return; } + + float strong = 0f, weak = 0f; + for (RumbleEffectInstance effect : effectQueue) { + RumbleState effectState = controller.applyRumbleSourceStrength(effect.effect().currentState(), effect.source()); + strong = Math.max(strong, effectState.strong()); + weak = Math.max(weak, effectState.weak()); + } + RumbleState state = new RumbleState(strong, weak); + + if (state.isZero()) { + clearRumble(); + return; + } + + if (silent) { + clearRumble(); + } else { + controller.setRumble(state.strong(), state.weak()); + wasSilent = false; + } + } + + private void clearRumble() { + if (wasSilent) + return; + + controller.setRumble(0f, 0f); + wasSilent = true; } public void clearEffects() { diff --git a/src/main/java/dev/isxander/controlify/rumble/RumbleState.java b/src/main/java/dev/isxander/controlify/rumble/RumbleState.java index 924ebd4..3300a4a 100644 --- a/src/main/java/dev/isxander/controlify/rumble/RumbleState.java +++ b/src/main/java/dev/isxander/controlify/rumble/RumbleState.java @@ -3,6 +3,10 @@ package dev.isxander.controlify.rumble; public record RumbleState(float strong, float weak) { public static final RumbleState NONE = new RumbleState(0.0F, 0.0F); + public boolean isZero() { + return strong == 0.0F && weak == 0.0F; + } + public RumbleState mul(float multiplier) { return new RumbleState(strong * multiplier, weak * multiplier); } diff --git a/src/testmod/java/dev/isxander/controlify/test/FakeController.java b/src/testmod/java/dev/isxander/controlify/test/FakeController.java index a90630e..bcdcb2b 100644 --- a/src/testmod/java/dev/isxander/controlify/test/FakeController.java +++ b/src/testmod/java/dev/isxander/controlify/test/FakeController.java @@ -14,6 +14,7 @@ import dev.isxander.controlify.controller.joystick.mapping.UnmappedJoystickMappi import dev.isxander.controlify.rumble.RumbleCapable; import dev.isxander.controlify.rumble.RumbleManager; import dev.isxander.controlify.rumble.RumbleSource; +import dev.isxander.controlify.rumble.RumbleState; import java.util.List; import java.util.Optional; @@ -41,7 +42,7 @@ public class FakeController implements JoystickController { this.config = new JoystickConfig(this); this.rumbleManager = new RumbleManager(new RumbleCapable() { @Override - public boolean setRumble(float strongMagnitude, float weakMagnitude, RumbleSource source) { + public boolean setRumble(float strongMagnitude, float weakMagnitude) { return false; } @@ -49,6 +50,11 @@ public class FakeController implements JoystickController { public boolean supportsRumble() { return false; } + + @Override + public RumbleState applyRumbleSourceStrength(RumbleState state, RumbleSource source) { + return state; + } }); this.config.deadzonesCalibrated = true; }