1
0
forked from Clones/Controlify

✏️ Lazily ask for vibration natives once controller plugged in (close #63)

This commit is contained in:
isXander
2023-05-05 17:16:15 +01:00
parent 63c3816a21
commit 834b7e9f6f
4 changed files with 56 additions and 28 deletions

View File

@ -40,9 +40,10 @@ import org.lwjgl.glfw.GLFW;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import java.util.stream.IntStream;
public class Controlify implements ControlifyApi { public class Controlify implements ControlifyApi {
public static final Logger LOGGER = LogUtils.getLogger(); public static final Logger LOGGER = LogUtils.getLogger();
@ -57,6 +58,8 @@ public class Controlify implements ControlifyApi {
private InputMode currentInputMode = InputMode.KEYBOARD_MOUSE; private InputMode currentInputMode = InputMode.KEYBOARD_MOUSE;
private ControllerHIDService controllerHIDService; private ControllerHIDService controllerHIDService;
private CompletableFuture<Boolean> vibrationOnboardingFuture = null;
private final ControlifyConfig config = new ControlifyConfig(this); private final ControlifyConfig config = new ControlifyConfig(this);
private final Queue<Controller<?, ?>> calibrationQueue = new ArrayDeque<>(); private final Queue<Controller<?, ?>> calibrationQueue = new ArrayDeque<>();
@ -73,17 +76,49 @@ public class Controlify implements ControlifyApi {
config().load(); config().load();
if (!config().globalSettings().vibrationOnboarded) { var controllersConnected = IntStream.range(0, GLFW.GLFW_JOYSTICK_LAST + 1).anyMatch(GLFW::glfwJoystickPresent);
minecraft.setScreen(new VibrationOnboardingScreen( if (controllersConnected) {
minecraft.screen, askVibrationNatives().whenComplete((loaded, th) -> discoverControllers());
answer -> this.initializeControllers()
));
} else {
this.initializeControllers();
}
} }
private void initializeControllers() { // listen for new controllers
GLFW.glfwSetJoystickCallback((jid, event) -> {
try {
this.askVibrationNatives().whenComplete((loaded, th) -> {
if (event == GLFW.GLFW_CONNECTED) {
this.onControllerHotplugged(jid);
} else if (event == GLFW.GLFW_DISCONNECTED) {
this.onControllerDisconnect(jid);
}
});
} catch (Exception e) {
e.printStackTrace();
}
});
}
private CompletableFuture<Boolean> askVibrationNatives() {
if (vibrationOnboardingFuture != null) return vibrationOnboardingFuture;
if (config().globalSettings().vibrationOnboarded) {
return CompletableFuture.completedFuture(config().globalSettings().loadVibrationNatives);
}
vibrationOnboardingFuture = new CompletableFuture<>();
minecraft.setScreen(new VibrationOnboardingScreen(
minecraft.screen,
answer -> {
if (answer)
SDL2NativesManager.initialise();
vibrationOnboardingFuture.complete(answer);
}
));
return vibrationOnboardingFuture;
}
private void discoverControllers() {
DebugLog.log("Discovering and initializing controllers..."); DebugLog.log("Discovering and initializing controllers...");
if (config().globalSettings().loadVibrationNatives) if (config().globalSettings().loadVibrationNatives)
@ -123,19 +158,6 @@ public class Controlify implements ControlifyApi {
config().saveIfDirty(); config().saveIfDirty();
} }
// listen for new controllers
GLFW.glfwSetJoystickCallback((jid, event) -> {
try {
if (event == GLFW.GLFW_CONNECTED) {
this.onControllerHotplugged(jid);
} else if (event == GLFW.GLFW_DISCONNECTED) {
this.onControllerDisconnect(jid);
}
} catch (Exception e) {
e.printStackTrace();
}
});
ClientTickEvents.START_CLIENT_TICK.register(this::tick); ClientTickEvents.START_CLIENT_TICK.register(this::tick);
FabricLoader.getInstance().getEntrypoints("controlify", ControlifyEntrypoint.class).forEach(entrypoint -> { FabricLoader.getInstance().getEntrypoints("controlify", ControlifyEntrypoint.class).forEach(entrypoint -> {

View File

@ -19,7 +19,7 @@ public class DebugProperties {
/* Print gyro data if supported */ /* Print gyro data if supported */
public static final boolean PRINT_GYRO = boolProp("controlify.debug.print_gyro", false, false); public static final boolean PRINT_GYRO = boolProp("controlify.debug.print_gyro", false, false);
/* Print what drivers are being used */ /* Print what drivers are being used */
public static final boolean PRINT_DRIVER = boolProp("controlify.debug.print_driver", false, true); public static final boolean PRINT_DRIVER = boolProp("controlify.debug.print_driver", true, true);
public static void printProperties() { public static void printProperties() {
if (properties.stream().noneMatch(DebugProperty::enabled)) if (properties.stream().noneMatch(DebugProperty::enabled))

View File

@ -36,7 +36,7 @@ public record GamepadDrivers(BasicGamepadInputDriver basicGamepadInputDriver, Gy
} }
// broken // broken
if (hid.isPresent() && SteamDeckDriver.isSteamDeck(hid.get()) && false) { if (hid.isPresent() && SteamDeckDriver.isSteamDeck(hid.get())) {
gyroDriver = new SteamDeckDriver(hid.get()); gyroDriver = new SteamDeckDriver(hid.get());
} }

View File

@ -5,12 +5,15 @@ import dev.isxander.controlify.controller.gamepad.GamepadState;
import dev.isxander.controlify.controller.hid.HIDIdentifier; import dev.isxander.controlify.controller.hid.HIDIdentifier;
import org.hid4java.HidDevice; import org.hid4java.HidDevice;
import java.util.Arrays;
public class SteamDeckDriver implements GyroDriver, BasicGamepadInputDriver { public class SteamDeckDriver implements GyroDriver, BasicGamepadInputDriver {
private static final int cInputRecordLen = 8; // Number of bytes that are read from the hid device per 1 byte of HID private static final int cInputRecordLen = 8; // Number of bytes that are read from the hid device per 1 byte of HID
private static final int cByteposInput = 4; // Position in the raw hid data where HID data byte is private static final int cByteposInput = 4; // Position in the raw hid data where HID data byte is
private static final byte[] startMarker = new byte[] { 0x01, 0x00, 0x09, 0x40 }; // Beginning of every Steam deck HID frame private static final byte[] startMarker = new byte[] { 0x01, 0x00, 0x09, 0x40 }; // Beginning of every Steam deck HID frame
private final HidDevice hidDevice; private final HidDevice hidDevice;
private int interval = 0;
private GamepadState.GyroState gyroDelta = GamepadState.GyroState.ORIGIN; private GamepadState.GyroState gyroDelta = GamepadState.GyroState.ORIGIN;
private BasicGamepadState basicGamepadState = new BasicGamepadState(GamepadState.AxesState.EMPTY, GamepadState.ButtonState.EMPTY); private BasicGamepadState basicGamepadState = new BasicGamepadState(GamepadState.AxesState.EMPTY, GamepadState.ButtonState.EMPTY);
@ -23,7 +26,9 @@ public class SteamDeckDriver implements GyroDriver, BasicGamepadInputDriver {
@Override @Override
public void update() { public void update() {
sendSomething(); if (interval == 0)
keepAlive();
interval = (interval + 1) % 120;
byte[] data = new byte[64]; byte[] data = new byte[64];
int readCnt = hidDevice.read(data); int readCnt = hidDevice.read(data);
@ -35,6 +40,8 @@ public class SteamDeckDriver implements GyroDriver, BasicGamepadInputDriver {
Controlify.LOGGER.warn("Error reading data."); Controlify.LOGGER.warn("Error reading data.");
} }
System.out.println(Arrays.toString(data));
if (!checkData(data, readCnt)) return; if (!checkData(data, readCnt)) return;
Frame frame = Frame.fromBytes(data); Frame frame = Frame.fromBytes(data);
@ -42,9 +49,8 @@ public class SteamDeckDriver implements GyroDriver, BasicGamepadInputDriver {
readFrame(frame); readFrame(frame);
} }
private void sendSomething() { private void keepAlive() {
hidDevice.getFeatureReport(new byte[]{ (byte) 0x89 }, (byte) 0x0); hidDevice.sendFeatureReport(new byte[0], (byte) 8);
hidDevice.write(new byte[]{ (byte) 0x89 }, 2, (byte) 0x0);
} }
private void readFrame(Frame frame) { private void readFrame(Frame frame) {