1
0
forked from Clones/Controlify
Files
Controlify/src/main/java/dev/isxander/controlify/controller/gamepad/GamepadController.java
2023-07-10 17:05:43 +01:00

158 lines
5.9 KiB
Java

package dev.isxander.controlify.controller.gamepad;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.bindings.ControllerBindings;
import dev.isxander.controlify.controller.AbstractController;
import dev.isxander.controlify.controller.BatteryLevel;
import dev.isxander.controlify.controller.hid.ControllerHIDService;
import dev.isxander.controlify.debug.DebugProperties;
import dev.isxander.controlify.driver.*;
import dev.isxander.controlify.rumble.RumbleManager;
import dev.isxander.controlify.rumble.RumbleSource;
import dev.isxander.controlify.utils.ControllerUtils;
import dev.isxander.controlify.utils.Log;
import net.minecraft.resources.ResourceLocation;
import org.lwjgl.glfw.GLFW;
import java.util.Set;
public class GamepadController extends AbstractController<GamepadState, GamepadConfig> {
private GamepadState state = GamepadState.EMPTY;
private GamepadState prevState = GamepadState.EMPTY;
private final RumbleManager rumbleManager;
private GamepadState.GyroState absoluteGyro = new GamepadState.GyroState();
public final GamepadDrivers drivers;
private final Set<Driver> uniqueDrivers;
private int antiSnapbackTicksL, antiSnapbackTicksR;
public GamepadController(int joystickId, ControllerHIDService.ControllerHIDInfo hidInfo) {
super(joystickId, hidInfo);
if (!GLFW.glfwJoystickIsGamepad(joystickId))
throw new IllegalArgumentException("Joystick " + joystickId + " is not a gamepad!");
this.drivers = GamepadDrivers.forController(joystickId, hidInfo.hidDevice());
this.uniqueDrivers = drivers.getUniqueDrivers();
this.drivers.printDrivers();
if (!this.name.startsWith(type().friendlyName()))
setName(this.drivers.nameProviderDriver().getName());
this.rumbleManager = new RumbleManager(this);
this.defaultConfig = new GamepadConfig();
this.config = new GamepadConfig();
if (hidInfo.hidDevice().map(hid -> SteamDeckDriver.isSteamDeck(hid.getVendorId(), hid.getProductId())).orElse(false)) {
this.defaultConfig.mixedInput = true;
this.config.mixedInput = true;
}
this.bindings = new ControllerBindings<>(this);
}
@Override
public GamepadState state() {
return state;
}
@Override
public GamepadState prevState() {
return prevState;
}
@Override
public void updateState() {
prevState = state;
uniqueDrivers.forEach(Driver::update);
BasicGamepadInputDriver.BasicGamepadState basicState = drivers.basicGamepadInputDriver().getBasicGamepadState();
GamepadState.AxesState deadzoneAxesState = basicState.axes()
.leftJoystickDeadZone(config().getLeftStickDeadzone())
.rightJoystickDeadZone(config().getRightStickDeadzone());
if (DebugProperties.USE_SNAPBACK) {
if (antiSnapbackTicksL > 0) {
deadzoneAxesState = deadzoneAxesState.neutraliseLeft();
antiSnapbackTicksL--;
} else if (ControllerUtils.shouldApplyAntiSnapBack(deadzoneAxesState.leftStickX(), deadzoneAxesState.leftStickY(), prevState.gamepadAxes().leftStickX(), prevState.gamepadAxes().leftStickY(), 0.08f)) {
antiSnapbackTicksL = 2;
deadzoneAxesState = deadzoneAxesState.neutraliseLeft();
}
if (antiSnapbackTicksR > 0) {
deadzoneAxesState = deadzoneAxesState.neutraliseRight();
antiSnapbackTicksR--;
} else if (ControllerUtils.shouldApplyAntiSnapBack(deadzoneAxesState.rightStickX(), deadzoneAxesState.rightStickY(), prevState.gamepadAxes().rightStickX(), prevState.gamepadAxes().rightStickY(), 0.08f)) {
antiSnapbackTicksR = 2;
deadzoneAxesState = deadzoneAxesState.neutraliseRight();
}
}
// TODO: Add some sort of gyro filtering
GamepadState.GyroState gyroState = new GamepadState.GyroState(drivers.gyroDriver().getGyroState()).sub(config().gyroCalibration);
this.absoluteGyro.add(gyroState);
state = new GamepadState(deadzoneAxesState, basicState.axes(), basicState.buttons(), gyroState, absoluteGyro);
if (DebugProperties.PRINT_TRIGGER_STATE) {
Log.LOGGER.info("Left Trigger: " + state.gamepadAxes().leftTrigger());
Log.LOGGER.info("Right Trigger: " + state.gamepadAxes().rightTrigger());
}
}
public GamepadState.GyroState absoluteGyroState() {
return absoluteGyro;
}
public boolean hasGyro() {
return drivers.gyroDriver().isGyroSupported();
}
@Override
public void clearState() {
state = GamepadState.EMPTY;
}
@Override
public boolean setRumble(float strongMagnitude, float weakMagnitude, RumbleSource source) {
if (!supportsRumble() || !config().allowVibrations) return false;
var strengthMod = config().getRumbleStrength(source);
if (source != RumbleSource.MASTER)
strengthMod *= config().getRumbleStrength(RumbleSource.MASTER);
strongMagnitude *= strengthMod;
weakMagnitude *= strengthMod;
return drivers.rumbleDriver().rumble(Math.min(strongMagnitude, 1), Math.min(weakMagnitude, 1));
}
@Override
public boolean supportsRumble() {
return drivers.rumbleDriver().isRumbleSupported();
}
@Override
public RumbleManager rumbleManager() {
return this.rumbleManager;
}
@Override
public BatteryLevel batteryLevel() {
return drivers.batteryDriver().getBatteryLevel();
}
@Override
public void close() {
uniqueDrivers.forEach(Driver::close);
}
@Override
public ResourceLocation icon() {
String theme = config().theme == BuiltinGamepadTheme.DEFAULT ? type().themeId() : config().theme.id();
return Controlify.id("textures/gui/gamepad/" + theme + "/icon.png");
}
}