From ee774dcfeed3bbdff3ac4c365a8e7d4242102f9f Mon Sep 17 00:00:00 2001 From: isXander Date: Fri, 3 Feb 2023 20:57:42 +0000 Subject: [PATCH] better theme handling and better mouse hide handling (still not perfect) --- .../dev/isxander/controlify/Controlify.java | 9 +++--- .../isxander/controlify/bindings/Bind.java | 2 +- .../controlify/bindings/ControllerTheme.java | 28 ----------------- .../controlify/config/ControlifyConfig.java | 3 +- .../controlify/config/gui/YACLHelper.java | 17 +++------- .../controlify/controller/Controller.java | 31 +++++++++++++++++-- .../controller/ControllerConfig.java | 28 ----------------- .../controller/ControllerTheme.java | 24 ++++++++++++++ .../controlify/controller/ControllerType.java | 1 - .../virtualmouse/MouseHandlerAccessor.java | 4 +++ .../virtualmouse/MouseHandlerMixin.java | 17 ++++++++++ .../virtualmouse/VirtualMouseHandler.java | 8 +++-- .../assets/controlify/lang/en_us.json | 3 +- src/main/resources/controlify.mixins.json | 3 +- 14 files changed, 94 insertions(+), 84 deletions(-) delete mode 100644 src/main/java/dev/isxander/controlify/bindings/ControllerTheme.java delete mode 100644 src/main/java/dev/isxander/controlify/controller/ControllerConfig.java create mode 100644 src/main/java/dev/isxander/controlify/controller/ControllerTheme.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/MouseHandlerMixin.java diff --git a/src/main/java/dev/isxander/controlify/Controlify.java b/src/main/java/dev/isxander/controlify/Controlify.java index c8e4372..b10f756 100644 --- a/src/main/java/dev/isxander/controlify/Controlify.java +++ b/src/main/java/dev/isxander/controlify/Controlify.java @@ -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); } } } diff --git a/src/main/java/dev/isxander/controlify/bindings/Bind.java b/src/main/java/dev/isxander/controlify/bindings/Bind.java index 544ae7d..d1b7b53 100644 --- a/src/main/java/dev/isxander/controlify/bindings/Bind.java +++ b/src/main/java/dev/isxander/controlify/bindings/Bind.java @@ -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) { diff --git a/src/main/java/dev/isxander/controlify/bindings/ControllerTheme.java b/src/main/java/dev/isxander/controlify/bindings/ControllerTheme.java deleted file mode 100644 index aa4227a..0000000 --- a/src/main/java/dev/isxander/controlify/bindings/ControllerTheme.java +++ /dev/null @@ -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 idGetter; - - ControllerTheme(Function 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()); - } -} diff --git a/src/main/java/dev/isxander/controlify/config/ControlifyConfig.java b/src/main/java/dev/isxander/controlify/config/ControlifyConfig.java index b7af1f4..1d83b45 100644 --- a/src/main/java/dev/isxander/controlify/config/ControlifyConfig.java +++ b/src/main/java/dev/isxander/controlify/config/ControlifyConfig.java @@ -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")); } diff --git a/src/main/java/dev/isxander/controlify/config/gui/YACLHelper.java b/src/main/java/dev/isxander/controlify/config/gui/YACLHelper.java index 96ebd3a..ff04bc7 100644 --- a/src/main/java/dev/isxander/controlify/config/gui/YACLHelper.java +++ b/src/main/java/dev/isxander/controlify/config/gui/YACLHelper.java @@ -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()); diff --git a/src/main/java/dev/isxander/controlify/controller/Controller.java b/src/main/java/dev/isxander/controlify/controller/Controller.java index 1f726e3..db449af 100644 --- a/src/main/java/dev/isxander/controlify/controller/Controller.java +++ b/src/main/java/dev/isxander/controlify/controller/Controller.java @@ -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; + } } diff --git a/src/main/java/dev/isxander/controlify/controller/ControllerConfig.java b/src/main/java/dev/isxander/controlify/controller/ControllerConfig.java deleted file mode 100644 index a5d27bc..0000000 --- a/src/main/java/dev/isxander/controlify/controller/ControllerConfig.java +++ /dev/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; -} diff --git a/src/main/java/dev/isxander/controlify/controller/ControllerTheme.java b/src/main/java/dev/isxander/controlify/controller/ControllerTheme.java new file mode 100644 index 0000000..ae0568f --- /dev/null +++ b/src/main/java/dev/isxander/controlify/controller/ControllerTheme.java @@ -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()); + } +} diff --git a/src/main/java/dev/isxander/controlify/controller/ControllerType.java b/src/main/java/dev/isxander/controlify/controller/ControllerType.java index 397c61e..ab73d03 100644 --- a/src/main/java/dev/isxander/controlify/controller/ControllerType.java +++ b/src/main/java/dev/isxander/controlify/controller/ControllerType.java @@ -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; diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/MouseHandlerAccessor.java b/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/MouseHandlerAccessor.java index f9ab48b..cb5726e 100644 --- a/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/MouseHandlerAccessor.java +++ b/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/MouseHandlerAccessor.java @@ -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); } diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/MouseHandlerMixin.java b/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/MouseHandlerMixin.java new file mode 100644 index 0000000..02bb629 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/MouseHandlerMixin.java @@ -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; + } +} diff --git a/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java b/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java index a8b17d9..748681e 100644 --- a/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java +++ b/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java @@ -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; diff --git a/src/main/resources/assets/controlify/lang/en_us.json b/src/main/resources/assets/controlify/lang/en_us.json index e7c4d55..412d119 100644 --- a/src/main/resources/assets/controlify/lang/en_us.json +++ b/src/main/resources/assets/controlify/lang/en_us.json @@ -41,11 +41,10 @@ "controlify.toast.vmouse_disabled.title": "Virtual Mouse Disabled", "controlify.toast.vmouse_disabled.description": "Controlify virtual mouse is now disabled for this screen.", "controlify.toast.controller_connected.title": "Controller Connected", - "controlify.toast.controller_connected.description": "A new controller has just been connected. You can switch to it in Controlify settings.", + "controlify.toast.controller_connected.description": "A new '%s' controller named has just been connected. You can switch to your other controller in Controlify settings.", "controlify.toast.controller_disconnected.title": "Controller Disconnected", "controlify.toast.controller_disconnected.description": "'%s' was disconnected.", - "controlify.controller_theme.auto": "Auto", "controlify.controller_theme.xbox_one": "Xbox", "controlify.controller_theme.dualshock4": "PS4", diff --git a/src/main/resources/controlify.mixins.json b/src/main/resources/controlify.mixins.json index 370c35a..fc83df1 100644 --- a/src/main/resources/controlify.mixins.json +++ b/src/main/resources/controlify.mixins.json @@ -24,6 +24,7 @@ "feature.virtualmouse.GameRendererMixin", "feature.virtualmouse.KeyboardHandlerAccessor", "feature.virtualmouse.MinecraftMixin", - "feature.virtualmouse.MouseHandlerAccessor" + "feature.virtualmouse.MouseHandlerAccessor", + "feature.virtualmouse.MouseHandlerMixin" ] }