1
0
forked from Clones/Controlify

✏️ Move button guide to screen processor + vmouse improvements

This commit is contained in:
isXander
2023-05-14 19:27:07 +01:00
parent 45c20bb2dc
commit f557c1ab05
26 changed files with 496 additions and 228 deletions

View File

@ -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<ColumnLayoutComponent<RowLayoutComponent<GuideActionRenderer<ContainerGuideCtx>>>> leftLayout;
private static PositionedComponent<ColumnLayoutComponent<RowLayoutComponent<GuideActionRenderer<ContainerGuideCtx>>>> 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.<RowLayoutComponent<GuideActionRenderer<ContainerGuideCtx>>>builder()
.spacing(2)
.colPadding(2, 2)
.elementPosition(ColumnLayoutComponent.ElementPosition.LEFT)
.element(RowLayoutComponent.<GuideActionRenderer<ContainerGuideCtx>>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.<RowLayoutComponent<GuideActionRenderer<ContainerGuideCtx>>>builder()
.spacing(2)
.elementPosition(ColumnLayoutComponent.ElementPosition.RIGHT)
.colPadding(2, 2)
.element(RowLayoutComponent.<GuideActionRenderer<ContainerGuideCtx>>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<?>;
}
}

View File

@ -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();
}

View File

@ -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));
}
}

View File

@ -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<T extends RenderComponent> {
public class PositionedComponent<T extends RenderComponent> implements Renderable {
private final T component;
private int x, y;
@ -21,19 +20,24 @@ public class PositionedComponent<T extends RenderComponent> {
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<T extends RenderComponent> {
public T getComponent() {
return component;
}
private Vector2i windowSize() {
Window window = Minecraft.getInstance().getWindow();
return new Vector2i(window.getGuiScaledWidth(), window.getGuiScaledHeight());
}
}

View File

@ -111,7 +111,8 @@ public class RowLayoutComponent<T extends RenderComponent> extends AbstractLayou
return this;
}
public Builder<T> elements(T... elements) {
@SafeVarargs
public final Builder<T> elements(T... elements) {
this.elements.addAll(Arrays.asList(elements));
return this;
}