forked from Clones/Controlify
➕ Another dramatic improvement to gyro control
This commit is contained in:
@ -6,6 +6,7 @@ import dev.isxander.controlify.api.ingameinput.LookInputModifier;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.api.event.ControlifyEvents;
|
||||
import dev.isxander.controlify.controller.gamepad.GamepadController;
|
||||
import dev.isxander.controlify.controller.gamepad.GamepadState;
|
||||
import dev.isxander.controlify.utils.Animator;
|
||||
import dev.isxander.controlify.utils.Easings;
|
||||
import dev.isxander.controlify.utils.NavigationHelper;
|
||||
@ -17,8 +18,7 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector2fc;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiFunction;
|
||||
@ -30,6 +30,9 @@ public class InGameInputHandler {
|
||||
private double lookInputX, lookInputY;
|
||||
private boolean shouldShowPlayerList;
|
||||
|
||||
private GamepadState.GyroState gyroInput = GamepadState.GyroState.ORIGIN;
|
||||
private boolean wasAiming;
|
||||
|
||||
private final NavigationHelper dropRepeatHelper;
|
||||
|
||||
public InGameInputHandler(Controller<?, ?> controller) {
|
||||
@ -130,53 +133,68 @@ public class InGameInputHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
var isAiming = isAiming(player);
|
||||
|
||||
float impulseY = 0f;
|
||||
float impulseX = 0f;
|
||||
|
||||
// flick stick - turn 90 degrees immediately upon turning
|
||||
// should be paired with gyro controls
|
||||
if (gamepad != null && gamepad.config().flickStick) {
|
||||
var turnAngle = 90 / 0.15f; // Entity#turn multiplies cursor delta by 0.15 to get rotation
|
||||
|
||||
AtomicReference<Float> lastAngle = new AtomicReference<>(0f);
|
||||
Vector2fc flickVec = new Vector2f(
|
||||
controller.bindings().LOOK_RIGHT.justPressed() ? 1 : controller.bindings().LOOK_LEFT.justPressed() ? -1 : 0,
|
||||
controller.bindings().LOOK_DOWN.justPressed() ? 1 : controller.bindings().LOOK_UP.justPressed() ? -1 : 0
|
||||
);
|
||||
float flick = controller.bindings().LOOK_DOWN.justPressed() || controller.bindings().LOOK_RIGHT.justPressed() ? 1 : controller.bindings().LOOK_UP.justPressed() || controller.bindings().LOOK_LEFT.justPressed() ? -1 : 0;
|
||||
|
||||
if (!flickVec.equals(0, 0)) {
|
||||
if (flick != 0f) {
|
||||
AtomicReference<Float> lastAngle = new AtomicReference<>(0f);
|
||||
Animator.INSTANCE.play(new Animator.AnimationInstance(10, Easings::easeOutExpo)
|
||||
.addConsumer(angle -> {
|
||||
player.turn((angle - lastAngle.get()) * flickVec.x(), (angle - lastAngle.get()) * flickVec.y());
|
||||
player.turn((angle - lastAngle.get()) * flick, 0);
|
||||
lastAngle.set(angle);
|
||||
}, 0, turnAngle));
|
||||
}
|
||||
} else {
|
||||
// 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);
|
||||
impulseY *= Math.abs(impulseY);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// normal look input
|
||||
var impulseY = controller.bindings().LOOK_DOWN.state() - controller.bindings().LOOK_UP.state();
|
||||
var impulseX = controller.bindings().LOOK_RIGHT.state() - controller.bindings().LOOK_LEFT.state();
|
||||
impulseX *= Math.abs(impulseX);
|
||||
impulseY *= Math.abs(impulseY);
|
||||
|
||||
if (controller.config().reduceAimingSensitivity && player != null && player.isUsingItem()) {
|
||||
float aimMultiplier = switch (player.getUseItem().getUseAnimation()) {
|
||||
case BOW, CROSSBOW, SPEAR -> 0.6f;
|
||||
case SPYGLASS -> 0.2f;
|
||||
default -> 1f;
|
||||
};
|
||||
impulseX *= aimMultiplier;
|
||||
impulseY *= aimMultiplier;
|
||||
if (controller.config().reduceAimingSensitivity && player != null && player.isUsingItem()) {
|
||||
float aimMultiplier = switch (player.getUseItem().getUseAnimation()) {
|
||||
case BOW, CROSSBOW, SPEAR -> 0.6f;
|
||||
case SPYGLASS -> 0.2f;
|
||||
default -> 1f;
|
||||
};
|
||||
impulseX *= aimMultiplier;
|
||||
impulseY *= aimMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
// gyro input
|
||||
if (gamepad != null
|
||||
&& gamepad.hasGyro()
|
||||
&& (!gamepad.config().gyroRequiresButton || gamepad.bindings().GAMEPAD_GYRO_BUTTON.held())
|
||||
) {
|
||||
var gyroDelta = gamepad.absoluteGyroState().deadzone(0.05f);
|
||||
if (gamepad != null && gamepad.hasGyro()) {
|
||||
boolean useGyro = false;
|
||||
|
||||
impulseY += -gyroDelta.pitch() * gamepad.config().gyroLookSensitivity * (gamepad.config().invertGyroY ? -1 : 1);
|
||||
impulseX += (-gyroDelta.roll() + -gyroDelta.yaw()) * gamepad.config().gyroLookSensitivity * (gamepad.config().invertGyroX ? -1 : 1);
|
||||
if (gamepad.config().gyroRequiresButton) {
|
||||
if (gamepad.bindings().GAMEPAD_GYRO_BUTTON.justPressed() || (isAiming && !wasAiming))
|
||||
gyroInput = GamepadState.GyroState.ORIGIN;
|
||||
|
||||
if (gamepad.bindings().GAMEPAD_GYRO_BUTTON.held() || isAiming) {
|
||||
if (gamepad.config().relativeGyroMode)
|
||||
gyroInput = gyroInput.added(gamepad.state().gyroDelta().multiplied(0.1f));
|
||||
else
|
||||
gyroInput = gamepad.state().gyroDelta();
|
||||
useGyro = true;
|
||||
}
|
||||
} else {
|
||||
gyroInput = gamepad.state().gyroDelta();
|
||||
useGyro = true;
|
||||
}
|
||||
|
||||
if (useGyro) {
|
||||
impulseY += -gyroInput.pitch() * gamepad.config().gyroLookSensitivity * (gamepad.config().invertGyroY ? -1 : 1);
|
||||
impulseX += (-gyroInput.roll() + -gyroInput.yaw()) * gamepad.config().gyroLookSensitivity * (gamepad.config().invertGyroX ? -1 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
LookInputModifier lookInputModifier = ControlifyEvents.LOOK_INPUT_MODIFIER.invoker();
|
||||
@ -185,6 +203,8 @@ public class InGameInputHandler {
|
||||
|
||||
lookInputX = impulseX * controller.config().horizontalLookSensitivity * 65f;
|
||||
lookInputY = impulseY * controller.config().verticalLookSensitivity * 65f;
|
||||
|
||||
wasAiming = isAiming;
|
||||
}
|
||||
|
||||
public void processPlayerLook(float deltaTime) {
|
||||
@ -197,6 +217,13 @@ public class InGameInputHandler {
|
||||
return this.shouldShowPlayerList;
|
||||
}
|
||||
|
||||
private boolean isAiming(Player player) {
|
||||
return player.isUsingItem() && switch (player.getUseItem().getUseAnimation()) {
|
||||
case BOW, CROSSBOW, SPEAR, SPYGLASS -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
public record FunctionalLookInputModifier(BiFunction<Float, Controller<?, ?>, Float> x, BiFunction<Float, Controller<?, ?>, Float> y) implements LookInputModifier {
|
||||
@Override
|
||||
public float modifyX(float x, Controller<?, ?> controller) {
|
||||
|
Reference in New Issue
Block a user