From 75fa069a9842f21a61e66c4528b1a53b0eeeb2fd Mon Sep 17 00:00:00 2001 From: isXander Date: Mon, 20 Feb 2023 19:50:40 +0000 Subject: [PATCH] sodium compat --- build.gradle.kts | 6 ++ gradle/libs.versions.toml | 2 + .../bindings/ControllerBindings.java | 6 +- .../controlify/compatibility/.gitkeep | 0 .../compatibility/sodium/ButtonProcessor.java | 23 +++++++ .../sodium/CycleControlProcessor.java | 29 +++++++++ .../sodium/SliderControlProcessor.java | 40 ++++++++++++ .../sodium/SodiumGuiScreenProcessor.java | 35 +++++++++++ .../sodium/TickBoxControlProcessor.java | 27 ++++++++ ...ngControllerElementComponentProcessor.java | 2 +- ...erControllerElementComponentProcessor.java | 6 +- .../yacl/YACLScreenProcessor.java | 2 +- .../compat/sodium/AbstractWidgetMixin.java | 24 +++++++ .../compat/sodium/ControlElementMixin.java | 58 +++++++++++++++++ .../sodium/CycleControlElementMixin.java | 31 +++++++++ .../compat/sodium/FlatButtonWidgetMixin.java | 63 +++++++++++++++++++ .../sodium/SliderControlElementMixin.java | 38 +++++++++++ .../sodium/SodiumOptionsGUIAccessor.java | 17 +++++ .../compat/sodium/SodiumOptionsGUIMixin.java | 40 ++++++++++++ .../sodium/TickBoxControlElementMixin.java | 25 ++++++++ .../yacl/CyclingControllerElementMixin.java | 4 +- .../yacl/SliderControllerElementMixin.java | 4 +- .../yacl/YACLScreenMixin.java | 4 +- .../vanilla/SliderComponentProcessor.java | 1 - .../assets/controlify/lang/en_us.json | 4 +- src/main/resources/controlify.mixins.json | 14 ++++- 26 files changed, 485 insertions(+), 20 deletions(-) delete mode 100644 src/main/java/dev/isxander/controlify/compatibility/.gitkeep create mode 100644 src/main/java/dev/isxander/controlify/compatibility/sodium/ButtonProcessor.java create mode 100644 src/main/java/dev/isxander/controlify/compatibility/sodium/CycleControlProcessor.java create mode 100644 src/main/java/dev/isxander/controlify/compatibility/sodium/SliderControlProcessor.java create mode 100644 src/main/java/dev/isxander/controlify/compatibility/sodium/SodiumGuiScreenProcessor.java create mode 100644 src/main/java/dev/isxander/controlify/compatibility/sodium/TickBoxControlProcessor.java rename src/main/java/dev/isxander/controlify/{screenop/compat => compatibility}/yacl/CyclingControllerElementComponentProcessor.java (96%) rename src/main/java/dev/isxander/controlify/{screenop/compat => compatibility}/yacl/SliderControllerElementComponentProcessor.java (86%) rename src/main/java/dev/isxander/controlify/{screenop/compat => compatibility}/yacl/YACLScreenProcessor.java (95%) create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/sodium/AbstractWidgetMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/sodium/ControlElementMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/sodium/CycleControlElementMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/sodium/FlatButtonWidgetMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/sodium/SliderControlElementMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/sodium/SodiumOptionsGUIAccessor.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/sodium/SodiumOptionsGUIMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/sodium/TickBoxControlElementMixin.java rename src/main/java/dev/isxander/controlify/mixins/{feature/screenop => compat}/yacl/CyclingControllerElementMixin.java (81%) rename src/main/java/dev/isxander/controlify/mixins/{feature/screenop => compat}/yacl/SliderControllerElementMixin.java (81%) rename src/main/java/dev/isxander/controlify/mixins/{feature/screenop => compat}/yacl/YACLScreenMixin.java (80%) diff --git a/build.gradle.kts b/build.gradle.kts index 608bed9..f2d5001 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,6 +28,7 @@ repositories { } } maven("https://jitpack.io") + maven("https://maven.flashyreese.me/snapshots") } loom { @@ -52,11 +53,16 @@ dependencies { annotationProcessor(libs.mixin.extras) include(libs.mixin.extras) + // used to identify controller connections implementation(libs.hid4java) include(libs.hid4java) + // used to parse hiddb.json5 implementation(libs.quilt.json5) include(libs.quilt.json5) + + // sodium compat + modImplementation(libs.sodium) } tasks { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 497bd93..657f23d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,6 +16,7 @@ yet_another_config_lib = "2.3.0+beta.2+update.1.19.4-SNAPSHOT" mod_menu = "6.1.0-alpha.1" hid4java = "0.7.0" quilt_json5 = "1.0.3" +sodium = "0.4.10+build.209" [libraries] minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" } @@ -27,6 +28,7 @@ yet_another_config_lib = { module = "dev.isxander:yet-another-config-lib", versi mod_menu = { module = "com.terraformersmc:modmenu", version.ref = "mod_menu" } hid4java = { module = "org.hid4java:hid4java", version.ref = "hid4java" } quilt_json5 = { module = "org.quiltmc:quilt-json5", version.ref = "quilt_json5" } +sodium = { module = "me.jellysquid.mods:sodium-fabric", version.ref = "sodium" } [plugins] loom = { id = "fabric-loom", version.ref = "loom" } diff --git a/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java b/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java index 9a2ea95..e2cee7c 100644 --- a/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java +++ b/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java @@ -38,7 +38,7 @@ public class ControllerBindings { VMOUSE_ESCAPE, VMOUSE_SHIFT, VMOUSE_TOGGLE, GUI_NAVI_UP, GUI_NAVI_DOWN, GUI_NAVI_LEFT, GUI_NAVI_RIGHT, - YACL_CYCLE_OPT_FORWARD, YACL_CYCLE_OPT_BACKWARD; + CYCLE_OPT_FORWARD, CYCLE_OPT_BACKWARD; private final Map> registry = new LinkedHashMap<>(); @@ -92,8 +92,8 @@ public class ControllerBindings { register(GUI_NAVI_DOWN = new ControllerBinding<>(controller, GamepadBinds.LEFT_STICK_BACKWARD, new ResourceLocation("controlify", "gui_navi_down"))); register(GUI_NAVI_LEFT = new ControllerBinding<>(controller, GamepadBinds.LEFT_STICK_LEFT, new ResourceLocation("controlify", "gui_navi_left"))); register(GUI_NAVI_RIGHT = new ControllerBinding<>(controller, GamepadBinds.LEFT_STICK_RIGHT, new ResourceLocation("controlify", "gui_navi_right"))); - register(YACL_CYCLE_OPT_FORWARD = new ControllerBinding<>(controller, GamepadBinds.RIGHT_STICK_RIGHT, new ResourceLocation("controlify", "yacl_cycle_opt_forward"))); - register(YACL_CYCLE_OPT_BACKWARD = new ControllerBinding<>(controller, GamepadBinds.RIGHT_STICK_LEFT, new ResourceLocation("controlify", "yacl_cycle_opt_backward"))); + register(CYCLE_OPT_FORWARD = new ControllerBinding<>(controller, GamepadBinds.RIGHT_STICK_RIGHT, new ResourceLocation("controlify", "cycle_opt_forward"))); + register(CYCLE_OPT_BACKWARD = new ControllerBinding<>(controller, GamepadBinds.RIGHT_STICK_LEFT, new ResourceLocation("controlify", "cycle_opt_backward"))); ControlifyEvents.CONTROLLER_BIND_REGISTRY.invoker().onRegisterControllerBinds(this, controller); diff --git a/src/main/java/dev/isxander/controlify/compatibility/.gitkeep b/src/main/java/dev/isxander/controlify/compatibility/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/dev/isxander/controlify/compatibility/sodium/ButtonProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/sodium/ButtonProcessor.java new file mode 100644 index 0000000..4f72e98 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/compatibility/sodium/ButtonProcessor.java @@ -0,0 +1,23 @@ +package dev.isxander.controlify.compatibility.sodium; + +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.screenop.ComponentProcessor; +import dev.isxander.controlify.screenop.ScreenProcessor; + +public class ButtonProcessor implements ComponentProcessor { + private final Runnable action; + + public ButtonProcessor(Runnable action) { + this.action = action != null ? action : () -> {}; + } + + @Override + public boolean overrideControllerButtons(ScreenProcessor screen, Controller controller) { + if (controller.bindings().GUI_PRESS.justPressed()) { + action.run(); + return true; + } + + return false; + } +} diff --git a/src/main/java/dev/isxander/controlify/compatibility/sodium/CycleControlProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/sodium/CycleControlProcessor.java new file mode 100644 index 0000000..2ac16a8 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/compatibility/sodium/CycleControlProcessor.java @@ -0,0 +1,29 @@ +package dev.isxander.controlify.compatibility.sodium; + +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.screenop.ComponentProcessor; +import dev.isxander.controlify.screenop.ScreenProcessor; + +import java.util.function.Consumer; + +public class CycleControlProcessor implements ComponentProcessor { + private final Consumer cycleMethod; + + public CycleControlProcessor(Consumer cycleMethod) { + this.cycleMethod = cycleMethod; + } + + @Override + public boolean overrideControllerButtons(ScreenProcessor screen, Controller controller) { + if (controller.bindings().CYCLE_OPT_FORWARD.justPressed() || controller.bindings().GUI_PRESS.justPressed()) { + cycleMethod.accept(false); + return true; + } + if (controller.bindings().CYCLE_OPT_BACKWARD.justPressed()) { + cycleMethod.accept(true); + return true; + } + + return false; + } +} diff --git a/src/main/java/dev/isxander/controlify/compatibility/sodium/SliderControlProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/sodium/SliderControlProcessor.java new file mode 100644 index 0000000..4618e05 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/compatibility/sodium/SliderControlProcessor.java @@ -0,0 +1,40 @@ +package dev.isxander.controlify.compatibility.sodium; + +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.screenop.ComponentProcessor; +import dev.isxander.controlify.screenop.ScreenProcessor; + +import java.util.function.Consumer; + +public class SliderControlProcessor implements ComponentProcessor { + private final Consumer cycleMethod; + private int ticksSinceIncrement = 0; + private boolean prevLeft, prevRight; + + public SliderControlProcessor(Consumer cycleMethod) { + this.cycleMethod = cycleMethod; + } + + @Override + public boolean overrideControllerButtons(ScreenProcessor screen, Controller controller) { + ticksSinceIncrement++; + + var left = controller.bindings().CYCLE_OPT_BACKWARD.held(); + var right = controller.bindings().CYCLE_OPT_FORWARD.held(); + + if (left || right) { + if (ticksSinceIncrement > controller.config().screenRepeatNavigationDelay || left != prevLeft || right != prevRight) { + cycleMethod.accept(left); + ticksSinceIncrement = 0; + prevLeft = left; + prevRight = right; + return true; + } + } else { + this.prevLeft = false; + this.prevRight = false; + } + + return false; + } +} diff --git a/src/main/java/dev/isxander/controlify/compatibility/sodium/SodiumGuiScreenProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/sodium/SodiumGuiScreenProcessor.java new file mode 100644 index 0000000..bda0439 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/compatibility/sodium/SodiumGuiScreenProcessor.java @@ -0,0 +1,35 @@ +package dev.isxander.controlify.compatibility.sodium; + +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.mixins.compat.sodium.SodiumOptionsGUIAccessor; +import dev.isxander.controlify.screenop.ScreenProcessor; +import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI; + +public class SodiumGuiScreenProcessor extends ScreenProcessor { + public SodiumGuiScreenProcessor(SodiumOptionsGUI screen) { + super(screen); + } + + @Override + protected void handleComponentNavigation(Controller controller) { + super.handleComponentNavigation(controller); + } + + @Override + protected void handleButtons(Controller controller) { + var accessor = (SodiumOptionsGUIAccessor) screen; + + if (controller.bindings().GUI_NEXT_TAB.justPressed()) { + var currentIndex = accessor.getPages().indexOf(accessor.getCurrentPage()); + var nextIndex = (currentIndex + 1) % accessor.getPages().size(); + screen.setPage(accessor.getPages().get(nextIndex)); + } + if (controller.bindings().GUI_PREV_TAB.justPressed()) { + var currentIndex = accessor.getPages().indexOf(accessor.getCurrentPage()); + var nextIndex = (currentIndex - 1 + accessor.getPages().size()) % accessor.getPages().size(); + screen.setPage(accessor.getPages().get(nextIndex)); + } + + super.handleButtons(controller); + } +} diff --git a/src/main/java/dev/isxander/controlify/compatibility/sodium/TickBoxControlProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/sodium/TickBoxControlProcessor.java new file mode 100644 index 0000000..fe54a3a --- /dev/null +++ b/src/main/java/dev/isxander/controlify/compatibility/sodium/TickBoxControlProcessor.java @@ -0,0 +1,27 @@ +package dev.isxander.controlify.compatibility.sodium; + +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.screenop.ComponentProcessor; +import dev.isxander.controlify.screenop.ScreenProcessor; + +public class TickBoxControlProcessor implements ComponentProcessor { + private final Runnable toggleMethod; + + public TickBoxControlProcessor(Runnable toggleMethod) { + this.toggleMethod = toggleMethod; + } + + @Override + public boolean overrideControllerButtons(ScreenProcessor screen, Controller controller) { + if (controller.bindings().GUI_PRESS.justPressed()) { + toggleMethod.run(); + return true; + } + if (controller.bindings().CYCLE_OPT_FORWARD.justPressed() || controller.bindings().CYCLE_OPT_BACKWARD.justPressed()) { + toggleMethod.run(); + return true; + } + + return false; + } +} diff --git a/src/main/java/dev/isxander/controlify/screenop/compat/yacl/CyclingControllerElementComponentProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/yacl/CyclingControllerElementComponentProcessor.java similarity index 96% rename from src/main/java/dev/isxander/controlify/screenop/compat/yacl/CyclingControllerElementComponentProcessor.java rename to src/main/java/dev/isxander/controlify/compatibility/yacl/CyclingControllerElementComponentProcessor.java index 6368d2b..96ef45f 100644 --- a/src/main/java/dev/isxander/controlify/screenop/compat/yacl/CyclingControllerElementComponentProcessor.java +++ b/src/main/java/dev/isxander/controlify/compatibility/yacl/CyclingControllerElementComponentProcessor.java @@ -1,4 +1,4 @@ -package dev.isxander.controlify.screenop.compat.yacl; +package dev.isxander.controlify.compatibility.yacl; import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.screenop.ScreenProcessor; diff --git a/src/main/java/dev/isxander/controlify/screenop/compat/yacl/SliderControllerElementComponentProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/yacl/SliderControllerElementComponentProcessor.java similarity index 86% rename from src/main/java/dev/isxander/controlify/screenop/compat/yacl/SliderControllerElementComponentProcessor.java rename to src/main/java/dev/isxander/controlify/compatibility/yacl/SliderControllerElementComponentProcessor.java index 27099b5..a100f15 100644 --- a/src/main/java/dev/isxander/controlify/screenop/compat/yacl/SliderControllerElementComponentProcessor.java +++ b/src/main/java/dev/isxander/controlify/compatibility/yacl/SliderControllerElementComponentProcessor.java @@ -1,4 +1,4 @@ -package dev.isxander.controlify.screenop.compat.yacl; +package dev.isxander.controlify.compatibility.yacl; import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.screenop.ScreenProcessor; @@ -18,8 +18,8 @@ public class SliderControllerElementComponentProcessor implements ComponentProce public boolean overrideControllerButtons(ScreenProcessor screen, Controller controller) { ticksSinceIncrement++; - var left = controller.bindings().GUI_NAVI_LEFT.held(); - var right = controller.bindings().GUI_NAVI_RIGHT.held(); + var left = controller.bindings().CYCLE_OPT_BACKWARD.held(); + var right = controller.bindings().CYCLE_OPT_FORWARD.held(); if (left || right) { if (ticksSinceIncrement > controller.config().screenRepeatNavigationDelay || left != prevLeft || right != prevRight) { diff --git a/src/main/java/dev/isxander/controlify/screenop/compat/yacl/YACLScreenProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/yacl/YACLScreenProcessor.java similarity index 95% rename from src/main/java/dev/isxander/controlify/screenop/compat/yacl/YACLScreenProcessor.java rename to src/main/java/dev/isxander/controlify/compatibility/yacl/YACLScreenProcessor.java index 7f5c8a9..1cb50b3 100644 --- a/src/main/java/dev/isxander/controlify/screenop/compat/yacl/YACLScreenProcessor.java +++ b/src/main/java/dev/isxander/controlify/compatibility/yacl/YACLScreenProcessor.java @@ -1,4 +1,4 @@ -package dev.isxander.controlify.screenop.compat.yacl; +package dev.isxander.controlify.compatibility.yacl; import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.screenop.ScreenProcessor; diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/sodium/AbstractWidgetMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/AbstractWidgetMixin.java new file mode 100644 index 0000000..26ff361 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/AbstractWidgetMixin.java @@ -0,0 +1,24 @@ +package dev.isxander.controlify.mixins.compat.sodium; + +import me.jellysquid.mods.sodium.client.gui.widgets.AbstractWidget; +import net.minecraft.client.gui.ComponentPath; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.navigation.FocusNavigationEvent; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(AbstractWidget.class) +public abstract class AbstractWidgetMixin implements GuiEventListener { + @Shadow protected abstract void drawRect(double x1, double y1, double x2, double y2, int color); + + @Shadow protected abstract void playClickSound(); + + @Shadow public abstract boolean isFocused(); + + @Nullable + @Override + public ComponentPath nextFocusPath(FocusNavigationEvent focusNavigationEvent) { + return !this.isFocused() ? ComponentPath.leaf(this) : null; + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/sodium/ControlElementMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/ControlElementMixin.java new file mode 100644 index 0000000..a24d206 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/ControlElementMixin.java @@ -0,0 +1,58 @@ +package dev.isxander.controlify.mixins.compat.sodium; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.mojang.blaze3d.vertex.PoseStack; +import me.jellysquid.mods.sodium.client.gui.options.Option; +import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement; +import me.jellysquid.mods.sodium.client.util.Dim2i; +import net.minecraft.client.gui.ComponentPath; +import net.minecraft.client.gui.navigation.FocusNavigationEvent; +import net.minecraft.client.gui.navigation.ScreenRectangle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ControlElement.class) +public abstract class ControlElementMixin extends AbstractWidgetMixin { + + @Shadow @Final protected Option option; + @Shadow @Final protected Dim2i dim; + + @Inject(method = "render", at = @At("TAIL")) + private void renderFocusRect(PoseStack matrixStack, int mouseX, int mouseY, float delta, CallbackInfo ci) { + if (this.isFocused()) { + int x1 = this.dim.x(); + int y1 = this.dim.y(); + int x2 = this.dim.getLimitX(); + int y2 = this.dim.getLimitY(); + + this.drawRect(x1, y1, x2, y1 + 1, -1); + this.drawRect(x1, y2 - 1, x2, y2, -1); + this.drawRect(x1, y1, x1 + 1, y2, -1); + this.drawRect(x2 - 1, y1, x2, y2, -1);; + } + } + + @ModifyExpressionValue(method = "render", at = @At(value = "FIELD", target = "Lme/jellysquid/mods/sodium/client/gui/options/control/ControlElement;hovered:Z", opcode = Opcodes.GETFIELD, ordinal = 0)) + private boolean shouldShortenName(boolean hovered) { + return hovered || this.isFocused(); + } + + @Override + public @Nullable ComponentPath nextFocusPath(FocusNavigationEvent focusNavigationEvent) { + if (!this.option.isAvailable()) + return null; + return super.nextFocusPath(focusNavigationEvent); + } + + @Override + public @NotNull ScreenRectangle getRectangle() { + return new ScreenRectangle(this.dim.x(), this.dim.y(), this.dim.width(), this.dim.height()); + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/sodium/CycleControlElementMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/CycleControlElementMixin.java new file mode 100644 index 0000000..1ff14a9 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/CycleControlElementMixin.java @@ -0,0 +1,31 @@ +package dev.isxander.controlify.mixins.compat.sodium; + +import dev.isxander.controlify.compatibility.sodium.CycleControlProcessor; +import dev.isxander.controlify.screenop.ComponentProcessor; +import dev.isxander.controlify.screenop.ComponentProcessorProvider; +import org.spongepowered.asm.mixin.*; + +@Pseudo +@Mixin(targets = "me.jellysquid.mods.sodium.client.gui.options.control.CyclingControl$CyclingControlElement") +public abstract class CycleControlElementMixin> extends ControlElementMixin implements ComponentProcessorProvider { + @Shadow private int currentIndex; + @Final @Shadow private T[] allowedValues; + + @Unique private final ComponentProcessor controlify$componentProcessor + = new CycleControlProcessor(this::cycle); + + @Override + public ComponentProcessor componentProcessor() { + return controlify$componentProcessor; + } + + private void cycle(boolean backwards) { + if (backwards) { + this.currentIndex = (this.currentIndex - 1 + this.allowedValues.length) % this.allowedValues.length; + } else { + this.currentIndex = (this.option.getValue().ordinal() + 1) % this.allowedValues.length; + } + this.option.setValue(this.allowedValues[this.currentIndex]); + this.playClickSound(); + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/sodium/FlatButtonWidgetMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/FlatButtonWidgetMixin.java new file mode 100644 index 0000000..006e9fe --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/FlatButtonWidgetMixin.java @@ -0,0 +1,63 @@ +package dev.isxander.controlify.mixins.compat.sodium; + +import com.mojang.blaze3d.vertex.PoseStack; +import dev.isxander.controlify.compatibility.sodium.ButtonProcessor; +import dev.isxander.controlify.screenop.ComponentProcessor; +import dev.isxander.controlify.screenop.ComponentProcessorProvider; +import me.jellysquid.mods.sodium.client.gui.widgets.FlatButtonWidget; +import me.jellysquid.mods.sodium.client.util.Dim2i; +import net.minecraft.client.gui.ComponentPath; +import net.minecraft.client.gui.navigation.FocusNavigationEvent; +import net.minecraft.client.gui.navigation.ScreenRectangle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(FlatButtonWidget.class) +public abstract class FlatButtonWidgetMixin extends AbstractWidgetMixin implements ComponentProcessorProvider { + @Shadow @Final private Dim2i dim; + @Shadow private boolean visible; + @Shadow private boolean enabled; + @Shadow @Final private Runnable action; + + @Unique private final ComponentProcessor controlify$componentProcessor + = new ButtonProcessor(() -> action.run()); + + @Inject(method = "render", at = @At("TAIL")) + private void renderFocusRect(PoseStack matrixStack, int mouseX, int mouseY, float delta, CallbackInfo ci) { + if (this.enabled && this.isFocused()) { + int x1 = this.dim.x(); + int y1 = this.dim.y(); + int x2 = this.dim.getLimitX(); + int y2 = this.dim.getLimitY(); + + this.drawRect(x1, y1, x2, y1 + 1, -1); + this.drawRect(x1, y2 - 1, x2, y2, -1); + this.drawRect(x1, y1, x1 + 1, y2, -1); + this.drawRect(x2 - 1, y1, x2, y2, -1);; + } + } + + @Override + public @Nullable ComponentPath nextFocusPath(FocusNavigationEvent focusNavigationEvent) { + if (!visible || !enabled) + return null; + return super.nextFocusPath(focusNavigationEvent); + } + + @Override + public @NotNull ScreenRectangle getRectangle() { + return new ScreenRectangle(this.dim.x(), this.dim.y(), this.dim.width(), this.dim.height()); + } + + @Override + public ComponentProcessor componentProcessor() { + return controlify$componentProcessor; + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/sodium/SliderControlElementMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/SliderControlElementMixin.java new file mode 100644 index 0000000..2f5f3f1 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/SliderControlElementMixin.java @@ -0,0 +1,38 @@ +package dev.isxander.controlify.mixins.compat.sodium; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import dev.isxander.controlify.compatibility.sodium.SliderControlProcessor; +import dev.isxander.controlify.screenop.ComponentProcessor; +import dev.isxander.controlify.screenop.ComponentProcessorProvider; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(targets = "me.jellysquid.mods.sodium.client.gui.options.control.SliderControl$Button") +public abstract class SliderControlElementMixin extends ControlElementMixin implements ComponentProcessorProvider { + @Shadow public abstract int getIntValue(); + @Shadow @Final private int interval; + @Shadow protected abstract void setValue(double d); + @Shadow public abstract double getThumbPositionForValue(int value); + + @Unique private final ComponentProcessor controlify$componentProcessor + = new SliderControlProcessor(this::incrementSlider); + + @ModifyExpressionValue(method = "render", at = @At(value = "FIELD", target = "Lme/jellysquid/mods/sodium/client/gui/options/control/SliderControl$Button;hovered:Z", opcode = Opcodes.GETFIELD)) + private boolean shouldRenderSlider(boolean hovered) { + return hovered || this.isFocused(); + } + + @Override + public ComponentProcessor componentProcessor() { + return controlify$componentProcessor; + } + + private void incrementSlider(boolean reverse) { + int inc = reverse ? -1 : 1; + this.setValue(this.getThumbPositionForValue(this.getIntValue() + inc * this.interval)); + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/sodium/SodiumOptionsGUIAccessor.java b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/SodiumOptionsGUIAccessor.java new file mode 100644 index 0000000..6592f08 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/SodiumOptionsGUIAccessor.java @@ -0,0 +1,17 @@ +package dev.isxander.controlify.mixins.compat.sodium; + +import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI; +import me.jellysquid.mods.sodium.client.gui.options.OptionPage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(SodiumOptionsGUI.class) +public interface SodiumOptionsGUIAccessor { + @Accessor + List getPages(); + + @Accessor + OptionPage getCurrentPage(); +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/sodium/SodiumOptionsGUIMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/SodiumOptionsGUIMixin.java new file mode 100644 index 0000000..cdc364f --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/SodiumOptionsGUIMixin.java @@ -0,0 +1,40 @@ +package dev.isxander.controlify.mixins.compat.sodium; + +import dev.isxander.controlify.compatibility.sodium.SodiumGuiScreenProcessor; +import dev.isxander.controlify.screenop.ScreenProcessor; +import dev.isxander.controlify.screenop.ScreenProcessorProvider; +import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI; +import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(value = SodiumOptionsGUI.class, remap = false) +public abstract class SodiumOptionsGUIMixin extends Screen implements ScreenProcessorProvider { + @Shadow @Final private List> controls; + + @Unique private final SodiumGuiScreenProcessor controlify$screenProcessor + = new SodiumGuiScreenProcessor((SodiumOptionsGUI) (Object) this); + + protected SodiumOptionsGUIMixin(Component title) { + super(title); + } + + @Inject(method = "rebuildGUIOptions", at = @At("RETURN")) + private void focusFirstButton(CallbackInfo ci) { + this.setInitialFocus(controls.get(0)); + } + + @Override + public ScreenProcessor screenProcessor() { + return controlify$screenProcessor; + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/sodium/TickBoxControlElementMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/TickBoxControlElementMixin.java new file mode 100644 index 0000000..51649bb --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/sodium/TickBoxControlElementMixin.java @@ -0,0 +1,25 @@ +package dev.isxander.controlify.mixins.compat.sodium; + +import dev.isxander.controlify.compatibility.sodium.TickBoxControlProcessor; +import dev.isxander.controlify.screenop.ComponentProcessor; +import dev.isxander.controlify.screenop.ComponentProcessorProvider; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Unique; + +@Pseudo +@Mixin(targets = "me.jellysquid.mods.sodium.client.gui.options.control.TickBoxControl$TickBoxControlElement") +public abstract class TickBoxControlElementMixin extends ControlElementMixin implements ComponentProcessorProvider { + @Unique private final ComponentProcessor controlify$componentProcessor + = new TickBoxControlProcessor(this::toggle); + + @Override + public ComponentProcessor componentProcessor() { + return controlify$componentProcessor; + } + + private void toggle() { + this.option.setValue(!this.option.getValue()); + this.playClickSound(); + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/screenop/yacl/CyclingControllerElementMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/yacl/CyclingControllerElementMixin.java similarity index 81% rename from src/main/java/dev/isxander/controlify/mixins/feature/screenop/yacl/CyclingControllerElementMixin.java rename to src/main/java/dev/isxander/controlify/mixins/compat/yacl/CyclingControllerElementMixin.java index a180078..9290811 100644 --- a/src/main/java/dev/isxander/controlify/mixins/feature/screenop/yacl/CyclingControllerElementMixin.java +++ b/src/main/java/dev/isxander/controlify/mixins/compat/yacl/CyclingControllerElementMixin.java @@ -1,8 +1,8 @@ -package dev.isxander.controlify.mixins.feature.screenop.yacl; +package dev.isxander.controlify.mixins.compat.yacl; import dev.isxander.controlify.screenop.ComponentProcessor; import dev.isxander.controlify.screenop.ComponentProcessorProvider; -import dev.isxander.controlify.screenop.compat.yacl.CyclingControllerElementComponentProcessor; +import dev.isxander.controlify.compatibility.yacl.CyclingControllerElementComponentProcessor; import dev.isxander.yacl.gui.controllers.cycling.CyclingControllerElement; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/screenop/yacl/SliderControllerElementMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/yacl/SliderControllerElementMixin.java similarity index 81% rename from src/main/java/dev/isxander/controlify/mixins/feature/screenop/yacl/SliderControllerElementMixin.java rename to src/main/java/dev/isxander/controlify/mixins/compat/yacl/SliderControllerElementMixin.java index b09b90c..19c06fc 100644 --- a/src/main/java/dev/isxander/controlify/mixins/feature/screenop/yacl/SliderControllerElementMixin.java +++ b/src/main/java/dev/isxander/controlify/mixins/compat/yacl/SliderControllerElementMixin.java @@ -1,8 +1,8 @@ -package dev.isxander.controlify.mixins.feature.screenop.yacl; +package dev.isxander.controlify.mixins.compat.yacl; import dev.isxander.controlify.screenop.ComponentProcessor; import dev.isxander.controlify.screenop.ComponentProcessorProvider; -import dev.isxander.controlify.screenop.compat.yacl.SliderControllerElementComponentProcessor; +import dev.isxander.controlify.compatibility.yacl.SliderControllerElementComponentProcessor; import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/screenop/yacl/YACLScreenMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/yacl/YACLScreenMixin.java similarity index 80% rename from src/main/java/dev/isxander/controlify/mixins/feature/screenop/yacl/YACLScreenMixin.java rename to src/main/java/dev/isxander/controlify/mixins/compat/yacl/YACLScreenMixin.java index 9a9465d..ffbf101 100644 --- a/src/main/java/dev/isxander/controlify/mixins/feature/screenop/yacl/YACLScreenMixin.java +++ b/src/main/java/dev/isxander/controlify/mixins/compat/yacl/YACLScreenMixin.java @@ -1,8 +1,8 @@ -package dev.isxander.controlify.mixins.feature.screenop.yacl; +package dev.isxander.controlify.mixins.compat.yacl; import dev.isxander.controlify.screenop.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessorProvider; -import dev.isxander.controlify.screenop.compat.yacl.YACLScreenProcessor; +import dev.isxander.controlify.compatibility.yacl.YACLScreenProcessor; import dev.isxander.yacl.gui.YACLScreen; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; diff --git a/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/SliderComponentProcessor.java b/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/SliderComponentProcessor.java index 73fd576..5c2cf64 100644 --- a/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/SliderComponentProcessor.java +++ b/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/SliderComponentProcessor.java @@ -63,7 +63,6 @@ public class SliderComponentProcessor implements ComponentProcessor { @Override public void onFocusGained(ScreenProcessor screen, Controller controller) { - System.out.println("navigated!"); this.canChangeValueSetter.accept(false); } } diff --git a/src/main/resources/assets/controlify/lang/en_us.json b/src/main/resources/assets/controlify/lang/en_us.json index 0338c73..57af014 100644 --- a/src/main/resources/assets/controlify/lang/en_us.json +++ b/src/main/resources/assets/controlify/lang/en_us.json @@ -115,8 +115,8 @@ "controlify.binding.controlify.gui_navi_up": "GUI Navi Up", "controlify.binding.controlify.gui_navi_left": "GUI Navi Left", "controlify.binding.controlify.gui_navi_right": "GUI Navi Right", - "controlify.binding.controlify.yacl_cycle_opt_forward": "YACL Cycle Option Forward", - "controlify.binding.controlify.yacl_cycle_opt_backward": "YACL Cycle Option Backward", + "controlify.binding.controlify.cycle_opt_forward": "Cycle Option Forward", + "controlify.binding.controlify.cycle_opt_backward": "Cycle Option Backward", "controlify.guide.inventory": "Open Inventory", "controlify.guide.swim_up": "Swim Up", diff --git a/src/main/resources/controlify.mixins.json b/src/main/resources/controlify.mixins.json index 3a9966b..f15bb09 100644 --- a/src/main/resources/controlify.mixins.json +++ b/src/main/resources/controlify.mixins.json @@ -4,9 +4,17 @@ "minVersion": "0.8", "compatibilityLevel": "JAVA_17", "mixins": [ + "compat.sodium.ControlElementMixin", + "compat.sodium.CycleControlElementMixin", + "compat.sodium.FlatButtonWidgetMixin", + "compat.sodium.SliderControlElementMixin", + "compat.sodium.TickBoxControlElementMixin", "core.GLXMixin" ], "client": [ + "compat.sodium.AbstractWidgetMixin", + "compat.sodium.SodiumOptionsGUIAccessor", + "compat.sodium.SodiumOptionsGUIMixin", "core.ClientPacketListenerMixin", "core.KeyboardHandlerMixin", "core.MinecraftMixin", @@ -32,9 +40,9 @@ "feature.screenop.vanilla.SelectWorldScreenMixin", "feature.screenop.vanilla.ServerSelectionListEntryMixin", "feature.screenop.vanilla.WorldSelectionListEntryMixin", - "feature.screenop.yacl.CyclingControllerElementMixin", - "feature.screenop.yacl.SliderControllerElementMixin", - "feature.screenop.yacl.YACLScreenMixin", + "compat.yacl.CyclingControllerElementMixin", + "compat.yacl.SliderControllerElementMixin", + "compat.yacl.YACLScreenMixin", "feature.settingsbutton.ControlsScreenMixin", "feature.virtualmouse.GameRendererMixin", "feature.virtualmouse.InputConstantsMixin",