1
0
forked from Clones/Controlify

compound binds, complete vanilla compat, better vmouse screen handling, controller uuid, beta notice screen, configurable movement keys, vmouse shift key, icon, optimize controller save/load

This commit is contained in:
isXander
2023-02-05 14:55:20 +00:00
parent 9c7972c971
commit 6c5108469c
62 changed files with 831 additions and 137 deletions

View File

@ -2,6 +2,7 @@ package dev.isxander.controlify.config.gui;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.bindings.Bind;
import dev.isxander.controlify.bindings.IBind;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
@ -17,23 +18,27 @@ import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW;
public class BindButtonController implements Controller<Bind> {
private final Option<Bind> option;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
public class BindButtonController implements Controller<IBind> {
private final Option<IBind> option;
private final dev.isxander.controlify.controller.Controller controller;
public BindButtonController(Option<Bind> option, dev.isxander.controlify.controller.Controller controller) {
public BindButtonController(Option<IBind> option, dev.isxander.controlify.controller.Controller controller) {
this.option = option;
this.controller = controller;
}
@Override
public Option<Bind> option() {
public Option<IBind> option() {
return this.option;
}
@Override
public Component formatValue() {
return Component.literal(option().pendingValue().identifier());
return Component.empty();
}
@Override
@ -42,8 +47,9 @@ public class BindButtonController implements Controller<Bind> {
}
public static class BindButtonWidget extends ControllerWidget<BindButtonController> implements ComponentProcessorProvider, ComponentProcessor {
private boolean awaitingControllerInput = false;
private boolean awaitingControllerInput = false, skipFirstTickInput = false;
private final Component awaitingText = Component.translatable("controlify.gui.bind_input_awaiting").withStyle(ChatFormatting.ITALIC);
private final Set<Bind> pressedBinds = new LinkedHashSet<>();
public BindButtonWidget(BindButtonController control, YACLScreen screen, Dimension<Integer> dim) {
super(control, screen, dim);
@ -52,9 +58,17 @@ public class BindButtonController implements Controller<Bind> {
@Override
protected void drawValueText(PoseStack matrices, int mouseX, int mouseY, float delta) {
if (awaitingControllerInput) {
textRenderer.drawShadow(matrices, awaitingText, getDimension().xLimit() - textRenderer.width(awaitingText) - getXPadding(), getDimension().centerY() - textRenderer.lineHeight / 2f, 0xFFFFFF);
if (pressedBinds.isEmpty()) {
textRenderer.drawShadow(matrices, awaitingText, getDimension().xLimit() - textRenderer.width(awaitingText) - getXPadding(), getDimension().centerY() - textRenderer.lineHeight / 2f, 0xFFFFFF);
} else {
var bind = IBind.create(pressedBinds);
var plusSize = 2 + textRenderer.width("+");
bind.draw(matrices, getDimension().xLimit() - bind.drawSize().width() - getXPadding() - plusSize, getDimension().centerY(), control.controller);
textRenderer.drawShadow(matrices, "+", getDimension().xLimit() - getXPadding() - plusSize, getDimension().centerY() - textRenderer.lineHeight / 2f, 0xFFFFFF);
}
} else {
ButtonRenderer.drawButton(control.option().pendingValue(), control.controller, matrices, getDimension().xLimit() - ButtonRenderer.BUTTON_SIZE / 2, getDimension().centerY(), ButtonRenderer.BUTTON_SIZE);
var bind = control.option().pendingValue();
bind.draw(matrices, getDimension().xLimit() - bind.drawSize().width(), getDimension().centerY(), control.controller);
}
}
@ -84,24 +98,32 @@ public class BindButtonController implements Controller<Bind> {
}
@Override
public boolean overrideControllerButtons(ScreenProcessor screen, dev.isxander.controlify.controller.Controller controller) {
if (!awaitingControllerInput || !isFocused()) return false;
for (var bind : Bind.values()) {
boolean stateNow = bind.state(controller.state(), controller);
boolean stateBefore = bind.state(controller.prevState(), controller);
if (stateNow && !stateBefore) {
control.option().requestSet(bind);
awaitingControllerInput = false;
return true;
}
public boolean overrideControllerButtons(ScreenProcessor<?> screen, dev.isxander.controlify.controller.Controller controller) {
if (controller.bindings().GUI_PRESS.justPressed()) {
return awaitingControllerInput = true;
}
return false;
if (!awaitingControllerInput) return false;
if (pressedBinds.stream().anyMatch(bind -> !bind.held(controller.state(), controller))) {
// finished
awaitingControllerInput = false;
control.option().requestSet(IBind.create(pressedBinds));
pressedBinds.clear();
} else {
for (var bind : Bind.values()) {
if (bind.held(controller.state(), controller) && !bind.held(controller.prevState(), controller)) {
pressedBinds.add(bind);
}
}
control.controller.consumeButtonState();
}
return true;
}
@Override
public boolean overrideControllerNavigation(ScreenProcessor screen, dev.isxander.controlify.controller.Controller controller) {
public boolean overrideControllerNavigation(ScreenProcessor<?> screen, dev.isxander.controlify.controller.Controller controller) {
return awaitingControllerInput;
}
@ -115,7 +137,7 @@ public class BindButtonController implements Controller<Bind> {
if (awaitingControllerInput)
return textRenderer.width(awaitingText);
return ButtonRenderer.BUTTON_SIZE;
return control.option().pendingValue().drawSize().width();
}
}
}

View File

@ -1,28 +1,41 @@
package dev.isxander.controlify.config.gui;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.bindings.Bind;
import dev.isxander.controlify.bindings.IBind;
import dev.isxander.controlify.config.GlobalSettings;
import dev.isxander.controlify.controller.ControllerTheme;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.yacl.api.*;
import dev.isxander.yacl.gui.controllers.ActionController;
import dev.isxander.yacl.gui.controllers.TickBoxController;
import dev.isxander.yacl.gui.controllers.cycling.CyclingListController;
import dev.isxander.yacl.gui.controllers.cycling.EnumController;
import dev.isxander.yacl.gui.controllers.slider.FloatSliderController;
import dev.isxander.yacl.gui.controllers.slider.IntegerSliderController;
import net.minecraft.ChatFormatting;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.AlertScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
public class YACLHelper {
public static Screen generateConfigScreen(Screen parent) {
if (Controlify.instance().currentController() == null) {
return new AlertScreen(
() -> Minecraft.getInstance().setScreen(parent),
Component.translatable("controlify.gui.error.title").withStyle(ChatFormatting.RED, ChatFormatting.BOLD),
Component.translatable("controlify.gui.error.message").withStyle(ChatFormatting.RED)
);
}
var controlify = Controlify.instance();
var yacl = YetAnotherConfigLib.createBuilder()
.title(Component.literal("Controlify"))
.save(() -> controlify.config().save());
var globalSettings = Controlify.instance().config().globalSettings();
var globalCategory = ConfigCategory.createBuilder()
.name(Component.translatable("controlify.gui.category.global"))
.option(Option.createBuilder(Controller.class)
@ -31,6 +44,17 @@ public class YACLHelper {
.binding(Controlify.instance().currentController(), () -> Controlify.instance().currentController(), v -> Controlify.instance().setCurrentController(v))
.controller(opt -> new CyclingListController<>(opt, Controller.CONTROLLERS.values().stream().filter(Controller::connected).toList(), c -> Component.literal(c.name())))
.instant(true)
.build())
.option(Option.createBuilder(boolean.class)
.name(Component.translatable("controlify.gui.out_of_focus_input"))
.tooltip(Component.translatable("controlify.gui.out_of_focus_input.tooltip"))
.binding(GlobalSettings.DEFAULT.outOfFocusInput, () -> globalSettings.outOfFocusInput, v -> globalSettings.outOfFocusInput = v)
.controller(TickBoxController::new)
.build())
.option(ButtonOption.createBuilder()
.name(Component.translatable("controlify.gui.open_issue_tracker"))
.action((screen, button) -> Util.getPlatform().openUri("https://github.com/isxander/controlify/issues"))
.controller(opt -> new ActionController(opt, Component.translatable("controlify.gui.format.open")))
.build());
yacl.category(globalCategory.build());
@ -85,15 +109,9 @@ public class YACLHelper {
.controller(opt -> new FloatSliderController(opt, 0, 1, 0.01f, v -> Component.literal(String.format("%.0f%%", v*100))))
.build())
.option(Option.createBuilder(float.class)
.name(Component.translatable("controlify.gui.left_trigger_threshold"))
.tooltip(Component.translatable("controlify.gui.left_trigger_threshold.tooltip"))
.binding(def.leftTriggerActivationThreshold, () -> config.leftTriggerActivationThreshold, v -> config.leftTriggerActivationThreshold = v)
.controller(opt -> new FloatSliderController(opt, 0, 1, 0.05f, v -> Component.literal(String.format("%.0f%%", v*100))))
.build())
.option(Option.createBuilder(float.class)
.name(Component.translatable("controlify.gui.right_trigger_threshold"))
.tooltip(Component.translatable("controlify.gui.right_trigger_threshold.tooltip"))
.binding(def.rightTriggerActivationThreshold, () -> config.rightTriggerActivationThreshold, v -> config.rightTriggerActivationThreshold = v)
.name(Component.translatable("controlify.gui.button_activation_threshold"))
.tooltip(Component.translatable("controlify.gui.button_activation_threshold.tooltip"))
.binding(def.buttonActivationThreshold, () -> config.buttonActivationThreshold, v -> config.buttonActivationThreshold = v)
.controller(opt -> new FloatSliderController(opt, 0, 1, 0.05f, v -> Component.literal(String.format("%.0f%%", v*100))))
.build())
.option(Option.createBuilder(ControllerTheme.class)
@ -108,10 +126,12 @@ public class YACLHelper {
var controlsGroup = OptionGroup.createBuilder()
.name(Component.translatable("controlify.gui.group.controls"));
for (var control : controller.bindings().registry().values()) {
controlsGroup.option(Option.createBuilder(Bind.class)
controlsGroup.option(Option.createBuilder(IBind.class)
.name(control.name())
.binding(control.defaultBind(), control::currentBind, control::setCurrentBind)
.controller(opt -> new BindButtonController(opt, controller))
.tooltip(control.description())
.instant(true)
.build());
}
category.group(controlsGroup.build());