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; return;
} }
var isAiming = isAiming(player); boolean isAiming = isAiming(player);
float impulseY = 0f; float impulseY = 0f;
float impulseX = 0f; float impulseX = 0f;
@ -162,13 +162,13 @@ public class InGameInputHandler {
}, 0, turnAngle)); }, 0, turnAngle));
} }
} else { } 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 // normal look input
impulseY = controller.bindings().LOOK_DOWN.state() - controller.bindings().LOOK_UP.state(); impulseY = controller.bindings().LOOK_DOWN.state() - controller.bindings().LOOK_UP.state();
impulseX = controller.bindings().LOOK_RIGHT.state() - controller.bindings().LOOK_LEFT.state(); impulseX = controller.bindings().LOOK_RIGHT.state() - controller.bindings().LOOK_LEFT.state();
impulseX *= Math.abs(impulseX) * 10f; // 10 degrees per second impulseX *= controller.config().horizontalLookSensitivity * 10f; // 10 degrees per second at 100% sensitivity
impulseY *= Math.abs(impulseY) * 10f; impulseY *= controller.config().verticalLookSensitivity * 10f;
impulseX *= controller.config().horizontalLookSensitivity;
impulseY *= controller.config().verticalLookSensitivity;
if (controller.config().reduceAimingSensitivity && player.isUsingItem()) { if (controller.config().reduceAimingSensitivity && player.isUsingItem()) {
float aimMultiplier = switch (player.getUseItem().getUseAnimation()) { float aimMultiplier = switch (player.getUseItem().getUseAnimation()) {

View File

@ -31,7 +31,7 @@ public abstract class AbstractContainerScreenMixin<T extends AbstractContainerMe
@Override @Override
public Set<SnapPoint> getSnapPoints() { public Set<SnapPoint> getSnapPoints() {
return getMenu().slots.stream() 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()); .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.ControllerHIDService;
import dev.isxander.controlify.hid.HIDDevice; import dev.isxander.controlify.hid.HIDDevice;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import org.joml.Vector2f;
import java.util.HexFormat; import java.util.HexFormat;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function;
public class ControllerUtils { public class ControllerUtils {
public static String createControllerString(Controller<?, ?> controller) { public static String createControllerString(Controller<?, ?> controller) {
@ -38,6 +40,16 @@ public class ControllerUtils {
return (float) (y * Math.sqrt(1 - (x * x) / 2)); 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) { public static boolean shouldApplyAntiSnapBack(float x, float y, float px, float py, float threshold) {
float dx = x - px; float dx = x - px;
float dy = y - py; 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.api.event.ControlifyEvents;
import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor; import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor;
import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor; 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.HoldRepeatHelper;
import dev.isxander.controlify.utils.ToastUtils; import dev.isxander.controlify.utils.ToastUtils;
import net.minecraft.client.Minecraft; 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.network.chat.Component;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import org.joml.RoundingMode; import org.joml.*;
import org.joml.Vector2d;
import org.joml.Vector2dc;
import org.joml.Vector2i;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.lang.Math;
import java.util.Comparator; import java.util.Comparator;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
public class VirtualMouseHandler { public class VirtualMouseHandler {
private static final ResourceLocation CURSOR_TEXTURE = new ResourceLocation("controlify", "textures/gui/virtual_mouse.png"); private static final ResourceLocation CURSOR_TEXTURE = new ResourceLocation("controlify", "textures/gui/virtual_mouse.png");
@ -68,10 +68,19 @@ public class VirtualMouseHandler {
return; 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(); // apply an easing function directly to the vector's length
var prevImpulseY = controller.bindings().VMOUSE_MOVE_DOWN.prevState() - controller.bindings().VMOUSE_MOVE_UP.prevState(); // if you do easing(x), easing(y), then the diagonals where it's something like (~0.8, ~0.8) will incorrectly ease
var prevImpulseX = controller.bindings().VMOUSE_MOVE_RIGHT.prevState() - controller.bindings().VMOUSE_MOVE_LEFT.prevState(); 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) { if (minecraft.screen != null && minecraft.screen instanceof ISnapBehaviour snapBehaviour) {
snapPoints = snapBehaviour.getSnapPoints(); snapPoints = snapBehaviour.getSnapPoints();
@ -80,18 +89,18 @@ public class VirtualMouseHandler {
} }
// if just released stick, snap to nearest snap point // if just released stick, snap to nearest snap point
if (impulseX == 0 && impulseY == 0) { if (impulse.x == 0 && impulse.y == 0) {
if ((prevImpulseX != 0 || prevImpulseY != 0)) if ((prevImpulse.x != 0 || prevImpulse.y != 0))
snapToClosestPoint(); snapToClosestPoint();
} }
var sensitivity = controller.config().virtualMouseSensitivity; var sensitivity = controller.config().virtualMouseSensitivity;
var windowSizeModifier = Math.max(minecraft.getWindow().getWidth(), minecraft.getWindow().getHeight()) / 800f; 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 // abs to keep sign
targetX += impulseX * Mth.abs(impulseX) * 20f * sensitivity * windowSizeModifier; targetX += impulse.x * 20f * sensitivity * windowSizeModifier;
targetY += impulseY * Mth.abs(impulseY) * 20f * sensitivity * windowSizeModifier; targetY += impulse.y * 20f * sensitivity * windowSizeModifier;
targetX = Mth.clamp(targetX, 0, minecraft.getWindow().getWidth()); targetX = Mth.clamp(targetX, 0, minecraft.getWindow().getWidth());
targetY = Mth.clamp(targetY, 0, minecraft.getWindow().getHeight()); targetY = Mth.clamp(targetY, 0, minecraft.getWindow().getHeight());