forked from Clones/Controlify
better theme handling and better mouse hide handling (still not perfect)
This commit is contained in:
@ -48,8 +48,8 @@ public class Controlify {
|
||||
|
||||
controllerHIDService.start();
|
||||
|
||||
// load after initial controller discovery
|
||||
config().load();
|
||||
config().load(); // load after initial controller discovery
|
||||
config().save(); // save new controller configs if they don't exist
|
||||
|
||||
// listen for new controllers
|
||||
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
||||
@ -148,7 +148,8 @@ public class Controlify {
|
||||
this.currentInputMode = currentInputMode;
|
||||
|
||||
var minecraft = Minecraft.getInstance();
|
||||
hideMouse(currentInputMode == InputMode.CONTROLLER);
|
||||
if (!minecraft.mouseHandler.isMouseGrabbed())
|
||||
hideMouse(currentInputMode == InputMode.CONTROLLER);
|
||||
if (minecraft.screen != null) {
|
||||
ScreenProcessorProvider.provide(minecraft.screen).onInputModeChanged(currentInputMode);
|
||||
}
|
||||
@ -170,7 +171,7 @@ public class Controlify {
|
||||
if (hide && !virtualMouseHandler().isVirtualMouseEnabled()) {
|
||||
// stop mouse hovering over last element before hiding cursor but don't actually move it
|
||||
// so when the user switches back to mouse it will be in the same place
|
||||
mouseHandlerAccessor.invokeOnMove(minecraft.getWindow().getWindow(), 0, 0);
|
||||
mouseHandlerAccessor.invokeOnMove(minecraft.getWindow().getWindow(), -50, -50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public enum Bind {
|
||||
}
|
||||
|
||||
public ResourceLocation textureLocation(Controller controller) {
|
||||
return new ResourceLocation("controlify", "textures/gui/buttons/" + controller.config().theme.id(controller) + "/" + identifier + ".png");
|
||||
return new ResourceLocation("controlify", "textures/gui/buttons/" + controller.config().theme.id() + "/" + identifier + ".png");
|
||||
}
|
||||
|
||||
public static Bind fromIdentifier(String identifier) {
|
||||
|
@ -1,28 +0,0 @@
|
||||
package dev.isxander.controlify.bindings;
|
||||
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.yacl.api.NameableEnum;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public enum ControllerTheme implements NameableEnum {
|
||||
AUTO(c -> c.type().theme().id(c)),
|
||||
XBOX_ONE(c -> "xbox"),
|
||||
DUALSHOCK4(c -> "dualshock4");
|
||||
|
||||
private final Function<Controller, String> idGetter;
|
||||
|
||||
ControllerTheme(Function<Controller, String> idGetter) {
|
||||
this.idGetter = idGetter;
|
||||
}
|
||||
|
||||
public String id(Controller controller) {
|
||||
return idGetter.apply(controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return Component.translatable("controlify.controller_theme." + name().toLowerCase());
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ package dev.isxander.controlify.config;
|
||||
import com.google.gson.*;
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.controller.ControllerConfig;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -93,7 +92,7 @@ public class ControlifyConfig {
|
||||
}
|
||||
|
||||
private void applyControllerConfig(Controller controller, JsonObject object) {
|
||||
controller.setConfig(GSON.fromJson(object.getAsJsonObject("config"), ControllerConfig.class));
|
||||
controller.setConfig(GSON.fromJson(object.getAsJsonObject("config"), Controller.ControllerConfig.class));
|
||||
controller.bindings().fromJson(object.getAsJsonObject("bindings"));
|
||||
}
|
||||
|
||||
|
@ -2,19 +2,17 @@ package dev.isxander.controlify.config.gui;
|
||||
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import dev.isxander.controlify.bindings.Bind;
|
||||
import dev.isxander.controlify.bindings.ControllerTheme;
|
||||
import dev.isxander.controlify.config.GlobalSettings;
|
||||
import dev.isxander.controlify.controller.ControllerTheme;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.controller.ControllerConfig;
|
||||
import dev.isxander.yacl.api.*;
|
||||
import dev.isxander.yacl.gui.controllers.TickBoxController;
|
||||
import dev.isxander.yacl.gui.controllers.cycling.CyclingListController;
|
||||
import dev.isxander.yacl.gui.controllers.cycling.EnumController;
|
||||
import dev.isxander.yacl.gui.controllers.slider.FloatSliderController;
|
||||
import dev.isxander.yacl.gui.controllers.slider.IntegerSliderController;
|
||||
import dev.isxander.yacl.gui.controllers.string.StringController;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.locale.Language;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class YACLHelper {
|
||||
@ -33,13 +31,6 @@ public class YACLHelper {
|
||||
.binding(Controlify.instance().currentController(), () -> Controlify.instance().currentController(), v -> Controlify.instance().setCurrentController(v))
|
||||
.controller(opt -> new CyclingListController<>(opt, Controller.CONTROLLERS.values().stream().filter(Controller::connected).toList(), c -> Component.literal(c.name())))
|
||||
.instant(true)
|
||||
.build())
|
||||
.option(ListOption.createBuilder(String.class)
|
||||
.name(Component.translatable("controlify.gui.vmouse_screens"))
|
||||
.tooltip(Component.translatable("controlify.gui.vmouse_screens.tooltip"))
|
||||
.binding(GlobalSettings.DEFAULT.virtualMouseScreens, () -> controlify.config().globalSettings().virtualMouseScreens, v -> controlify.config().globalSettings().virtualMouseScreens = v)
|
||||
.controller(StringController::new)
|
||||
.initial(Language.getInstance().getOrDefault("controlify.gui.vmouse_screens.placeholder"))
|
||||
.build());
|
||||
|
||||
yacl.category(globalCategory.build());
|
||||
@ -51,7 +42,7 @@ public class YACLHelper {
|
||||
category.name(Component.literal(customName == null ? controller.name() : customName));
|
||||
|
||||
var config = controller.config();
|
||||
var def = ControllerConfig.DEFAULT;
|
||||
var def = controller.defaultConfig();
|
||||
var configGroup = OptionGroup.createBuilder()
|
||||
.name(Component.translatable("controlify.gui.group.config"))
|
||||
.tooltip(Component.translatable("controlify.gui.group.config.tooltip"))
|
||||
@ -108,7 +99,7 @@ public class YACLHelper {
|
||||
.option(Option.createBuilder(ControllerTheme.class)
|
||||
.name(Component.translatable("controlify.gui.controller_theme"))
|
||||
.tooltip(Component.translatable("controlify.gui.controller_theme.tooltip"))
|
||||
.binding(def.theme, () -> config.theme, v -> config.theme = v)
|
||||
.binding(controller.type().theme(), () -> config.theme, v -> config.theme = v)
|
||||
.controller(EnumController::new)
|
||||
.instant(true)
|
||||
.build());
|
||||
|
@ -1,7 +1,6 @@
|
||||
package dev.isxander.controlify.controller;
|
||||
|
||||
import dev.isxander.controlify.bindings.ControllerBindings;
|
||||
import dev.isxander.controlify.bindings.ControllerTheme;
|
||||
import dev.isxander.controlify.controller.hid.HIDIdentifier;
|
||||
import dev.isxander.controlify.event.ControlifyEvents;
|
||||
import org.hid4java.HidDevice;
|
||||
@ -27,7 +26,7 @@ public final class Controller {
|
||||
private ControllerState prevState = ControllerState.EMPTY;
|
||||
|
||||
private final ControllerBindings bindings = new ControllerBindings(this);
|
||||
private ControllerConfig config = new ControllerConfig();
|
||||
private ControllerConfig config, defaultConfig;
|
||||
|
||||
public Controller(int joystickId, String guid, String name, boolean gamepad, String uid, ControllerType type) {
|
||||
this.joystickId = joystickId;
|
||||
@ -36,6 +35,8 @@ public final class Controller {
|
||||
this.gamepad = gamepad;
|
||||
this.uid = uid;
|
||||
this.type = type;
|
||||
this.config = new ControllerConfig();
|
||||
this.defaultConfig = new ControllerConfig();
|
||||
}
|
||||
|
||||
public ControllerState state() {
|
||||
@ -110,6 +111,10 @@ public final class Controller {
|
||||
return config;
|
||||
}
|
||||
|
||||
public ControllerConfig defaultConfig() {
|
||||
return defaultConfig;
|
||||
}
|
||||
|
||||
public void setConfig(ControllerConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
@ -150,4 +155,26 @@ public final class Controller {
|
||||
return controller;
|
||||
}
|
||||
|
||||
public class ControllerConfig {
|
||||
public float horizontalLookSensitivity = 1f;
|
||||
public float verticalLookSensitivity = 0.9f;
|
||||
|
||||
public float leftStickDeadzone = 0.2f;
|
||||
public float rightStickDeadzone = 0.2f;
|
||||
|
||||
// not sure if triggers need deadzones
|
||||
public float leftTriggerDeadzone = 0.0f;
|
||||
public float rightTriggerDeadzone = 0.0f;
|
||||
|
||||
public float leftTriggerActivationThreshold = 0.5f;
|
||||
public float rightTriggerActivationThreshold = 0.5f;
|
||||
|
||||
public int screenRepeatNavigationDelay = 4;
|
||||
|
||||
public float virtualMouseSensitivity = 1f;
|
||||
|
||||
public ControllerTheme theme = type().theme();
|
||||
|
||||
public String customName = null;
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
package dev.isxander.controlify.controller;
|
||||
|
||||
import dev.isxander.controlify.bindings.ControllerTheme;
|
||||
|
||||
public class ControllerConfig {
|
||||
public static final ControllerConfig DEFAULT = new ControllerConfig();
|
||||
|
||||
public float horizontalLookSensitivity = 1f;
|
||||
public float verticalLookSensitivity = 0.9f;
|
||||
|
||||
public float leftStickDeadzone = 0.2f;
|
||||
public float rightStickDeadzone = 0.2f;
|
||||
|
||||
// not sure if triggers need deadzones
|
||||
public float leftTriggerDeadzone = 0.0f;
|
||||
public float rightTriggerDeadzone = 0.0f;
|
||||
|
||||
public float leftTriggerActivationThreshold = 0.5f;
|
||||
public float rightTriggerActivationThreshold = 0.5f;
|
||||
|
||||
public int screenRepeatNavigationDelay = 4;
|
||||
|
||||
public float virtualMouseSensitivity = 1f;
|
||||
|
||||
public ControllerTheme theme = ControllerTheme.AUTO;
|
||||
|
||||
public String customName = null;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package dev.isxander.controlify.controller;
|
||||
|
||||
import dev.isxander.yacl.api.NameableEnum;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public enum ControllerTheme implements NameableEnum {
|
||||
XBOX_ONE("xbox"),
|
||||
DUALSHOCK4("dualshock4");
|
||||
|
||||
private final String id;
|
||||
|
||||
ControllerTheme(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return Component.translatable("controlify.controller_theme." + name().toLowerCase());
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ package dev.isxander.controlify.controller;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import dev.isxander.controlify.bindings.ControllerTheme;
|
||||
import dev.isxander.controlify.controller.hid.HIDIdentifier;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
|
@ -2,6 +2,7 @@ package dev.isxander.controlify.mixins.feature.virtualmouse;
|
||||
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
@ -14,4 +15,7 @@ public interface MouseHandlerAccessor {
|
||||
|
||||
@Invoker
|
||||
void invokeOnScroll(long window, double scrollDeltaX, double scrollDeltaY);
|
||||
|
||||
@Accessor
|
||||
void setMouseGrabbed(boolean mouseGrabbed);
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
package dev.isxander.controlify.mixins.feature.virtualmouse;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.WrapWithCondition;
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import dev.isxander.controlify.InputMode;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public class MouseHandlerMixin {
|
||||
@WrapWithCondition(method = "releaseMouse", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/InputConstants;grabOrReleaseMouse(JIDD)V"))
|
||||
private boolean shouldReleaseMouse(long window, int newMouseState, double x, double y) {
|
||||
// mouse cursor appears for a split second when going into guis on controller input
|
||||
return Controlify.instance().currentInputMode() != InputMode.CONTROLLER;
|
||||
}
|
||||
}
|
@ -102,7 +102,8 @@ public class VirtualMouseHandler {
|
||||
GLFW.glfwSetInputMode(minecraft.getWindow().getWindow(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_HIDDEN);
|
||||
} else if (virtualMouseEnabled) {
|
||||
disableVirtualMouse();
|
||||
minecraft.mouseHandler.grabMouse();
|
||||
|
||||
minecraft.mouseHandler.grabMouse(); // re-grab mouse after vmouse disable
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,7 +128,7 @@ public class VirtualMouseHandler {
|
||||
var scaledY = currentY * (double)this.minecraft.getWindow().getGuiScaledHeight() / (double)this.minecraft.getWindow().getScreenHeight();
|
||||
|
||||
matrices.pushPose();
|
||||
matrices.translate(scaledX, scaledY, 0);
|
||||
matrices.translate(scaledX, scaledY, 1000f);
|
||||
matrices.scale(0.5f, 0.5f, 0.5f);
|
||||
|
||||
GuiComponent.blit(matrices, -16, -16, 0, 0, 32, 32, 32, 32);
|
||||
@ -158,6 +159,9 @@ public class VirtualMouseHandler {
|
||||
public void disableVirtualMouse() {
|
||||
if (!virtualMouseEnabled) return;
|
||||
|
||||
// make sure minecraft doesn't think the mouse is grabbed when it isn't
|
||||
((MouseHandlerAccessor) minecraft.mouseHandler).setMouseGrabbed(false);
|
||||
|
||||
GLFW.glfwSetInputMode(minecraft.getWindow().getWindow(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL);
|
||||
setMousePosition();
|
||||
virtualMouseEnabled = false;
|
||||
|
Reference in New Issue
Block a user