forked from Clones/Controlify
✏️ Lazily ask for vibration natives once controller plugged in (close #63)
This commit is contained in:
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 void initializeControllers() {
|
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 -> {
|
||||||
|
@ -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))
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
Reference in New Issue
Block a user