diff --git a/src/main/java/dev/isxander/controlify/ingame/InGameInputHandler.java b/src/main/java/dev/isxander/controlify/ingame/InGameInputHandler.java index 7c32f40..d7ef4c7 100644 --- a/src/main/java/dev/isxander/controlify/ingame/InGameInputHandler.java +++ b/src/main/java/dev/isxander/controlify/ingame/InGameInputHandler.java @@ -141,7 +141,7 @@ public class InGameInputHandler { return; } - var isAiming = isAiming(player); + boolean isAiming = isAiming(player); float impulseY = 0f; float impulseX = 0f; @@ -162,13 +162,13 @@ public class InGameInputHandler { }, 0, turnAngle)); } } else { + // TODO: refactor this function majorly, so you can easily multiply the impulse vec's length + // possibly separate the flick stick code into its own function? // normal look input impulseY = controller.bindings().LOOK_DOWN.state() - controller.bindings().LOOK_UP.state(); impulseX = controller.bindings().LOOK_RIGHT.state() - controller.bindings().LOOK_LEFT.state(); - impulseX *= Math.abs(impulseX) * 10f; // 10 degrees per second - impulseY *= Math.abs(impulseY) * 10f; - impulseX *= controller.config().horizontalLookSensitivity; - impulseY *= controller.config().verticalLookSensitivity; + impulseX *= controller.config().horizontalLookSensitivity * 10f; // 10 degrees per second at 100% sensitivity + impulseY *= controller.config().verticalLookSensitivity * 10f; if (controller.config().reduceAimingSensitivity && player.isUsingItem()) { float aimMultiplier = switch (player.getUseItem().getUseAnimation()) { diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/snapping/AbstractContainerScreenMixin.java b/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/snapping/AbstractContainerScreenMixin.java index 5f0a06c..fbbd678 100644 --- a/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/snapping/AbstractContainerScreenMixin.java +++ b/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/snapping/AbstractContainerScreenMixin.java @@ -31,7 +31,7 @@ public abstract class AbstractContainerScreenMixin getSnapPoints() { return getMenu().slots.stream() - .map(slot -> new SnapPoint(new Vector2i(leftPos + slot.x + 8, topPos + slot.y + 8), 14)) + .map(slot -> new SnapPoint(new Vector2i(leftPos + slot.x + 8, topPos + slot.y + 8), 15)) .collect(Collectors.toSet()); } } diff --git a/src/main/java/dev/isxander/controlify/utils/ControllerUtils.java b/src/main/java/dev/isxander/controlify/utils/ControllerUtils.java index 8bc736c..caef878 100644 --- a/src/main/java/dev/isxander/controlify/utils/ControllerUtils.java +++ b/src/main/java/dev/isxander/controlify/utils/ControllerUtils.java @@ -6,9 +6,11 @@ import dev.isxander.controlify.controller.gamepad.GamepadController; import dev.isxander.controlify.hid.ControllerHIDService; import dev.isxander.controlify.hid.HIDDevice; import net.minecraft.util.Mth; +import org.joml.Vector2f; import java.util.HexFormat; import java.util.Optional; +import java.util.function.Function; public class ControllerUtils { public static String createControllerString(Controller controller) { @@ -38,6 +40,16 @@ public class ControllerUtils { return (float) (y * Math.sqrt(1 - (x * x) / 2)); } + public static Vector2f applyEasingToLength(float x, float y, Function easing) { + float length = Mth.sqrt(x * x + y * y); + float easedLength = easing.apply(length); + float angle = (float) Mth.atan2(y, x); + return new Vector2f( + Mth.cos(angle) * easedLength, + Mth.sin(angle) * easedLength + ); + } + public static boolean shouldApplyAntiSnapBack(float x, float y, float px, float py, float threshold) { float dx = x - px; float dy = y - py; diff --git a/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java b/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java index 29aa1c1..10aa4da 100644 --- a/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java +++ b/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java @@ -14,6 +14,7 @@ import dev.isxander.controlify.screenop.ScreenProcessorProvider; import dev.isxander.controlify.api.event.ControlifyEvents; import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor; import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor; +import dev.isxander.controlify.utils.ControllerUtils; import dev.isxander.controlify.utils.HoldRepeatHelper; import dev.isxander.controlify.utils.ToastUtils; import net.minecraft.client.Minecraft; @@ -23,14 +24,13 @@ import net.minecraft.client.gui.navigation.ScreenDirection; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; -import org.joml.RoundingMode; -import org.joml.Vector2d; -import org.joml.Vector2dc; -import org.joml.Vector2i; +import org.joml.*; import org.lwjgl.glfw.GLFW; +import java.lang.Math; import java.util.Comparator; import java.util.Set; +import java.util.function.Function; public class VirtualMouseHandler { private static final ResourceLocation CURSOR_TEXTURE = new ResourceLocation("controlify", "textures/gui/virtual_mouse.png"); @@ -68,10 +68,19 @@ public class VirtualMouseHandler { return; } - var impulseY = controller.bindings().VMOUSE_MOVE_DOWN.state() - controller.bindings().VMOUSE_MOVE_UP.state(); - var impulseX = controller.bindings().VMOUSE_MOVE_RIGHT.state() - controller.bindings().VMOUSE_MOVE_LEFT.state(); - var prevImpulseY = controller.bindings().VMOUSE_MOVE_DOWN.prevState() - controller.bindings().VMOUSE_MOVE_UP.prevState(); - var prevImpulseX = controller.bindings().VMOUSE_MOVE_RIGHT.prevState() - controller.bindings().VMOUSE_MOVE_LEFT.prevState(); + + // apply an easing function directly to the vector's length + // if you do easing(x), easing(y), then the diagonals where it's something like (~0.8, ~0.8) will incorrectly ease + Vector2f impulse = ControllerUtils.applyEasingToLength( + controller.bindings().VMOUSE_MOVE_RIGHT.state() - controller.bindings().VMOUSE_MOVE_LEFT.state(), + controller.bindings().VMOUSE_MOVE_DOWN.state() - controller.bindings().VMOUSE_MOVE_UP.state(), + x -> (float) Math.pow(x, 3) + ); + Vector2f prevImpulse = ControllerUtils.applyEasingToLength( + controller.bindings().VMOUSE_MOVE_RIGHT.prevState() - controller.bindings().VMOUSE_MOVE_LEFT.prevState(), + controller.bindings().VMOUSE_MOVE_DOWN.prevState() - controller.bindings().VMOUSE_MOVE_UP.prevState(), + x -> (float) Math.pow(x, 3) + ); if (minecraft.screen != null && minecraft.screen instanceof ISnapBehaviour snapBehaviour) { snapPoints = snapBehaviour.getSnapPoints(); @@ -80,18 +89,18 @@ public class VirtualMouseHandler { } // if just released stick, snap to nearest snap point - if (impulseX == 0 && impulseY == 0) { - if ((prevImpulseX != 0 || prevImpulseY != 0)) + if (impulse.x == 0 && impulse.y == 0) { + if ((prevImpulse.x != 0 || prevImpulse.y != 0)) snapToClosestPoint(); } var sensitivity = controller.config().virtualMouseSensitivity; var windowSizeModifier = Math.max(minecraft.getWindow().getWidth(), minecraft.getWindow().getHeight()) / 800f; - // quadratic function to make small movements smaller + // cubic function to make small movements smaller // abs to keep sign - targetX += impulseX * Mth.abs(impulseX) * 20f * sensitivity * windowSizeModifier; - targetY += impulseY * Mth.abs(impulseY) * 20f * sensitivity * windowSizeModifier; + targetX += impulse.x * 20f * sensitivity * windowSizeModifier; + targetY += impulse.y * 20f * sensitivity * windowSizeModifier; targetX = Mth.clamp(targetX, 0, minecraft.getWindow().getWidth()); targetY = Mth.clamp(targetY, 0, minecraft.getWindow().getHeight());