forked from Clones/Controlify
bind menu & button rendering
This commit is contained in:
@ -33,7 +33,7 @@ public enum Bind {
|
|||||||
Bind(BiFunction<ControllerState, Controller, Boolean> state, String identifier) {
|
Bind(BiFunction<ControllerState, Controller, Boolean> state, String identifier) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
this.textureLocation = new ResourceLocation("controlify", "textures/gui/buttons/" + identifier + ".png");
|
this.textureLocation = new ResourceLocation("controlify", "textures/gui/buttons/xbox/" + identifier + ".png");
|
||||||
}
|
}
|
||||||
|
|
||||||
Bind(Function<ControllerState, Boolean> state, String identifier) {
|
Bind(Function<ControllerState, Boolean> state, String identifier) {
|
||||||
|
@ -17,7 +17,7 @@ public class ControllerBinding {
|
|||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
this.bind = this.defaultBind = defaultBind;
|
this.bind = this.defaultBind = defaultBind;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = Component.translatable("controlify.binding." + id);
|
this.name = Component.translatable("controlify.binding." + id.getNamespace() + "." + id.getPath());
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.override = override;
|
this.override = override;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import dev.isxander.controlify.Controlify;
|
|||||||
import dev.isxander.controlify.InputMode;
|
import dev.isxander.controlify.InputMode;
|
||||||
import dev.isxander.controlify.controller.Controller;
|
import dev.isxander.controlify.controller.Controller;
|
||||||
import dev.isxander.controlify.event.ControlifyEvents;
|
import dev.isxander.controlify.event.ControlifyEvents;
|
||||||
import dev.isxander.controlify.mixins.KeyMappingAccessor;
|
import dev.isxander.controlify.mixins.feature.bind.KeyMappingAccessor;
|
||||||
import net.minecraft.client.KeyMapping;
|
import net.minecraft.client.KeyMapping;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
@ -17,6 +17,7 @@ public class ControllerBindings {
|
|||||||
JUMP, SNEAK,
|
JUMP, SNEAK,
|
||||||
ATTACK, USE,
|
ATTACK, USE,
|
||||||
SPRINT,
|
SPRINT,
|
||||||
|
DROP,
|
||||||
NEXT_SLOT, PREV_SLOT,
|
NEXT_SLOT, PREV_SLOT,
|
||||||
PAUSE,
|
PAUSE,
|
||||||
INVENTORY,
|
INVENTORY,
|
||||||
@ -24,7 +25,7 @@ public class ControllerBindings {
|
|||||||
OPEN_CHAT,
|
OPEN_CHAT,
|
||||||
GUI_PRESS, GUI_BACK;
|
GUI_PRESS, GUI_BACK;
|
||||||
|
|
||||||
private final Map<ResourceLocation, ControllerBinding> registry = new HashMap<>();
|
private final Map<ResourceLocation, ControllerBinding> registry = new LinkedHashMap<>();
|
||||||
|
|
||||||
public ControllerBindings(Controller controller) {
|
public ControllerBindings(Controller controller) {
|
||||||
var options = Minecraft.getInstance().options;
|
var options = Minecraft.getInstance().options;
|
||||||
@ -34,6 +35,7 @@ public class ControllerBindings {
|
|||||||
register(ATTACK = new ControllerBinding(controller, Bind.RIGHT_TRIGGER, new ResourceLocation("controlify", "attack"), options.keyAttack));
|
register(ATTACK = new ControllerBinding(controller, Bind.RIGHT_TRIGGER, new ResourceLocation("controlify", "attack"), options.keyAttack));
|
||||||
register(USE = new ControllerBinding(controller, Bind.LEFT_TRIGGER, new ResourceLocation("controlify", "use"), options.keyUse));
|
register(USE = new ControllerBinding(controller, Bind.LEFT_TRIGGER, new ResourceLocation("controlify", "use"), options.keyUse));
|
||||||
register(SPRINT = new ControllerBinding(controller, Bind.LEFT_STICK, new ResourceLocation("controlify", "sprint"), options.keySprint));
|
register(SPRINT = new ControllerBinding(controller, Bind.LEFT_STICK, new ResourceLocation("controlify", "sprint"), options.keySprint));
|
||||||
|
register(DROP = new ControllerBinding(controller, Bind.DPAD_DOWN, new ResourceLocation("controlify", "drop"), options.keyDrop));
|
||||||
register(NEXT_SLOT = new ControllerBinding(controller, Bind.RIGHT_BUMPER, new ResourceLocation("controlify", "next_slot"), null));
|
register(NEXT_SLOT = new ControllerBinding(controller, Bind.RIGHT_BUMPER, new ResourceLocation("controlify", "next_slot"), null));
|
||||||
register(PREV_SLOT = new ControllerBinding(controller, Bind.LEFT_BUMPER, new ResourceLocation("controlify", "prev_slot"), null));
|
register(PREV_SLOT = new ControllerBinding(controller, Bind.LEFT_BUMPER, new ResourceLocation("controlify", "prev_slot"), null));
|
||||||
register(PAUSE = new ControllerBinding(controller, Bind.START, new ResourceLocation("controlify", "pause"), null));
|
register(PAUSE = new ControllerBinding(controller, Bind.START, new ResourceLocation("controlify", "pause"), null));
|
||||||
@ -43,6 +45,7 @@ public class ControllerBindings {
|
|||||||
register(GUI_PRESS = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "gui_press"), null));
|
register(GUI_PRESS = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "gui_press"), null));
|
||||||
register(GUI_BACK = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "gui_back"), null));
|
register(GUI_BACK = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "gui_back"), null));
|
||||||
|
|
||||||
|
|
||||||
ControlifyEvents.CONTROLLER_BIND_REGISTRY.invoker().onRegisterControllerBinds(this, controller);
|
ControlifyEvents.CONTROLLER_BIND_REGISTRY.invoker().onRegisterControllerBinds(this, controller);
|
||||||
|
|
||||||
ControlifyEvents.CONTROLLER_STATE_UPDATED.register(this::imitateVanillaClick);
|
ControlifyEvents.CONTROLLER_STATE_UPDATED.register(this::imitateVanillaClick);
|
||||||
|
@ -3,17 +3,22 @@ package dev.isxander.controlify.compatibility.screen;
|
|||||||
import dev.isxander.controlify.Controlify;
|
import dev.isxander.controlify.Controlify;
|
||||||
import dev.isxander.controlify.InputMode;
|
import dev.isxander.controlify.InputMode;
|
||||||
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
|
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
|
||||||
|
import dev.isxander.controlify.compatibility.screen.component.CustomFocus;
|
||||||
import dev.isxander.controlify.controller.Controller;
|
import dev.isxander.controlify.controller.Controller;
|
||||||
import dev.isxander.controlify.mixins.ScreenAccessor;
|
import dev.isxander.controlify.mixins.compat.screen.vanilla.ScreenAccessor;
|
||||||
import net.minecraft.client.gui.ComponentPath;
|
import net.minecraft.client.gui.ComponentPath;
|
||||||
|
import net.minecraft.client.gui.components.events.AbstractContainerEventHandler;
|
||||||
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
import net.minecraft.client.gui.navigation.FocusNavigationEvent;
|
import net.minecraft.client.gui.navigation.FocusNavigationEvent;
|
||||||
import net.minecraft.client.gui.navigation.ScreenDirection;
|
import net.minecraft.client.gui.navigation.ScreenDirection;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
|
||||||
public class ScreenProcessor {
|
public class ScreenProcessor {
|
||||||
private static final int REPEAT_DELAY = 5;
|
private static final int REPEAT_DELAY = 3;
|
||||||
private static final int INITIAL_REPEAT_DELAY = 20;
|
|
||||||
|
|
||||||
public final Screen screen;
|
public final Screen screen;
|
||||||
private int lastMoved = 0;
|
private int lastMoved = 0;
|
||||||
@ -28,15 +33,16 @@ public class ScreenProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void handleComponentNavigation(Controller controller) {
|
protected void handleComponentNavigation(Controller controller) {
|
||||||
if (screen.getFocused() != null) {
|
var focusTree = getFocusTree();
|
||||||
var focused = screen.getFocused();
|
while (!focusTree.isEmpty()) {
|
||||||
|
var focused = focusTree.poll();
|
||||||
var processor = ComponentProcessorProvider.provide(focused);
|
var processor = ComponentProcessorProvider.provide(focused);
|
||||||
if (processor.overrideControllerNavigation(this, controller)) return;
|
if (processor.overrideControllerNavigation(this, controller)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var accessor = (ScreenAccessor) screen;
|
var accessor = (ScreenAccessor) screen;
|
||||||
|
|
||||||
boolean repeatEventAvailable = ++lastMoved > INITIAL_REPEAT_DELAY;
|
boolean repeatEventAvailable = ++lastMoved >= REPEAT_DELAY;
|
||||||
|
|
||||||
var axes = controller.state().axes();
|
var axes = controller.state().axes();
|
||||||
var prevAxes = controller.prevState().axes();
|
var prevAxes = controller.prevState().axes();
|
||||||
@ -67,14 +73,15 @@ public class ScreenProcessor {
|
|||||||
if (path != null) {
|
if (path != null) {
|
||||||
accessor.invokeChangeFocus(path);
|
accessor.invokeChangeFocus(path);
|
||||||
ComponentProcessorProvider.provide(path.component()).onNavigateTo(this, controller);
|
ComponentProcessorProvider.provide(path.component()).onNavigateTo(this, controller);
|
||||||
lastMoved = repeatEventAvailable ? INITIAL_REPEAT_DELAY - REPEAT_DELAY : 0;
|
lastMoved = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleButtons(Controller controller) {
|
protected void handleButtons(Controller controller) {
|
||||||
if (screen.getFocused() != null) {
|
var focusTree = getFocusTree();
|
||||||
var focused = screen.getFocused();
|
while (!focusTree.isEmpty()) {
|
||||||
|
var focused = focusTree.poll();
|
||||||
var processor = ComponentProcessorProvider.provide(focused);
|
var processor = ComponentProcessorProvider.provide(focused);
|
||||||
if (processor.overrideControllerButtons(this, controller)) return;
|
if (processor.overrideControllerButtons(this, controller)) return;
|
||||||
}
|
}
|
||||||
@ -94,4 +101,18 @@ public class ScreenProcessor {
|
|||||||
accessor.invokeChangeFocus(path);
|
accessor.invokeChangeFocus(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Queue<GuiEventListener> getFocusTree() {
|
||||||
|
if (screen.getFocused() == null) return new ArrayDeque<>();
|
||||||
|
|
||||||
|
var tree = new ArrayDeque<GuiEventListener>();
|
||||||
|
var focused = screen.getFocused();
|
||||||
|
tree.add(focused);
|
||||||
|
while (focused instanceof CustomFocus customFocus) {
|
||||||
|
focused = customFocus.getCustomFocus();
|
||||||
|
tree.addFirst(focused);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,23 +7,17 @@ import dev.isxander.controlify.controller.Controller;
|
|||||||
import dev.isxander.controlify.controller.ControllerState;
|
import dev.isxander.controlify.controller.ControllerState;
|
||||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
|
|
||||||
public class ComponentProcessor<T extends GuiEventListener> {
|
public interface ComponentProcessor {
|
||||||
static final ComponentProcessor<?> EMPTY = new ComponentProcessor<>(null);
|
ComponentProcessor EMPTY = new ComponentProcessor(){};
|
||||||
|
|
||||||
protected final T component;
|
default boolean overrideControllerNavigation(ScreenProcessor screen, Controller controller) {
|
||||||
|
|
||||||
public ComponentProcessor(T component) {
|
|
||||||
this.component = component;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean overrideControllerNavigation(ScreenProcessor screen, Controller controller) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean overrideControllerButtons(ScreenProcessor screen, Controller controller) {
|
default boolean overrideControllerButtons(ScreenProcessor screen, Controller controller) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onNavigateTo(ScreenProcessor screen, Controller controller) {
|
default void onNavigateTo(ScreenProcessor screen, Controller controller) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ package dev.isxander.controlify.compatibility.screen.component;
|
|||||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
|
|
||||||
public interface ComponentProcessorProvider {
|
public interface ComponentProcessorProvider {
|
||||||
ComponentProcessor<?> componentProcessor();
|
ComponentProcessor componentProcessor();
|
||||||
|
|
||||||
static ComponentProcessor<?> provide(GuiEventListener component) {
|
static ComponentProcessor provide(GuiEventListener component) {
|
||||||
if (component instanceof ComponentProcessorProvider provider)
|
if (component instanceof ComponentProcessorProvider provider)
|
||||||
return provider.componentProcessor();
|
return provider.componentProcessor();
|
||||||
return ComponentProcessor.EMPTY;
|
return ComponentProcessor.EMPTY;
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package dev.isxander.controlify.compatibility.screen.component;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
|
|
||||||
|
public interface CustomFocus {
|
||||||
|
GuiEventListener getCustomFocus();
|
||||||
|
}
|
@ -8,15 +8,17 @@ import org.lwjgl.glfw.GLFW;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class SliderComponentProcessor extends ComponentProcessor<AbstractSliderButton> {
|
public class SliderComponentProcessor implements ComponentProcessor {
|
||||||
private final Supplier<Boolean> canChangeValueGetter;
|
private final Supplier<Boolean> canChangeValueGetter;
|
||||||
private final Consumer<Boolean> canChangeValueSetter;
|
private final Consumer<Boolean> canChangeValueSetter;
|
||||||
|
|
||||||
|
private final AbstractSliderButton component;
|
||||||
|
|
||||||
private static final int SLIDER_CHANGE_DELAY = 1;
|
private static final int SLIDER_CHANGE_DELAY = 1;
|
||||||
private int lastSliderChange = SLIDER_CHANGE_DELAY;
|
private int lastSliderChange = SLIDER_CHANGE_DELAY;
|
||||||
|
|
||||||
public SliderComponentProcessor(AbstractSliderButton component, Supplier<Boolean> canChangeValueGetter, Consumer<Boolean> canChangeValueSetter) {
|
public SliderComponentProcessor(AbstractSliderButton component, Supplier<Boolean> canChangeValueGetter, Consumer<Boolean> canChangeValueSetter) {
|
||||||
super(component);
|
this.component = component;
|
||||||
this.canChangeValueGetter = canChangeValueGetter;
|
this.canChangeValueGetter = canChangeValueGetter;
|
||||||
this.canChangeValueSetter = canChangeValueSetter;
|
this.canChangeValueSetter = canChangeValueSetter;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ public class ControlifyConfig {
|
|||||||
|
|
||||||
for (var controller : Controller.CONTROLLERS.values()) {
|
for (var controller : Controller.CONTROLLERS.values()) {
|
||||||
// `add` replaces if already existing
|
// `add` replaces if already existing
|
||||||
|
// TODO: find a better way to identify controllers, GUID will report the same for multiple controllers of the same model
|
||||||
configCopy.add(controller.guid(), generateControllerConfig(controller));
|
configCopy.add(controller.guid(), generateControllerConfig(controller));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,119 @@
|
|||||||
|
package dev.isxander.controlify.config.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import dev.isxander.controlify.bindings.Bind;
|
||||||
|
import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
|
||||||
|
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
|
||||||
|
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
|
||||||
|
import dev.isxander.controlify.event.ControlifyEvents;
|
||||||
|
import dev.isxander.controlify.gui.ButtonRenderer;
|
||||||
|
import dev.isxander.yacl.api.Controller;
|
||||||
|
import dev.isxander.yacl.api.Option;
|
||||||
|
import dev.isxander.yacl.api.utils.Dimension;
|
||||||
|
import dev.isxander.yacl.gui.AbstractWidget;
|
||||||
|
import dev.isxander.yacl.gui.YACLScreen;
|
||||||
|
import dev.isxander.yacl.gui.controllers.ControllerWidget;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public BindButtonController(Option<Bind> option) {
|
||||||
|
this.option = option;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Option<Bind> option() {
|
||||||
|
return this.option;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component formatValue() {
|
||||||
|
return Component.literal(option().pendingValue().identifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractWidget provideWidget(YACLScreen yaclScreen, Dimension<Integer> dimension) {
|
||||||
|
return new BindButtonWidget(this, yaclScreen, dimension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BindButtonWidget extends ControllerWidget<BindButtonController> implements ComponentProcessorProvider, ComponentProcessor {
|
||||||
|
private boolean awaitingControllerInput = false;
|
||||||
|
private final Component awaitingText = Component.translatable("controlify.gui.bind_input_awaiting").withStyle(ChatFormatting.ITALIC);
|
||||||
|
|
||||||
|
public BindButtonWidget(BindButtonController control, YACLScreen screen, Dimension<Integer> dim) {
|
||||||
|
super(control, screen, dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
} else {
|
||||||
|
ButtonRenderer.drawButton(control.option().pendingValue(), matrices, getDimension().xLimit() - ButtonRenderer.BUTTON_SIZE / 2, getDimension().centerY(), ButtonRenderer.BUTTON_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||||
|
if (isFocused() && keyCode == GLFW.GLFW_KEY_ENTER && !awaitingControllerInput) {
|
||||||
|
awaitingControllerInput = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||||
|
if (getDimension().isPointInside((int)mouseX, (int)mouseY)) {
|
||||||
|
awaitingControllerInput = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentProcessor componentProcessor() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean overrideControllerNavigation(ScreenProcessor screen, dev.isxander.controlify.controller.Controller controller) {
|
||||||
|
return awaitingControllerInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getHoveredControlWidth() {
|
||||||
|
return getUnhoveredControlWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getUnhoveredControlWidth() {
|
||||||
|
if (awaitingControllerInput)
|
||||||
|
return textRenderer.width(awaitingText);
|
||||||
|
|
||||||
|
return ButtonRenderer.BUTTON_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package dev.isxander.controlify.config.gui;
|
package dev.isxander.controlify.config.gui;
|
||||||
|
|
||||||
|
import dev.isxander.controlify.bindings.Bind;
|
||||||
import dev.isxander.controlify.config.ControlifyConfig;
|
import dev.isxander.controlify.config.ControlifyConfig;
|
||||||
import dev.isxander.controlify.controller.Controller;
|
import dev.isxander.controlify.controller.Controller;
|
||||||
import dev.isxander.controlify.controller.ControllerConfig;
|
import dev.isxander.controlify.controller.ControllerConfig;
|
||||||
@ -69,6 +70,17 @@ public class YACLHelper {
|
|||||||
.build());
|
.build());
|
||||||
category.group(configGroup.build());
|
category.group(configGroup.build());
|
||||||
|
|
||||||
|
var controlsGroup = OptionGroup.createBuilder()
|
||||||
|
.name(Component.translatable("controlify.gui.group.controls"));
|
||||||
|
for (var control : controller.bindings().registry().values()) {
|
||||||
|
controlsGroup.option(Option.createBuilder(Bind.class)
|
||||||
|
.name(control.name())
|
||||||
|
.binding(control.defaultBind(), control::currentBind, control::setCurrentBind)
|
||||||
|
.controller(BindButtonController::new)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
category.group(controlsGroup.build());
|
||||||
|
|
||||||
yacl.category(category.build());
|
yacl.category(category.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package dev.isxander.controlify.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import dev.isxander.controlify.bindings.Bind;
|
||||||
|
import net.minecraft.client.gui.GuiComponent;
|
||||||
|
|
||||||
|
public class ButtonRenderer {
|
||||||
|
public static final int BUTTON_SIZE = 22;
|
||||||
|
|
||||||
|
public static void drawButton(Bind button, PoseStack poseStack, int x, int y, int size) {
|
||||||
|
RenderSystem.setShaderTexture(0, button.textureLocation());
|
||||||
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
|
||||||
|
GuiComponent.blit(poseStack, x - size / 2, y - size / 2, 0, 0, BUTTON_SIZE, BUTTON_SIZE, BUTTON_SIZE, BUTTON_SIZE);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package dev.isxander.controlify.mixins.compat.screen.vanilla;
|
||||||
|
|
||||||
|
import dev.isxander.controlify.compatibility.screen.component.CustomFocus;
|
||||||
|
import net.minecraft.client.gui.components.events.AbstractContainerEventHandler;
|
||||||
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
@Mixin(AbstractContainerEventHandler.class)
|
||||||
|
public abstract class AbstractContainerEventHandlerMixin implements CustomFocus {
|
||||||
|
@Shadow public abstract @Nullable GuiEventListener getFocused();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuiEventListener getCustomFocus() {
|
||||||
|
return getFocused();
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package dev.isxander.controlify.mixins;
|
package dev.isxander.controlify.mixins.compat.screen.vanilla;
|
||||||
|
|
||||||
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
|
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
|
||||||
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
|
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
|
||||||
@ -23,7 +23,7 @@ public class AbstractSliderButtonMixin implements ComponentProcessorProvider {
|
|||||||
);
|
);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ComponentProcessor<AbstractSliderButton> componentProcessor() {
|
public ComponentProcessor componentProcessor() {
|
||||||
return controlify$processor;
|
return controlify$processor;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package dev.isxander.controlify.mixins.compat.screen.vanilla;
|
||||||
|
|
||||||
|
import dev.isxander.controlify.compatibility.screen.component.CustomFocus;
|
||||||
|
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
|
||||||
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
@Mixin(ContainerObjectSelectionList.Entry.class)
|
||||||
|
public abstract class ContainerObjectSelectionListEntryMixin implements CustomFocus {
|
||||||
|
@Shadow public abstract @Nullable GuiEventListener getFocused();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuiEventListener getCustomFocus() {
|
||||||
|
return getFocused();
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package dev.isxander.controlify.mixins;
|
package dev.isxander.controlify.mixins.compat.screen.vanilla;
|
||||||
|
|
||||||
import net.minecraft.client.gui.ComponentPath;
|
import net.minecraft.client.gui.ComponentPath;
|
||||||
import net.minecraft.client.gui.navigation.FocusNavigationEvent;
|
import net.minecraft.client.gui.navigation.FocusNavigationEvent;
|
@ -1,4 +1,4 @@
|
|||||||
package dev.isxander.controlify.mixins;
|
package dev.isxander.controlify.mixins.compat.screen.vanilla;
|
||||||
|
|
||||||
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider;
|
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider;
|
||||||
import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
|
import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
|
@ -1,4 +1,4 @@
|
|||||||
package dev.isxander.controlify.mixins;
|
package dev.isxander.controlify.mixins.core;
|
||||||
|
|
||||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
@ -1,4 +1,4 @@
|
|||||||
package dev.isxander.controlify.mixins;
|
package dev.isxander.controlify.mixins.core;
|
||||||
|
|
||||||
import dev.isxander.controlify.Controlify;
|
import dev.isxander.controlify.Controlify;
|
||||||
import dev.isxander.controlify.InputMode;
|
import dev.isxander.controlify.InputMode;
|
@ -1,4 +1,4 @@
|
|||||||
package dev.isxander.controlify.mixins;
|
package dev.isxander.controlify.mixins.core;
|
||||||
|
|
||||||
import dev.isxander.controlify.Controlify;
|
import dev.isxander.controlify.Controlify;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
@ -1,4 +1,4 @@
|
|||||||
package dev.isxander.controlify.mixins;
|
package dev.isxander.controlify.mixins.core;
|
||||||
|
|
||||||
import dev.isxander.controlify.Controlify;
|
import dev.isxander.controlify.Controlify;
|
||||||
import dev.isxander.controlify.InputMode;
|
import dev.isxander.controlify.InputMode;
|
@ -1,4 +1,4 @@
|
|||||||
package dev.isxander.controlify.mixins;
|
package dev.isxander.controlify.mixins.feature.bind;
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.InputConstants;
|
import com.mojang.blaze3d.platform.InputConstants;
|
||||||
import net.minecraft.client.KeyMapping;
|
import net.minecraft.client.KeyMapping;
|
@ -1,6 +1,10 @@
|
|||||||
{
|
{
|
||||||
"controlify.gui.group.config": "Config",
|
"controlify.gui.group.config": "Config",
|
||||||
"controlify.gui.group.config.tooltip": "Adjust the controller configuration.",
|
"controlify.gui.group.config.tooltip": "Adjust the controller configuration.",
|
||||||
|
"controlify.gui.horizontal_look_sensitivity": "Horizontal Look Sensitivity",
|
||||||
|
"controlify.gui.horizontal_look_sensitivity.tooltip": "How fast the camera moves horizontally when looking around.",
|
||||||
|
"controlify.gui.vertical_look_sensitivity": "Vertical Look Sensitivity",
|
||||||
|
"controlify.gui.vertical_look_sensitivity.tooltip": "How fast the camera moves vertically when looking around.",
|
||||||
"controlify.gui.left_stick_deadzone": "Left Stick Deadzone",
|
"controlify.gui.left_stick_deadzone": "Left Stick Deadzone",
|
||||||
"controlify.gui.left_stick_deadzone.tooltip": "How far the left joystick needs to be pushed before registering input.",
|
"controlify.gui.left_stick_deadzone.tooltip": "How far the left joystick needs to be pushed before registering input.",
|
||||||
"controlify.gui.right_stick_deadzone": "Right Stick Deadzone",
|
"controlify.gui.right_stick_deadzone": "Right Stick Deadzone",
|
||||||
@ -9,5 +13,24 @@
|
|||||||
"controlify.gui.left_trigger_threshold": "Left Trigger Threshold",
|
"controlify.gui.left_trigger_threshold": "Left Trigger Threshold",
|
||||||
"controlify.gui.left_trigger_threshold.tooltip": "How far the left trigger needs to be pushed before registering as pressed.",
|
"controlify.gui.left_trigger_threshold.tooltip": "How far the left trigger needs to be pushed before registering as pressed.",
|
||||||
"controlify.gui.right_trigger_threshold": "Right Trigger Threshold",
|
"controlify.gui.right_trigger_threshold": "Right Trigger Threshold",
|
||||||
"controlify.gui.right_trigger_threshold.tooltip": "How far the right trigger needs to be pushed before registering as pressed."
|
"controlify.gui.right_trigger_threshold.tooltip": "How far the right trigger needs to be pushed before registering as pressed.",
|
||||||
|
|
||||||
|
"controlify.gui.group.controls": "Controls",
|
||||||
|
"controlify.gui.group.controls.tooltip": "Adjust the controller controls.",
|
||||||
|
"controlify.gui.bind_input_awaiting": "Press any button",
|
||||||
|
|
||||||
|
"controlify.binding.controlify.jump": "Jump",
|
||||||
|
"controlify.binding.controlify.sneak": "Sneak",
|
||||||
|
"controlify.binding.controlify.attack": "Attack",
|
||||||
|
"controlify.binding.controlify.use": "Use",
|
||||||
|
"controlify.binding.controlify.sprint": "Sprint",
|
||||||
|
"controlify.binding.controlify.next_slot": "Next Hotbar Slot",
|
||||||
|
"controlify.binding.controlify.prev_slot": "Previous Hotbar Slot",
|
||||||
|
"controlify.binding.controlify.pause": "Pause Game",
|
||||||
|
"controlify.binding.controlify.inventory": "Open Inventory",
|
||||||
|
"controlify.binding.controlify.change_perspective": "Change Perspective",
|
||||||
|
"controlify.binding.controlify.open_chat": "Open Chat",
|
||||||
|
"controlify.binding.controlify.gui_press": "GUI Press",
|
||||||
|
"controlify.binding.controlify.gui_back": "GUI Back",
|
||||||
|
"controlify.binding.controlify.drop": "Drop Item"
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,15 @@
|
|||||||
"mixins": [
|
"mixins": [
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"AbstractSliderButtonMixin",
|
"compat.screen.vanilla.AbstractContainerEventHandlerMixin",
|
||||||
"ClientPacketListenerMixin",
|
"compat.screen.vanilla.AbstractSliderButtonMixin",
|
||||||
"KeyboardHandlerMixin",
|
"core.ClientPacketListenerMixin",
|
||||||
"KeyMappingAccessor",
|
"compat.screen.vanilla.ContainerObjectSelectionListEntryMixin",
|
||||||
"MinecraftMixin",
|
"core.KeyboardHandlerMixin",
|
||||||
"MouseHandlerMixin",
|
"feature.bind.KeyMappingAccessor",
|
||||||
"ScreenAccessor",
|
"core.MinecraftMixin",
|
||||||
"ScreenMixin"
|
"core.MouseHandlerMixin",
|
||||||
|
"compat.screen.vanilla.ScreenAccessor",
|
||||||
|
"compat.screen.vanilla.ScreenMixin"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user