1
0
forked from Clones/Controlify

Another dramatic improvement to gyro control

This commit is contained in:
isXander
2023-06-12 22:03:01 +01:00
parent 4df60549c6
commit 3f820e1c01
8 changed files with 138 additions and 53 deletions

View File

@ -3,6 +3,8 @@ package dev.isxander.controlify.gui.screen;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.ControllerManager;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.gamepad.GamepadController;
import dev.isxander.controlify.controller.gamepad.GamepadState;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
@ -16,7 +18,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
public class ControllerDeadzoneCalibrationScreen extends Screen {
public class ControllerCalibrationScreen extends Screen {
private static final int CALIBRATION_TIME = 100;
private static final ResourceLocation GUI_BARS_LOCATION = new ResourceLocation("textures/gui/bars.png");
@ -30,13 +32,14 @@ public class ControllerDeadzoneCalibrationScreen extends Screen {
protected boolean calibrating = false, calibrated = false;
protected int calibrationTicks = 0;
private final Map<Integer, double[]> calibrationData = new HashMap<>();
private final Map<Integer, double[]> deadzoneCalibration = new HashMap<>();
private GamepadState.GyroState accumulatedGyroVelocity = GamepadState.GyroState.ORIGIN;
public ControllerDeadzoneCalibrationScreen(Controller<?, ?> controller, Screen parent) {
public ControllerCalibrationScreen(Controller<?, ?> controller, Screen parent) {
this(controller, () -> parent);
}
public ControllerDeadzoneCalibrationScreen(Controller<?, ?> controller, Supplier<Screen> parent) {
public ControllerCalibrationScreen(Controller<?, ?> controller, Supplier<Screen> parent) {
super(Component.translatable("controlify.calibration.title"));
this.controller = controller;
this.parent = parent;
@ -117,15 +120,19 @@ public class ControllerDeadzoneCalibrationScreen extends Screen {
if (stateChanged()) {
calibrationTicks = 0;
calibrationData.clear();
deadzoneCalibration.clear();
accumulatedGyroVelocity = GamepadState.GyroState.ORIGIN;
}
if (calibrationTicks < CALIBRATION_TIME) {
calibrate(calibrationTicks);
processDeadzoneData(calibrationTicks);
processGyroData();
calibrationTicks++;
} else {
applyDeadzones();
generateGyroCalibration();
calibrating = false;
calibrated = true;
readyButton.active = true;
@ -136,22 +143,34 @@ public class ControllerDeadzoneCalibrationScreen extends Screen {
}
}
private void calibrate(int tick) {
private void processDeadzoneData(int tick) {
var axes = controller.state().rawAxes();
for (int i = 0; i < axes.size(); i++) {
var axis = Math.abs(axes.get(i));
calibrationData.computeIfAbsent(i, k -> new double[CALIBRATION_TIME])[tick] = axis;
deadzoneCalibration.computeIfAbsent(i, k -> new double[CALIBRATION_TIME])[tick] = axis;
}
}
private void processGyroData() {
if (controller instanceof GamepadController gamepad && gamepad.hasGyro()) {
accumulatedGyroVelocity = accumulatedGyroVelocity.added(gamepad.drivers.gyroDriver().getGyroState());
}
}
private void applyDeadzones() {
calibrationData.forEach((i, data) -> {
deadzoneCalibration.forEach((i, data) -> {
var max = Arrays.stream(data).max().orElseThrow();
controller.config().setDeadzone(i, (float) max + 0.05f);
});
}
private void generateGyroCalibration() {
if (controller instanceof GamepadController gamepad && gamepad.hasGyro()) {
gamepad.config().gyroCalibration = accumulatedGyroVelocity.divided(CALIBRATION_TIME);
}
}
private boolean stateChanged() {
var amt = 0.4f;

View File

@ -272,7 +272,7 @@ public class ControllerConfigScreenFactory {
.description(OptionDescription.createBuilder()
.text(Component.translatable("controlify.gui.auto_calibration.tooltip"))
.build())
.action((screen, button) -> Minecraft.getInstance().setScreen(new ControllerDeadzoneCalibrationScreen(controller, () -> {
.action((screen, button) -> Minecraft.getInstance().setScreen(new ControllerCalibrationScreen(controller, () -> {
deadzoneOpts.forEach(Option::forgetPendingValue);
return screen;
})))
@ -432,6 +432,17 @@ public class ControllerConfigScreenFactory {
o.requestSetDefault();
}))
.build());
var relativeModeOpt = Option.<Boolean>createBuilder()
.name(Component.translatable("controlify.gui.gyro_behaviour"))
.description(val -> OptionDescription.createBuilder()
.text(Component.translatable("controlify.gui.gyro_behaviour.tooltip"))
.text(val ? Component.translatable("controlify.gui.gyro_behaviour.relative.tooltip") : Component.translatable("controlify.gui.gyro_behaviour.absolute.tooltip"))
.build())
.binding(gpCfgDef.relativeGyroMode, () -> gpCfg.relativeGyroMode, v -> gpCfg.relativeGyroMode = v)
.controller(opt -> BooleanControllerBuilder.create(opt)
.valueFormatter(v -> v ? Component.translatable("controlify.gui.gyro_behaviour.relative") : Component.translatable("controlify.gui.gyro_behaviour.absolute")))
.build();
gyroGroup.option(relativeModeOpt);
gyroGroup.option(Util.make(() -> {
var opt = Option.<Boolean>createBuilder()
.name(Component.translatable("controlify.gui.gyro_invert_x"))
@ -461,6 +472,14 @@ public class ControllerConfigScreenFactory {
.binding(gpCfgDef.gyroRequiresButton, () -> gpCfg.gyroRequiresButton, v -> gpCfg.gyroRequiresButton = v)
.controller(TickBoxControllerBuilder::create)
.available(gyroSensitivity.pendingValue() > 0)
.listener((o, val) -> {
if (val) {
relativeModeOpt.setAvailable(gyroSensitivity.pendingValue() > 0);
} else {
relativeModeOpt.setAvailable(false);
relativeModeOpt.requestSet(false);
}
})
.build();
gyroOptions.add(opt);
return opt;