From f557c1ab0540419b23b02cc9c7abd1bda188159e Mon Sep 17 00:00:00 2001 From: isXander Date: Sun, 14 May 2023 19:27:07 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Move=20button=20guide=20to?= =?UTF-8?q?=20screen=20processor=20+=20vmouse=20improvements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 + gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 +- .../dev/isxander/controlify/Controlify.java | 4 +- .../controlify/bindings/BindContexts.java | 5 +- .../bindings/ControllerBindings.java | 10 +- .../gui/guide/ContainerButtonGuide.java | 176 +++++++++++++++++- .../gui/guide/InGameButtonGuide.java | 4 +- .../controlify/gui/layout/AnchorPoint.java | 7 +- .../gui/layout/PositionedComponent.java | 25 ++- .../gui/layout/RowLayoutComponent.java | 3 +- .../AbstractContainerScreenAccessor.java | 22 +++ .../screen/AbstractContainerScreenMixin.java | 153 --------------- .../feature/screenop/GameRendererMixin.java | 27 +++ .../{vanilla => }/ScreenAccessor.java | 9 +- .../controlify/screenop/ScreenProcessor.java | 28 ++- .../screenop/ScreenProcessorProvider.java | 3 +- .../AbstractContainerScreenProcessor.java | 143 +++++++++++++- .../CreativeModeInventoryScreenProcessor.java | 6 +- .../virtualmouse/VirtualMouseBehaviour.java | 12 ++ .../virtualmouse/VirtualMouseHandler.java | 69 ++++--- .../assets/controlify/lang/en_us.json | 2 + src/main/resources/controlify.mixins.json | 5 +- .../controlify/test/ClientTestHelper.java | 2 - .../controlify/test/FakeController.java | 2 - 26 files changed, 496 insertions(+), 228 deletions(-) create mode 100644 src/main/java/dev/isxander/controlify/mixins/feature/guide/screen/AbstractContainerScreenAccessor.java delete mode 100644 src/main/java/dev/isxander/controlify/mixins/feature/guide/screen/AbstractContainerScreenMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/feature/screenop/GameRendererMixin.java rename src/main/java/dev/isxander/controlify/mixins/feature/screenop/{vanilla => }/ScreenAccessor.java (70%) create mode 100644 src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseBehaviour.java diff --git a/build.gradle.kts b/build.gradle.kts index dc96da8..1971e4e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -72,6 +72,7 @@ dependencies { "fabric-lifecycle-events-v1", "fabric-key-binding-api-v1", "fabric-registry-sync-v0", + "fabric-screen-api-v1", ).forEach { modImplementation(fabricApi.module(it, libs.versions.fabric.api.get())) } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..ccebba7710deaf9f98673a68957ea02138b60d0a 100644 GIT binary patch delta 5094 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 delta 5107 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 I6Xdi10eY*&F8}}l diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 761b8f0..37aef8d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68..79a61d4 100755 --- a/gradlew +++ b/gradlew @@ -144,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac diff --git a/src/main/java/dev/isxander/controlify/Controlify.java b/src/main/java/dev/isxander/controlify/Controlify.java index a5d71a0..efe5f1c 100644 --- a/src/main/java/dev/isxander/controlify/Controlify.java +++ b/src/main/java/dev/isxander/controlify/Controlify.java @@ -9,6 +9,7 @@ import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.ControllerState; import dev.isxander.controlify.controller.sdl2.SDL2NativesManager; import dev.isxander.controlify.debug.DebugProperties; +import dev.isxander.controlify.gui.guide.ContainerButtonGuide; import dev.isxander.controlify.gui.screen.ControllerDeadzoneCalibrationScreen; import dev.isxander.controlify.gui.screen.SDLOnboardingScreen; import dev.isxander.controlify.screenop.ScreenProcessorProvider; @@ -149,7 +150,7 @@ public class Controlify implements ControlifyApi { LOGGER.info("No controllers found."); } - if (getCurrentController().isEmpty() && config().isFirstLaunch()) { + if (getCurrentController().isEmpty()) { this.setCurrentController(ControllerManager.getConnectedControllers().stream().findFirst().orElse(null)); } else { // setCurrentController saves config @@ -183,6 +184,7 @@ public class Controlify implements ControlifyApi { this.inGameInputHandler = null; this.virtualMouseHandler = new VirtualMouseHandler(); + //ContainerButtonGuide.setup(); controllerHIDService = new ControllerHIDService(); controllerHIDService.start(); diff --git a/src/main/java/dev/isxander/controlify/bindings/BindContexts.java b/src/main/java/dev/isxander/controlify/bindings/BindContexts.java index 7572f89..5386d23 100644 --- a/src/main/java/dev/isxander/controlify/bindings/BindContexts.java +++ b/src/main/java/dev/isxander/controlify/bindings/BindContexts.java @@ -8,9 +8,10 @@ public final class BindContexts { public static final BindContext INGAME = ctx("ingame"), GUI = ctx("gui"), - GUI_VMOUSE = ctx("gui_vmouse"), + GUI_VMOUSE_CURSOR_ONLY = ctx("gui_vmouse_cursor"), + GUI_VMOUSE = ctx("gui_vmouse", GUI_VMOUSE_CURSOR_ONLY), CONTROLIFY_CONFIG = ctx("controlify_config", GUI), - INVENTORY = ctx("inventory", GUI_VMOUSE); + INVENTORY = ctx("inventory", GUI_VMOUSE_CURSOR_ONLY); private static BindContext ctx(String path, BindContext... parents) { return new BindContext(Controlify.id(path), Set.of(parents)); diff --git a/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java b/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java index b221cbe..7596fbd 100644 --- a/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java +++ b/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java @@ -275,25 +275,25 @@ public class ControllerBindings { .identifier("controlify", "vmouse_move_up") .defaultBind(GamepadBinds.LEFT_STICK_FORWARD) .category(VMOUSE_CATEGORY) - .context(BindContexts.GUI_VMOUSE) + .context(BindContexts.GUI_VMOUSE_CURSOR_ONLY) .build()); register(VMOUSE_MOVE_DOWN = ControllerBindingBuilder.create(controller) .identifier("controlify", "vmouse_move_down") .defaultBind(GamepadBinds.LEFT_STICK_BACKWARD) .category(VMOUSE_CATEGORY) - .context(BindContexts.GUI_VMOUSE) + .context(BindContexts.GUI_VMOUSE_CURSOR_ONLY) .build()); register(VMOUSE_MOVE_LEFT = ControllerBindingBuilder.create(controller) .identifier("controlify", "vmouse_move_left") .defaultBind(GamepadBinds.LEFT_STICK_LEFT) .category(VMOUSE_CATEGORY) - .context(BindContexts.GUI_VMOUSE) + .context(BindContexts.GUI_VMOUSE_CURSOR_ONLY) .build()); register(VMOUSE_MOVE_RIGHT = ControllerBindingBuilder.create(controller) .identifier("controlify", "vmouse_move_right") .defaultBind(GamepadBinds.LEFT_STICK_RIGHT) .category(VMOUSE_CATEGORY) - .context(BindContexts.GUI_VMOUSE) + .context(BindContexts.GUI_VMOUSE_CURSOR_ONLY) .build()); register(VMOUSE_LCLICK = ControllerBindingBuilder.create(controller) .identifier("controlify", "vmouse_lclick") @@ -335,7 +335,7 @@ public class ControllerBindings { .identifier("controlify", "vmouse_toggle") .defaultBind(GamepadBinds.BACK) .category(VMOUSE_CATEGORY) - .context(BindContexts.GUI_VMOUSE) + .context(BindContexts.GUI_VMOUSE, BindContexts.GUI) .build()); register(GUI_NAVI_UP = ControllerBindingBuilder.create(controller) .identifier("controlify", "gui_navi_up") diff --git a/src/main/java/dev/isxander/controlify/gui/guide/ContainerButtonGuide.java b/src/main/java/dev/isxander/controlify/gui/guide/ContainerButtonGuide.java index 1b27475..35ba69a 100644 --- a/src/main/java/dev/isxander/controlify/gui/guide/ContainerButtonGuide.java +++ b/src/main/java/dev/isxander/controlify/gui/guide/ContainerButtonGuide.java @@ -1,4 +1,178 @@ package dev.isxander.controlify.gui.guide; -public class ContainerButtonGuide { +import com.mojang.blaze3d.vertex.PoseStack; +import dev.isxander.controlify.InputMode; +import dev.isxander.controlify.api.ControlifyApi; +import dev.isxander.controlify.api.event.ControlifyEvents; +import dev.isxander.controlify.bindings.ControllerBindings; +import dev.isxander.controlify.compatibility.ControlifyCompat; +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.gui.layout.AnchorPoint; +import dev.isxander.controlify.gui.layout.ColumnLayoutComponent; +import dev.isxander.controlify.gui.layout.PositionedComponent; +import dev.isxander.controlify.gui.layout.RowLayoutComponent; +import dev.isxander.controlify.mixins.feature.guide.screen.AbstractContainerScreenAccessor; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; + +import java.util.Optional; + +public final class ContainerButtonGuide { + private static PositionedComponent>>> leftLayout; + private static PositionedComponent>>> rightLayout; + + public static void setup() { + ScreenEvents.BEFORE_INIT.register((minecraft, screen, sw, sh) -> { + removeLayout(); + + if (isScreenCompatible(screen)) { + setupLayout(); + + ScreenEvents.afterRender(screen).register((s, stack, mouseX, mouseY, tickDelta) -> { + // Fabric API provides the wrong matrixstack (which is translated -2000), behind + // the ortho near plane, so we need to translate it back to the front. + // https://github.com/FabricMC/fabric/pull/3061 + stack.pushPose(); + stack.translate(0, 0, 2000); + + renderGuide((AbstractContainerScreen) s, stack, tickDelta, mouseX, mouseY, sw, sh); + + stack.popPose(); + }); + } + }); + + ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> { + if (isScreenCompatible(Minecraft.getInstance().screen)) { + if (mode == InputMode.CONTROLLER) { + setupLayout(); + } else { + removeLayout(); + } + } + }); + } + + private static void setupLayout() { + ControllerBindings bindings = ControlifyApi.get().getCurrentController() + .map(Controller::bindings) + .orElseThrow(); + + leftLayout = new PositionedComponent<>( + ColumnLayoutComponent.>>builder() + .spacing(2) + .colPadding(2, 2) + .elementPosition(ColumnLayoutComponent.ElementPosition.LEFT) + .element(RowLayoutComponent.>builder() + .spacing(5) + .rowPadding(0) + .elementPosition(RowLayoutComponent.ElementPosition.MIDDLE) + .element(new GuideActionRenderer<>( + new GuideAction<>(bindings.VMOUSE_LCLICK, ctx -> { + if (!ctx.holdingItem().isEmpty()) + if (ctx.hoveredSlot() != null && ctx.hoveredSlot().hasItem()) + if (ctx.hoveredSlot().mayPlace(ctx.holdingItem())) + if (ctx.holdingItem().getCount() > 1) + return Optional.of(Component.translatable("controlify.guide.container.place_all")); + else + return Optional.of(Component.translatable("controlify.guide.container.place_one")); + else + return Optional.of(Component.translatable("controlify.guide.container.swap")); + else if (ctx.cursorOutsideContainer()) + return Optional.of(Component.translatable("controlify.guide.container.drop")); + if (ctx.hoveredSlot() != null && ctx.hoveredSlot().hasItem()) + return Optional.of(Component.translatable("controlify.guide.container.take")); + return Optional.empty(); + }), + false, false + )) + .element(new GuideActionRenderer<>( + new GuideAction<>(bindings.GUI_BACK, ctx -> { + return Optional.of(Component.translatable("controlify.guide.container.exit")); + }), + false, false + )) + .build()) + .build(), + AnchorPoint.BOTTOM_LEFT, + 0, 0, + AnchorPoint.BOTTOM_LEFT + ); + + rightLayout = new PositionedComponent<>( + ColumnLayoutComponent.>>builder() + .spacing(2) + .elementPosition(ColumnLayoutComponent.ElementPosition.RIGHT) + .colPadding(2, 2) + .element(RowLayoutComponent.>builder() + .spacing(5) + .rowPadding(0) + .elementPosition(RowLayoutComponent.ElementPosition.MIDDLE) + .element(new GuideActionRenderer<>( + new GuideAction<>(bindings.VMOUSE_RCLICK, ctx -> { + if (ctx.hoveredSlot() != null && ctx.hoveredSlot().getItem().getCount() > 1 && ctx.holdingItem().isEmpty()) + return Optional.of(Component.translatable("controlify.guide.container.take_half")); + if (ctx.hoveredSlot() != null && !ctx.holdingItem().isEmpty() && ctx.hoveredSlot().mayPlace(ctx.holdingItem())) + return Optional.of(Component.translatable("controlify.guide.container.take_one")); + return Optional.empty(); + }), + true, false + )) + .element(new GuideActionRenderer<>( + new GuideAction<>(bindings.VMOUSE_SHIFT_CLICK, ctx -> { + return Optional.of(Component.translatable("controlify.guide.container.quick_move")); + }), + true, false + )) + .build()) + .build(), + AnchorPoint.BOTTOM_RIGHT, + 0, 0, + AnchorPoint.BOTTOM_RIGHT + ); + } + + private static void removeLayout() { + leftLayout = null; + rightLayout = null; + } + + private static void renderGuide(AbstractContainerScreen screen, PoseStack stack, float tickDelta, int mouseX, int mouseY, int screenWidth, int screenHeight) { + if (leftLayout == null || rightLayout == null) + return; + + if (!ControlifyApi.get().getCurrentController().map(controller -> controller.config().showScreenGuide).orElse(false)) { + return; + } + + var accessor = (AbstractContainerScreenAccessor) screen; + + ContainerGuideCtx ctx = new ContainerGuideCtx(accessor.getHoveredSlot(), screen.getMenu().getCarried(), accessor.invokeHasClickedOutside(mouseX, mouseY, accessor.getLeftPos(), accessor.getTopPos(), 0)); + + for (var row : leftLayout.getComponent().getChildComponents()) { + for (var element : row.getChildComponents()) { + element.updateName(ctx); + } + } + for (var row : rightLayout.getComponent().getChildComponents()) { + for (var element : row.getChildComponents()) { + element.updateName(ctx); + } + } + + leftLayout.updatePosition(); + rightLayout.updatePosition(); + + ControlifyCompat.ifBeginHudBatching(); + leftLayout.renderComponent(stack, tickDelta); + rightLayout.renderComponent(stack, tickDelta); + ControlifyCompat.ifEndHudBatching(); + } + + private static boolean isScreenCompatible(Screen screen) { + return screen instanceof AbstractContainerScreen; + } } diff --git a/src/main/java/dev/isxander/controlify/gui/guide/InGameButtonGuide.java b/src/main/java/dev/isxander/controlify/gui/guide/InGameButtonGuide.java index d478666..3d9206a 100644 --- a/src/main/java/dev/isxander/controlify/gui/guide/InGameButtonGuide.java +++ b/src/main/java/dev/isxander/controlify/gui/guide/InGameButtonGuide.java @@ -75,8 +75,8 @@ public class InGameButtonGuide implements IngameGuideRegistry { ControlifyCompat.ifBeginHudBatching(); - leftLayout.render(poseStack, tickDelta); - rightLayout.render(poseStack, tickDelta); + leftLayout.renderComponent(poseStack, tickDelta); + rightLayout.renderComponent(poseStack, tickDelta); ControlifyCompat.ifEndHudBatching(); } diff --git a/src/main/java/dev/isxander/controlify/gui/layout/AnchorPoint.java b/src/main/java/dev/isxander/controlify/gui/layout/AnchorPoint.java index a1ef488..303bf37 100644 --- a/src/main/java/dev/isxander/controlify/gui/layout/AnchorPoint.java +++ b/src/main/java/dev/isxander/controlify/gui/layout/AnchorPoint.java @@ -1,9 +1,6 @@ package dev.isxander.controlify.gui.layout; -import org.joml.Vector2f; -import org.joml.Vector2fc; import org.joml.Vector2i; -import org.joml.Vector2ic; public enum AnchorPoint { TOP_LEFT(0, 0), @@ -23,7 +20,7 @@ public enum AnchorPoint { this.anchorY = anchorY; } - public Vector2i getAnchorPosition(Vector2ic windowSize) { - return new Vector2i((int) (windowSize.x() * anchorX), (int) (windowSize.y() * anchorY)); + public Vector2i getAnchorPosition(int w, int h) { + return new Vector2i((int) (w * anchorX), (int) (h * anchorY)); } } diff --git a/src/main/java/dev/isxander/controlify/gui/layout/PositionedComponent.java b/src/main/java/dev/isxander/controlify/gui/layout/PositionedComponent.java index 10c0261..65e0719 100644 --- a/src/main/java/dev/isxander/controlify/gui/layout/PositionedComponent.java +++ b/src/main/java/dev/isxander/controlify/gui/layout/PositionedComponent.java @@ -1,12 +1,11 @@ package dev.isxander.controlify.gui.layout; -import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; -import org.joml.Vector2i; +import net.minecraft.client.gui.components.Renderable; import org.joml.Vector2ic; -public class PositionedComponent { +public class PositionedComponent implements Renderable { private final T component; private int x, y; @@ -21,19 +20,24 @@ public class PositionedComponent { this.offsetY = offsetY; this.windowAnchor = windowAnchor; this.origin = origin; - - updatePosition(); } public void updatePosition() { - Vector2ic windowPosition = windowAnchor.getAnchorPosition(windowSize()); - Vector2ic anchoredPosition = origin.getAnchorPosition(component.size()); + Vector2ic componentSize = component.size(); + + Vector2ic windowPosition = windowAnchor.getAnchorPosition(Minecraft.getInstance().getWindow().getGuiScaledWidth(), Minecraft.getInstance().getWindow().getGuiScaledHeight()); + Vector2ic anchoredPosition = origin.getAnchorPosition(componentSize.x(), componentSize.y()); this.x = windowPosition.x() + offsetX - anchoredPosition.x(); this.y = windowPosition.y() + offsetY - anchoredPosition.y(); } - public void render(PoseStack stack, float deltaTime) { + @Override + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { + this.renderComponent(matrices, delta); + } + + public void renderComponent(PoseStack stack, float deltaTime) { component.render(stack, x, y, deltaTime); } @@ -48,9 +52,4 @@ public class PositionedComponent { public T getComponent() { return component; } - - private Vector2i windowSize() { - Window window = Minecraft.getInstance().getWindow(); - return new Vector2i(window.getGuiScaledWidth(), window.getGuiScaledHeight()); - } } diff --git a/src/main/java/dev/isxander/controlify/gui/layout/RowLayoutComponent.java b/src/main/java/dev/isxander/controlify/gui/layout/RowLayoutComponent.java index b2275a8..cea5efa 100644 --- a/src/main/java/dev/isxander/controlify/gui/layout/RowLayoutComponent.java +++ b/src/main/java/dev/isxander/controlify/gui/layout/RowLayoutComponent.java @@ -111,7 +111,8 @@ public class RowLayoutComponent extends AbstractLayou return this; } - public Builder elements(T... elements) { + @SafeVarargs + public final Builder elements(T... elements) { this.elements.addAll(Arrays.asList(elements)); return this; } diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/guide/screen/AbstractContainerScreenAccessor.java b/src/main/java/dev/isxander/controlify/mixins/feature/guide/screen/AbstractContainerScreenAccessor.java new file mode 100644 index 0000000..634d12e --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/feature/guide/screen/AbstractContainerScreenAccessor.java @@ -0,0 +1,22 @@ +package dev.isxander.controlify.mixins.feature.guide.screen; + +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.world.inventory.Slot; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(AbstractContainerScreen.class) +public interface AbstractContainerScreenAccessor { + @Accessor + Slot getHoveredSlot(); + + @Invoker + boolean invokeHasClickedOutside(double mouseX, double mouseY, int left, int top, int button); + + @Accessor + int getLeftPos(); + + @Accessor + int getTopPos(); +} diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/guide/screen/AbstractContainerScreenMixin.java b/src/main/java/dev/isxander/controlify/mixins/feature/guide/screen/AbstractContainerScreenMixin.java deleted file mode 100644 index aad12f1..0000000 --- a/src/main/java/dev/isxander/controlify/mixins/feature/guide/screen/AbstractContainerScreenMixin.java +++ /dev/null @@ -1,153 +0,0 @@ -package dev.isxander.controlify.mixins.feature.guide.screen; - -import com.mojang.blaze3d.vertex.PoseStack; -import dev.isxander.controlify.InputMode; -import dev.isxander.controlify.api.ControlifyApi; -import dev.isxander.controlify.bindings.ControllerBindings; -import dev.isxander.controlify.controller.Controller; -import dev.isxander.controlify.gui.guide.ContainerGuideCtx; -import dev.isxander.controlify.gui.guide.GuideAction; -import dev.isxander.controlify.gui.guide.GuideActionRenderer; -import dev.isxander.controlify.gui.layout.AnchorPoint; -import dev.isxander.controlify.gui.layout.ColumnLayoutComponent; -import dev.isxander.controlify.gui.layout.PositionedComponent; -import dev.isxander.controlify.gui.layout.RowLayoutComponent; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.network.chat.Component; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -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; - -import java.util.Optional; - -// TODO: Move out of mixin -@Mixin(AbstractContainerScreen.class) -public abstract class AbstractContainerScreenMixin { - @Shadow @Nullable protected Slot hoveredSlot; - @Shadow @Final protected T menu; - @Shadow protected int leftPos; - @Shadow protected int topPos; - @Shadow protected abstract boolean hasClickedOutside(double mouseX, double mouseY, int left, int top, int button); - - @Unique private PositionedComponent>>> leftLayout; - @Unique private PositionedComponent>>> rightLayout; - - @Inject(method = "init", at = @At("RETURN")) - private void initButtonGuide(CallbackInfo ci) { - ControllerBindings bindings = ControlifyApi.get().getCurrentController() - .map(Controller::bindings) - .orElse(null); - - if (bindings == null) - return; - - leftLayout = new PositionedComponent<>( - ColumnLayoutComponent.>>builder() - .spacing(2) - .colPadding(2, 2) - .elementPosition(ColumnLayoutComponent.ElementPosition.LEFT) - .element(RowLayoutComponent.>builder() - .spacing(5) - .rowPadding(0) - .elementPosition(RowLayoutComponent.ElementPosition.MIDDLE) - .element(new GuideActionRenderer<>( - new GuideAction<>(bindings.VMOUSE_LCLICK, ctx -> { - if (!ctx.holdingItem().isEmpty()) - if (ctx.hoveredSlot() != null && ctx.hoveredSlot().hasItem()) - if (ctx.hoveredSlot().mayPlace(ctx.holdingItem())) - if (ctx.holdingItem().getCount() > 1) - return Optional.of(Component.translatable("controlify.guide.container.place_all")); - else - return Optional.of(Component.translatable("controlify.guide.container.place_one")); - else - return Optional.of(Component.translatable("controlify.guide.container.swap")); - else if (ctx.cursorOutsideContainer()) - return Optional.of(Component.translatable("controlify.guide.container.drop")); - if (ctx.hoveredSlot() != null && ctx.hoveredSlot().hasItem()) - return Optional.of(Component.translatable("controlify.guide.container.take")); - return Optional.empty(); - }), - false, false - )) - .elements(new GuideActionRenderer<>( - new GuideAction<>(bindings.GUI_BACK, ctx -> { - return Optional.of(Component.translatable("controlify.guide.container.exit")); - }), - false, false - )) - .build()) - .build(), - AnchorPoint.BOTTOM_LEFT, - 0, 0, - AnchorPoint.BOTTOM_LEFT - ); - - rightLayout = new PositionedComponent<>( - ColumnLayoutComponent.>>builder() - .spacing(2) - .elementPosition(ColumnLayoutComponent.ElementPosition.RIGHT) - .colPadding(2, 2) - .element(RowLayoutComponent.>builder() - .spacing(5) - .rowPadding(0) - .elementPosition(RowLayoutComponent.ElementPosition.MIDDLE) - .element(new GuideActionRenderer<>( - new GuideAction<>(bindings.VMOUSE_RCLICK, ctx -> { - if (ctx.hoveredSlot() != null && ctx.hoveredSlot().getItem().getCount() > 1 && ctx.holdingItem().isEmpty()) - return Optional.of(Component.translatable("controlify.guide.container.take_half")); - if (ctx.hoveredSlot() != null && !ctx.holdingItem().isEmpty() && ctx.hoveredSlot().mayPlace(ctx.holdingItem())) - return Optional.of(Component.translatable("controlify.guide.container.take_one")); - return Optional.empty(); - }), - true, false - )) - .element(new GuideActionRenderer<>( - new GuideAction<>(bindings.VMOUSE_SHIFT_CLICK, ctx -> { - return Optional.of(Component.translatable("controlify.guide.container.quick_move")); - }), - true, false - )) - .build()) - .build(), - AnchorPoint.BOTTOM_RIGHT, - 0, 0, - AnchorPoint.BOTTOM_RIGHT - ); - } - - @Inject(method = "render", at = @At("RETURN")) - private void renderButtonGuide(PoseStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) { - if (!ControlifyApi.get().getCurrentController().map(controller -> controller.config().showScreenGuide).orElse(false) - || ControlifyApi.get().currentInputMode() != InputMode.CONTROLLER - ) { - return; - } - - ContainerGuideCtx ctx = new ContainerGuideCtx(hoveredSlot, menu.getCarried(), hasClickedOutside(mouseX, mouseY, this.leftPos, this.topPos, 0)); - - for (var row : leftLayout.getComponent().getChildComponents()) { - for (var element : row.getChildComponents()) { - element.updateName(ctx); - } - } - for (var row : rightLayout.getComponent().getChildComponents()) { - for (var element : row.getChildComponents()) { - element.updateName(ctx); - } - } - - leftLayout.updatePosition(); - rightLayout.updatePosition(); - - leftLayout.render(matrices, delta); - rightLayout.render(matrices, delta); - } -} diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/screenop/GameRendererMixin.java b/src/main/java/dev/isxander/controlify/mixins/feature/screenop/GameRendererMixin.java new file mode 100644 index 0000000..f3336f5 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/feature/screenop/GameRendererMixin.java @@ -0,0 +1,27 @@ +package dev.isxander.controlify.mixins.feature.screenop; + +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.blaze3d.vertex.PoseStack; +import dev.isxander.controlify.api.ControlifyApi; +import dev.isxander.controlify.screenop.ScreenProcessorProvider; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +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(GameRenderer.class) +public class GameRendererMixin { + @Shadow @Final Minecraft minecraft; + + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;renderWithTooltip(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V", shift = At.Shift.AFTER)) + private void onPostRenderScreen(float tickDelta, long startTime, boolean tick, CallbackInfo ci, @Local(ordinal = 1) PoseStack poseStack) { + ControlifyApi.get().getCurrentController().ifPresent(controller -> { + if (minecraft.screen == null) return; + ScreenProcessorProvider.provide(minecraft.screen).render(controller, poseStack, tickDelta); + }); + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/screenop/vanilla/ScreenAccessor.java b/src/main/java/dev/isxander/controlify/mixins/feature/screenop/ScreenAccessor.java similarity index 70% rename from src/main/java/dev/isxander/controlify/mixins/feature/screenop/vanilla/ScreenAccessor.java rename to src/main/java/dev/isxander/controlify/mixins/feature/screenop/ScreenAccessor.java index 4ab0e38..699198e 100644 --- a/src/main/java/dev/isxander/controlify/mixins/feature/screenop/vanilla/ScreenAccessor.java +++ b/src/main/java/dev/isxander/controlify/mixins/feature/screenop/ScreenAccessor.java @@ -1,12 +1,16 @@ -package dev.isxander.controlify.mixins.feature.screenop.vanilla; +package dev.isxander.controlify.mixins.feature.screenop; import net.minecraft.client.gui.ComponentPath; +import net.minecraft.client.gui.components.Renderable; import net.minecraft.client.gui.navigation.FocusNavigationEvent; import net.minecraft.client.gui.navigation.ScreenDirection; import net.minecraft.client.gui.screens.Screen; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; +import java.util.List; + @Mixin(Screen.class) public interface ScreenAccessor { @Invoker @@ -17,4 +21,7 @@ public interface ScreenAccessor { @Invoker void invokeClearFocus(); + + @Accessor + List getRenderables(); } diff --git a/src/main/java/dev/isxander/controlify/screenop/ScreenProcessor.java b/src/main/java/dev/isxander/controlify/screenop/ScreenProcessor.java index 477ee44..efa8905 100644 --- a/src/main/java/dev/isxander/controlify/screenop/ScreenProcessor.java +++ b/src/main/java/dev/isxander/controlify/screenop/ScreenProcessor.java @@ -1,13 +1,16 @@ package dev.isxander.controlify.screenop; +import com.mojang.blaze3d.vertex.PoseStack; import dev.isxander.controlify.Controlify; import dev.isxander.controlify.InputMode; import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.api.event.ControlifyEvents; -import dev.isxander.controlify.mixins.feature.screenop.vanilla.ScreenAccessor; +import dev.isxander.controlify.mixins.feature.screenop.ScreenAccessor; import dev.isxander.controlify.mixins.feature.screenop.vanilla.TabNavigationBarAccessor; import dev.isxander.controlify.sound.ControlifySounds; import dev.isxander.controlify.utils.NavigationHelper; +import dev.isxander.controlify.virtualmouse.VirtualMouseBehaviour; +import dev.isxander.controlify.virtualmouse.VirtualMouseHandler; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ComponentPath; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -25,7 +28,7 @@ import java.util.*; public class ScreenProcessor { public final T screen; protected final NavigationHelper navigationHelper = new NavigationHelper(10, 3); - protected final Minecraft minecraft = Minecraft.getInstance(); + protected static final Minecraft minecraft = Minecraft.getInstance(); public ScreenProcessor(T screen) { this.screen = screen; @@ -40,12 +43,17 @@ public class ScreenProcessor { if (!handleComponentButtonOverride(controller)) handleButtons(controller); } else { - handleScreenVMouse(controller); + handleScreenVMouse(controller, Controlify.instance().virtualMouseHandler()); } handleTabNavigation(controller); } + public void render(Controller controller, PoseStack poseStack, float tickDelta) { + var vmouse = Controlify.instance().virtualMouseHandler(); + this.render(controller, poseStack, tickDelta, vmouse.isVirtualMouseEnabled() ? Optional.of(vmouse) : Optional.empty()); + } + public void onInputModeChanged(InputMode mode) { switch (mode) { case KEYBOARD_MOUSE -> ((ScreenAccessor) screen).invokeClearFocus(); @@ -115,12 +123,12 @@ public class ScreenProcessor { screen.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0); } if (controller.bindings().GUI_BACK.justPressed()) { - this.playClackSound(); + playClackSound(); screen.onClose(); } } - protected void handleScreenVMouse(Controller controller) { + protected void handleScreenVMouse(Controller controller, VirtualMouseHandler vmouse) { } @@ -180,6 +188,10 @@ public class ScreenProcessor { } } + protected void render(Controller controller, PoseStack poseStack, float tickDelta, Optional vmouse) { + + } + protected void setInitialFocus() { if (screen.getFocused() == null && Controlify.instance().currentInputMode() == InputMode.CONTROLLER && !Controlify.instance().virtualMouseHandler().isVirtualMouseEnabled()) { var accessor = (ScreenAccessor) screen; @@ -191,8 +203,8 @@ public class ScreenProcessor { } } - public boolean forceVirtualMouse() { - return false; + public VirtualMouseBehaviour virtualMouseBehaviour() { + return VirtualMouseBehaviour.DEFAULT; } protected Queue getFocusTree() { @@ -211,7 +223,7 @@ public class ScreenProcessor { return tree; } - protected void playClackSound() { + public static void playClackSound() { minecraft.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); } } diff --git a/src/main/java/dev/isxander/controlify/screenop/ScreenProcessorProvider.java b/src/main/java/dev/isxander/controlify/screenop/ScreenProcessorProvider.java index 981e4eb..0db164b 100644 --- a/src/main/java/dev/isxander/controlify/screenop/ScreenProcessorProvider.java +++ b/src/main/java/dev/isxander/controlify/screenop/ScreenProcessorProvider.java @@ -1,13 +1,14 @@ package dev.isxander.controlify.screenop; import net.minecraft.client.gui.screens.Screen; +import org.jetbrains.annotations.NotNull; import java.util.Optional; public interface ScreenProcessorProvider { ScreenProcessor screenProcessor(); - static ScreenProcessor provide(Screen screen) { + static ScreenProcessor provide(@NotNull Screen screen) { Optional> optional = REGISTRY.get(screen); if (optional.isPresent()) return optional.get(); diff --git a/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/AbstractContainerScreenProcessor.java b/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/AbstractContainerScreenProcessor.java index e3cc99d..8f204d5 100644 --- a/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/AbstractContainerScreenProcessor.java +++ b/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/AbstractContainerScreenProcessor.java @@ -1,14 +1,34 @@ package dev.isxander.controlify.screenop.compat.vanilla; +import dev.isxander.controlify.InputMode; +import dev.isxander.controlify.api.ControlifyApi; +import dev.isxander.controlify.bindings.ControllerBindings; import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.gui.guide.ContainerGuideCtx; +import dev.isxander.controlify.gui.guide.GuideAction; +import dev.isxander.controlify.gui.guide.GuideActionRenderer; +import dev.isxander.controlify.gui.layout.AnchorPoint; +import dev.isxander.controlify.gui.layout.PositionedComponent; +import dev.isxander.controlify.gui.layout.RowLayoutComponent; +import dev.isxander.controlify.mixins.feature.guide.screen.AbstractContainerScreenAccessor; +import dev.isxander.controlify.mixins.feature.screenop.ScreenAccessor; import dev.isxander.controlify.screenop.ScreenProcessor; +import dev.isxander.controlify.virtualmouse.VirtualMouseBehaviour; +import dev.isxander.controlify.virtualmouse.VirtualMouseHandler; +import net.minecraft.client.gui.components.Renderable; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; import net.minecraft.world.inventory.ClickType; import net.minecraft.world.inventory.Slot; +import java.util.List; +import java.util.Optional; import java.util.function.Supplier; public class AbstractContainerScreenProcessor> extends ScreenProcessor { + private PositionedComponent>> leftLayout; + private PositionedComponent>> rightLayout; + private final Supplier hoveredSlot; private final ClickSlotFunction clickSlotFunction; @@ -19,13 +39,134 @@ public class AbstractContainerScreenProcessor controller) { + protected void handleScreenVMouse(Controller controller, VirtualMouseHandler vmouse) { if (controller.bindings().DROP.justPressed()) { Slot slot = hoveredSlot.get(); if (slot != null && slot.hasItem()) { clickSlotFunction.clickSlot(slot, slot.index, 0, ClickType.THROW); } } + + if (leftLayout != null && rightLayout != null) { + var accessor = (AbstractContainerScreenAccessor) screen; + + ContainerGuideCtx ctx = new ContainerGuideCtx(hoveredSlot.get(), screen.getMenu().getCarried(), accessor.invokeHasClickedOutside(vmouse.getCurrentX(1f), vmouse.getCurrentY(1f), accessor.getLeftPos(), accessor.getTopPos(), 0)); + + for (var element : leftLayout.getComponent().getChildComponents()) { + element.updateName(ctx); + } + for (var element : rightLayout.getComponent().getChildComponents()) { + element.updateName(ctx); + } + + leftLayout.updatePosition(); + rightLayout.updatePosition(); + } + } + + @Override + public void onWidgetRebuild() { + ControllerBindings bindings = ControlifyApi.get().getCurrentController() + .map(Controller::bindings) + .orElse(null); + + if (bindings == null) { + return; + } + + leftLayout = new PositionedComponent<>( + RowLayoutComponent.>builder() + .spacing(5) + .rowPadding(0) + .elementPosition(RowLayoutComponent.ElementPosition.MIDDLE) + .element(new GuideActionRenderer<>( + new GuideAction<>(bindings.VMOUSE_LCLICK, ctx -> { + if (!ctx.holdingItem().isEmpty()) + if (ctx.hoveredSlot() != null && ctx.hoveredSlot().hasItem()) + if (ctx.hoveredSlot().mayPlace(ctx.holdingItem())) + if (ctx.holdingItem().getCount() > 1) + return Optional.of(Component.translatable("controlify.guide.container.place_all")); + else + return Optional.of(Component.translatable("controlify.guide.container.place_one")); + else + return Optional.of(Component.translatable("controlify.guide.container.swap")); + else if (ctx.cursorOutsideContainer()) + return Optional.of(Component.translatable("controlify.guide.container.drop")); + if (ctx.hoveredSlot() != null && ctx.hoveredSlot().hasItem()) + return Optional.of(Component.translatable("controlify.guide.container.take")); + return Optional.empty(); + }), + false, false + )) + .element(new GuideActionRenderer<>( + new GuideAction<>(bindings.GUI_BACK, ctx -> { + return Optional.of(Component.translatable("controlify.guide.container.exit")); + }), + false, false + )) + .build(), + AnchorPoint.BOTTOM_LEFT, + 0, 0, + AnchorPoint.BOTTOM_LEFT + ); + + rightLayout = new PositionedComponent<>( + RowLayoutComponent.>builder() + .spacing(5) + .rowPadding(0) + .elementPosition(RowLayoutComponent.ElementPosition.MIDDLE) + .element(new GuideActionRenderer<>( + new GuideAction<>(bindings.VMOUSE_RCLICK, ctx -> { + if (ctx.hoveredSlot() != null && ctx.hoveredSlot().getItem().getCount() > 1 && ctx.holdingItem().isEmpty()) + return Optional.of(Component.translatable("controlify.guide.container.take_half")); + if (ctx.hoveredSlot() != null && !ctx.holdingItem().isEmpty() && ctx.hoveredSlot().mayPlace(ctx.holdingItem())) + return Optional.of(Component.translatable("controlify.guide.container.take_one")); + return Optional.empty(); + }), + true, false + )) + .element(new GuideActionRenderer<>( + new GuideAction<>(bindings.VMOUSE_SHIFT_CLICK, ctx -> { + return Optional.of(Component.translatable("controlify.guide.container.quick_move")); + }), + true, false + )) + .build(), + AnchorPoint.BOTTOM_RIGHT, + 0, 0, + AnchorPoint.BOTTOM_RIGHT + ); + + if (ControlifyApi.get().currentInputMode() == InputMode.CONTROLLER) { + setRenderGuide(true); + } + } + + @Override + public void onInputModeChanged(InputMode mode) { + setRenderGuide(mode == InputMode.CONTROLLER); + } + + private void setRenderGuide(boolean render) { + List renderables = ((ScreenAccessor) screen).getRenderables(); + + if (leftLayout == null || rightLayout == null) + return; + + if (render) { + if (!renderables.contains(leftLayout)) + renderables.add(leftLayout); + if (!renderables.contains(rightLayout)) + renderables.add(rightLayout); + } else { + renderables.remove(leftLayout); + renderables.remove(rightLayout); + } + } + + @Override + public VirtualMouseBehaviour virtualMouseBehaviour() { + return VirtualMouseBehaviour.CURSOR_ONLY; } @FunctionalInterface diff --git a/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/CreativeModeInventoryScreenProcessor.java b/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/CreativeModeInventoryScreenProcessor.java index 0f38c9b..e958768 100644 --- a/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/CreativeModeInventoryScreenProcessor.java +++ b/src/main/java/dev/isxander/controlify/screenop/compat/vanilla/CreativeModeInventoryScreenProcessor.java @@ -1,8 +1,8 @@ package dev.isxander.controlify.screenop.compat.vanilla; import dev.isxander.controlify.controller.Controller; -import dev.isxander.controlify.screenop.ScreenProcessor; import dev.isxander.controlify.mixins.feature.screenop.vanilla.CreativeModeInventoryScreenAccessor; +import dev.isxander.controlify.virtualmouse.VirtualMouseHandler; import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.CreativeModeTabs; @@ -15,7 +15,7 @@ public class CreativeModeInventoryScreenProcessor extends AbstractContainerScree } @Override - protected void handleScreenVMouse(Controller controller) { + protected void handleScreenVMouse(Controller controller, VirtualMouseHandler vmouse) { var accessor = (CreativeModeInventoryScreenAccessor) screen; if (controller.bindings().GUI_NEXT_TAB.justPressed()) { @@ -31,6 +31,6 @@ public class CreativeModeInventoryScreenProcessor extends AbstractContainerScree accessor.invokeSelectTab(tabs.get(newIndex)); } - super.handleScreenVMouse(controller); + super.handleScreenVMouse(controller, vmouse); } } diff --git a/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseBehaviour.java b/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseBehaviour.java new file mode 100644 index 0000000..47f84d6 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseBehaviour.java @@ -0,0 +1,12 @@ +package dev.isxander.controlify.virtualmouse; + +public enum VirtualMouseBehaviour { + DEFAULT, + ENABLED, + DISABLED, + CURSOR_ONLY; + + public boolean hasCursor() { + return this != DISABLED; + } +} diff --git a/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java b/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java index d6ee2a1..22a975b 100644 --- a/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java +++ b/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java @@ -9,13 +9,14 @@ import dev.isxander.controlify.api.vmousesnapping.ISnapBehaviour; import dev.isxander.controlify.api.vmousesnapping.SnapPoint; import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.debug.DebugProperties; +import dev.isxander.controlify.screenop.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessorProvider; import dev.isxander.controlify.api.event.ControlifyEvents; import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor; import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor; +import dev.isxander.controlify.utils.ToastUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiComponent; -import net.minecraft.client.gui.components.toasts.SystemToast; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; @@ -40,7 +41,6 @@ public class VirtualMouseHandler { private Set snapPoints; private SnapPoint lastSnappedPoint; - private boolean snapping; public VirtualMouseHandler() { this.minecraft = Minecraft.getInstance(); @@ -77,8 +77,6 @@ public class VirtualMouseHandler { if (impulseX == 0 && impulseY == 0) { if ((prevImpulseX != 0 || prevImpulseY != 0)) snapToClosestPoint(); - } else { - snapping = false; } var sensitivity = controller.config().virtualMouseSensitivity; @@ -91,6 +89,17 @@ public class VirtualMouseHandler { targetX = Mth.clamp(targetX, 0, minecraft.getWindow().getWidth()); targetY = Mth.clamp(targetY, 0, minecraft.getWindow().getHeight()); + if (controller.bindings().GUI_BACK.justPressed() && minecraft.screen != null) { + ScreenProcessor.playClackSound(); + minecraft.screen.onClose(); + } + + if (!ScreenProcessorProvider.provide(minecraft.screen).virtualMouseBehaviour().hasCursor()) { + handleCompatibilityBinds(controller); + } + } + + private void handleCompatibilityBinds(Controller controller) { scrollY += controller.bindings().VMOUSE_SCROLL_UP.state() - controller.bindings().VMOUSE_SCROLL_DOWN.state(); var mouseHandler = (MouseHandlerAccessor) minecraft.mouseHandler; @@ -113,10 +122,6 @@ public class VirtualMouseHandler { } else if (controller.bindings().VMOUSE_SHIFT_CLICK.justReleased()) { mouseHandler.invokeOnPress(minecraft.getWindow().getWindow(), GLFW.GLFW_MOUSE_BUTTON_LEFT, GLFW.GLFW_RELEASE, 0); } - - if (controller.bindings().GUI_BACK.justPressed() && minecraft.screen != null) { - minecraft.screen.onClose(); - } } public void updateMouse() { @@ -164,7 +169,6 @@ public class VirtualMouseHandler { if (closestSnapPoint != null) { lastSnappedPoint = closestSnapPoint; - snapping = false; targetX = currentX = closestSnapPoint.position().x() / scaleFactor.x(); targetY = currentY = closestSnapPoint.position().y() / scaleFactor.y(); @@ -271,15 +275,30 @@ public class VirtualMouseHandler { public boolean requiresVirtualMouse() { var isController = Controlify.instance().currentInputMode() == InputMode.CONTROLLER; var hasScreen = minecraft.screen != null; - var forceVirtualMouse = hasScreen && ScreenProcessorProvider.provide(minecraft.screen).forceVirtualMouse(); - var screenIsVMouseScreen = hasScreen && Controlify.instance().config().globalSettings().virtualMouseScreens.stream().anyMatch(s -> s.isAssignableFrom(minecraft.screen.getClass())); - return isController && hasScreen && (forceVirtualMouse || screenIsVMouseScreen); + if (isController && hasScreen) { + return switch (ScreenProcessorProvider.provide(minecraft.screen).virtualMouseBehaviour()) { + case DEFAULT -> Controlify.instance().config().globalSettings().virtualMouseScreens.stream().anyMatch(s -> s.isAssignableFrom(minecraft.screen.getClass())); + case ENABLED, CURSOR_ONLY -> true; + case DISABLED -> false; + }; + } + + return false; } public void toggleVirtualMouse() { if (minecraft.screen == null) return; + if (ScreenProcessorProvider.provide(minecraft.screen).virtualMouseBehaviour() != VirtualMouseBehaviour.DEFAULT) { + ToastUtils.sendToast( + Component.translatable("controlify.toast.vmouse_unavailable.title"), + Component.translatable("controlify.toast.vmouse_unavailable.description"), + false + ); + return; + } + var screens = Controlify.instance().config().globalSettings().virtualMouseScreens; var screenClass = minecraft.screen.getClass(); if (screens.contains(screenClass)) { @@ -287,22 +306,20 @@ public class VirtualMouseHandler { disableVirtualMouse(); Controlify.instance().hideMouse(true, false); - minecraft.getToasts().addToast(SystemToast.multiline( - minecraft, - SystemToast.SystemToastIds.PERIODIC_NOTIFICATION, + ToastUtils.sendToast( Component.translatable("controlify.toast.vmouse_disabled.title"), - Component.translatable("controlify.toast.vmouse_disabled.description") - )); + Component.translatable("controlify.toast.vmouse_disabled.description"), + false + ); } else { screens.add(screenClass); enableVirtualMouse(); - minecraft.getToasts().addToast(SystemToast.multiline( - minecraft, - SystemToast.SystemToastIds.PERIODIC_NOTIFICATION, + ToastUtils.sendToast( Component.translatable("controlify.toast.vmouse_enabled.title"), - Component.translatable("controlify.toast.vmouse_enabled.description") - )); + Component.translatable("controlify.toast.vmouse_enabled.description"), + false + ); } Controlify.instance().config().save(); @@ -311,4 +328,12 @@ public class VirtualMouseHandler { public boolean isVirtualMouseEnabled() { return virtualMouseEnabled; } + + public int getCurrentX(float deltaTime) { + return (int) Mth.lerp(deltaTime, currentX, targetX); + } + + public int getCurrentY(float deltaTime) { + return (int) Mth.lerp(deltaTime, currentY, targetY); + } } diff --git a/src/main/resources/assets/controlify/lang/en_us.json b/src/main/resources/assets/controlify/lang/en_us.json index 1f143e8..50358b1 100644 --- a/src/main/resources/assets/controlify/lang/en_us.json +++ b/src/main/resources/assets/controlify/lang/en_us.json @@ -116,6 +116,8 @@ "controlify.toast.vmouse_enabled.description": "Controlify virtual mouse is now enabled for this screen.", "controlify.toast.vmouse_disabled.title": "Virtual Mouse Disabled", "controlify.toast.vmouse_disabled.description": "Controlify virtual mouse is now disabled for this screen.", + "controlify.toast.vmouse_unavailable.title": "Virtual Mouse Unavailable", + "controlify.toast.vmouse_unavailable.description": "This screen is forcing a specific virtual mouse mode and you cannot change it.", "controlify.toast.ask_to_switch.title": "Switch Controller?", "controlify.toast.ask_to_switch.description": "A new controller named '%s' has just been connected. Press any button to switch to it.", "controlify.toast.default_controller_connected.title": "Controller Connected", diff --git a/src/main/resources/controlify.mixins.json b/src/main/resources/controlify.mixins.json index 381ec42..3a8638b 100644 --- a/src/main/resources/controlify.mixins.json +++ b/src/main/resources/controlify.mixins.json @@ -39,7 +39,7 @@ "feature.guide.ingame.ClientPacketListenerMixin", "feature.guide.ingame.GuiMixin", "feature.guide.screen.AbstractButtonMixin", - "feature.guide.screen.AbstractContainerScreenMixin", + "feature.guide.screen.AbstractContainerScreenAccessor", "feature.guide.screen.AbstractWidgetMixin", "feature.guide.screen.TabNavigationBarMixin", "feature.oofinput.GameRendererMixin", @@ -49,7 +49,9 @@ "feature.rumble.explosion.ClientPacketListenerMixin", "feature.rumble.itembreak.LocalPlayerMixin", "feature.rumble.useitem.LocalPlayerMixin", + "feature.screenop.GameRendererMixin", "feature.screenop.MinecraftMixin", + "feature.screenop.ScreenAccessor", "feature.screenop.ScreenMixin", "feature.screenop.vanilla.AbstractButtonMixin", "feature.screenop.vanilla.AbstractContainerEventHandlerMixin", @@ -64,7 +66,6 @@ "feature.screenop.vanilla.JoinMultiplayerScreenMixin", "feature.screenop.vanilla.LanguageSelectionListEntryMixin", "feature.screenop.vanilla.OptionsSubScreenAccessor", - "feature.screenop.vanilla.ScreenAccessor", "feature.screenop.vanilla.SelectWorldScreenAccessor", "feature.screenop.vanilla.SelectWorldScreenMixin", "feature.screenop.vanilla.ServerSelectionListEntryMixin", diff --git a/src/testmod/java/dev/isxander/controlify/test/ClientTestHelper.java b/src/testmod/java/dev/isxander/controlify/test/ClientTestHelper.java index e61acd1..8039f16 100644 --- a/src/testmod/java/dev/isxander/controlify/test/ClientTestHelper.java +++ b/src/testmod/java/dev/isxander/controlify/test/ClientTestHelper.java @@ -1,6 +1,5 @@ package dev.isxander.controlify.test; -import dev.isxander.controlify.controller.Controller; import net.minecraft.client.Minecraft; import net.minecraft.client.Screenshot; @@ -69,7 +68,6 @@ public class ClientTestHelper { public static FakeController createAndUseDummyController() { var controller = new FakeController(); - Controller.CONTROLLERS.put(controller.uid(), controller); controller.use(); return controller; } diff --git a/src/testmod/java/dev/isxander/controlify/test/FakeController.java b/src/testmod/java/dev/isxander/controlify/test/FakeController.java index 4941cd1..5af4102 100644 --- a/src/testmod/java/dev/isxander/controlify/test/FakeController.java +++ b/src/testmod/java/dev/isxander/controlify/test/FakeController.java @@ -4,7 +4,6 @@ import com.google.gson.Gson; import com.google.gson.JsonElement; import dev.isxander.controlify.Controlify; import dev.isxander.controlify.bindings.ControllerBindings; -import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.ControllerType; import dev.isxander.controlify.controller.hid.ControllerHIDService; import dev.isxander.controlify.controller.joystick.JoystickConfig; @@ -194,7 +193,6 @@ public class FakeController implements JoystickController { public void finish() { Controlify.instance().setCurrentController(null); - Controller.CONTROLLERS.remove(uid, this); } @Override