1
0
forked from Clones/Controlify

✏️ Modify vmouse so that controls feel "less square" + apply a harsher easing function (quad -> cubic)

This commit is contained in:
isXander
2023-10-30 19:33:38 +00:00
parent 675bceff18
commit 8529fa8a08
4 changed files with 40 additions and 19 deletions

View File

@ -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()) {

View File

@ -31,7 +31,7 @@ public abstract class AbstractContainerScreenMixin<T extends AbstractContainerMe
@Override
public Set<SnapPoint> 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());
}
}

View File

@ -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<Float, Float> 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;

View File

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