1
0
forked from Clones/Controlify

better theme handling and better mouse hide handling (still not perfect)

This commit is contained in:
isXander
2023-02-03 20:57:42 +00:00
parent c9b0870af3
commit ee774dcfee
14 changed files with 94 additions and 84 deletions

View File

@ -48,8 +48,8 @@ public class Controlify {
controllerHIDService.start(); controllerHIDService.start();
// load after initial controller discovery config().load(); // load after initial controller discovery
config().load(); config().save(); // save new controller configs if they don't exist
// listen for new controllers // listen for new controllers
GLFW.glfwSetJoystickCallback((jid, event) -> { GLFW.glfwSetJoystickCallback((jid, event) -> {
@ -148,6 +148,7 @@ public class Controlify {
this.currentInputMode = currentInputMode; this.currentInputMode = currentInputMode;
var minecraft = Minecraft.getInstance(); var minecraft = Minecraft.getInstance();
if (!minecraft.mouseHandler.isMouseGrabbed())
hideMouse(currentInputMode == InputMode.CONTROLLER); hideMouse(currentInputMode == InputMode.CONTROLLER);
if (minecraft.screen != null) { if (minecraft.screen != null) {
ScreenProcessorProvider.provide(minecraft.screen).onInputModeChanged(currentInputMode); ScreenProcessorProvider.provide(minecraft.screen).onInputModeChanged(currentInputMode);
@ -170,7 +171,7 @@ public class Controlify {
if (hide && !virtualMouseHandler().isVirtualMouseEnabled()) { if (hide && !virtualMouseHandler().isVirtualMouseEnabled()) {
// stop mouse hovering over last element before hiding cursor but don't actually move it // 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 // 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);
} }
} }
} }

View File

@ -47,7 +47,7 @@ public enum Bind {
} }
public ResourceLocation textureLocation(Controller controller) { 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) { public static Bind fromIdentifier(String identifier) {

View File

@ -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());
}
}

View File

@ -3,7 +3,6 @@ package dev.isxander.controlify.config;
import com.google.gson.*; import com.google.gson.*;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerConfig;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import java.io.IOException; import java.io.IOException;
@ -93,7 +92,7 @@ public class ControlifyConfig {
} }
private void applyControllerConfig(Controller controller, JsonObject object) { 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")); controller.bindings().fromJson(object.getAsJsonObject("bindings"));
} }

View File

@ -2,19 +2,17 @@ package dev.isxander.controlify.config.gui;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.bindings.Bind; import dev.isxander.controlify.bindings.Bind;
import dev.isxander.controlify.bindings.ControllerTheme;
import dev.isxander.controlify.config.GlobalSettings; import dev.isxander.controlify.config.GlobalSettings;
import dev.isxander.controlify.controller.ControllerTheme;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerConfig;
import dev.isxander.yacl.api.*; 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.CyclingListController;
import dev.isxander.yacl.gui.controllers.cycling.EnumController; import dev.isxander.yacl.gui.controllers.cycling.EnumController;
import dev.isxander.yacl.gui.controllers.slider.FloatSliderController; import dev.isxander.yacl.gui.controllers.slider.FloatSliderController;
import dev.isxander.yacl.gui.controllers.slider.IntegerSliderController; import dev.isxander.yacl.gui.controllers.slider.IntegerSliderController;
import dev.isxander.yacl.gui.controllers.string.StringController;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
public class YACLHelper { public class YACLHelper {
@ -33,13 +31,6 @@ public class YACLHelper {
.binding(Controlify.instance().currentController(), () -> Controlify.instance().currentController(), v -> Controlify.instance().setCurrentController(v)) .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()))) .controller(opt -> new CyclingListController<>(opt, Controller.CONTROLLERS.values().stream().filter(Controller::connected).toList(), c -> Component.literal(c.name())))
.instant(true) .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()); .build());
yacl.category(globalCategory.build()); yacl.category(globalCategory.build());
@ -51,7 +42,7 @@ public class YACLHelper {
category.name(Component.literal(customName == null ? controller.name() : customName)); category.name(Component.literal(customName == null ? controller.name() : customName));
var config = controller.config(); var config = controller.config();
var def = ControllerConfig.DEFAULT; var def = controller.defaultConfig();
var configGroup = OptionGroup.createBuilder() var configGroup = OptionGroup.createBuilder()
.name(Component.translatable("controlify.gui.group.config")) .name(Component.translatable("controlify.gui.group.config"))
.tooltip(Component.translatable("controlify.gui.group.config.tooltip")) .tooltip(Component.translatable("controlify.gui.group.config.tooltip"))
@ -108,7 +99,7 @@ public class YACLHelper {
.option(Option.createBuilder(ControllerTheme.class) .option(Option.createBuilder(ControllerTheme.class)
.name(Component.translatable("controlify.gui.controller_theme")) .name(Component.translatable("controlify.gui.controller_theme"))
.tooltip(Component.translatable("controlify.gui.controller_theme.tooltip")) .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) .controller(EnumController::new)
.instant(true) .instant(true)
.build()); .build());

View File

@ -1,7 +1,6 @@
package dev.isxander.controlify.controller; package dev.isxander.controlify.controller;
import dev.isxander.controlify.bindings.ControllerBindings; import dev.isxander.controlify.bindings.ControllerBindings;
import dev.isxander.controlify.bindings.ControllerTheme;
import dev.isxander.controlify.controller.hid.HIDIdentifier; import dev.isxander.controlify.controller.hid.HIDIdentifier;
import dev.isxander.controlify.event.ControlifyEvents; import dev.isxander.controlify.event.ControlifyEvents;
import org.hid4java.HidDevice; import org.hid4java.HidDevice;
@ -27,7 +26,7 @@ public final class Controller {
private ControllerState prevState = ControllerState.EMPTY; private ControllerState prevState = ControllerState.EMPTY;
private final ControllerBindings bindings = new ControllerBindings(this); 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) { public Controller(int joystickId, String guid, String name, boolean gamepad, String uid, ControllerType type) {
this.joystickId = joystickId; this.joystickId = joystickId;
@ -36,6 +35,8 @@ public final class Controller {
this.gamepad = gamepad; this.gamepad = gamepad;
this.uid = uid; this.uid = uid;
this.type = type; this.type = type;
this.config = new ControllerConfig();
this.defaultConfig = new ControllerConfig();
} }
public ControllerState state() { public ControllerState state() {
@ -110,6 +111,10 @@ public final class Controller {
return config; return config;
} }
public ControllerConfig defaultConfig() {
return defaultConfig;
}
public void setConfig(ControllerConfig config) { public void setConfig(ControllerConfig config) {
this.config = config; this.config = config;
} }
@ -150,4 +155,26 @@ public final class Controller {
return 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;
}
} }

View File

@ -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;
}

View File

@ -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());
}
}

View File

@ -3,7 +3,6 @@ package dev.isxander.controlify.controller;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import dev.isxander.controlify.bindings.ControllerTheme;
import dev.isxander.controlify.controller.hid.HIDIdentifier; import dev.isxander.controlify.controller.hid.HIDIdentifier;
import java.io.InputStreamReader; import java.io.InputStreamReader;

View File

@ -2,6 +2,7 @@ package dev.isxander.controlify.mixins.feature.virtualmouse;
import net.minecraft.client.MouseHandler; import net.minecraft.client.MouseHandler;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(MouseHandler.class) @Mixin(MouseHandler.class)
@ -14,4 +15,7 @@ public interface MouseHandlerAccessor {
@Invoker @Invoker
void invokeOnScroll(long window, double scrollDeltaX, double scrollDeltaY); void invokeOnScroll(long window, double scrollDeltaX, double scrollDeltaY);
@Accessor
void setMouseGrabbed(boolean mouseGrabbed);
} }

View File

@ -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;
}
}

View File

@ -102,7 +102,8 @@ public class VirtualMouseHandler {
GLFW.glfwSetInputMode(minecraft.getWindow().getWindow(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_HIDDEN); GLFW.glfwSetInputMode(minecraft.getWindow().getWindow(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_HIDDEN);
} else if (virtualMouseEnabled) { } else if (virtualMouseEnabled) {
disableVirtualMouse(); 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(); var scaledY = currentY * (double)this.minecraft.getWindow().getGuiScaledHeight() / (double)this.minecraft.getWindow().getScreenHeight();
matrices.pushPose(); matrices.pushPose();
matrices.translate(scaledX, scaledY, 0); matrices.translate(scaledX, scaledY, 1000f);
matrices.scale(0.5f, 0.5f, 0.5f); matrices.scale(0.5f, 0.5f, 0.5f);
GuiComponent.blit(matrices, -16, -16, 0, 0, 32, 32, 32, 32); GuiComponent.blit(matrices, -16, -16, 0, 0, 32, 32, 32, 32);
@ -158,6 +159,9 @@ public class VirtualMouseHandler {
public void disableVirtualMouse() { public void disableVirtualMouse() {
if (!virtualMouseEnabled) return; 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); GLFW.glfwSetInputMode(minecraft.getWindow().getWindow(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL);
setMousePosition(); setMousePosition();
virtualMouseEnabled = false; virtualMouseEnabled = false;

View File

@ -41,11 +41,10 @@
"controlify.toast.vmouse_disabled.title": "Virtual Mouse Disabled", "controlify.toast.vmouse_disabled.title": "Virtual Mouse Disabled",
"controlify.toast.vmouse_disabled.description": "Controlify virtual mouse is now disabled for this screen.", "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.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.title": "Controller Disconnected",
"controlify.toast.controller_disconnected.description": "'%s' was disconnected.", "controlify.toast.controller_disconnected.description": "'%s' was disconnected.",
"controlify.controller_theme.auto": "Auto",
"controlify.controller_theme.xbox_one": "Xbox", "controlify.controller_theme.xbox_one": "Xbox",
"controlify.controller_theme.dualshock4": "PS4", "controlify.controller_theme.dualshock4": "PS4",

View File

@ -24,6 +24,7 @@
"feature.virtualmouse.GameRendererMixin", "feature.virtualmouse.GameRendererMixin",
"feature.virtualmouse.KeyboardHandlerAccessor", "feature.virtualmouse.KeyboardHandlerAccessor",
"feature.virtualmouse.MinecraftMixin", "feature.virtualmouse.MinecraftMixin",
"feature.virtualmouse.MouseHandlerAccessor" "feature.virtualmouse.MouseHandlerAccessor",
"feature.virtualmouse.MouseHandlerMixin"
] ]
} }