From cef0556a9fd2fb145e1d33102d5f3fc89781db26 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 6 Jul 2022 17:34:35 +0800 Subject: Fix #963 --- .../rei/api/client/gui/widgets/Widget.java | 11 +--- .../shedaniel/rei/api/client/util/MatrixUtils.java | 59 ++++++++++++++++++++++ .../categories/tag/ReferenceTagNodeWidget.java | 19 ++++--- .../client/categories/tag/TagNodeWidget.java | 7 +-- .../client/categories/tag/TagTreeWidget.java | 14 +++-- .../client/categories/tag/TagTreesWidget.java | 48 ------------------ .../client/categories/tag/ValueTagNodeWidget.java | 33 ++++++++---- .../gui/widget/DelegateWidgetWithTranslate.java | 6 +-- 8 files changed, 112 insertions(+), 85 deletions(-) create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/util/MatrixUtils.java delete mode 100644 default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagTreesWidget.java diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Widget.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Widget.java index 16ef576ee..2e683f51a 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Widget.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Widget.java @@ -32,6 +32,7 @@ import me.shedaniel.math.Rectangle; import me.shedaniel.math.impl.PointHelper; import me.shedaniel.rei.api.client.gui.AbstractContainerEventHandler; import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.util.MatrixUtils; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; @@ -130,15 +131,7 @@ public abstract class Widget extends AbstractContainerEventHandler implements ne @ApiStatus.Experimental public static CloseableScissors scissor(Matrix4f matrix, Rectangle bounds) { - Vector4f vec1 = new Vector4f((float) bounds.x, (float) bounds.y, 0, 1); - vec1.transform(matrix); - Vector4f vec2 = new Vector4f((float) bounds.getMaxX(), (float) bounds.getMaxY(), 0, 1); - vec2.transform(matrix); - int x1 = Math.round(vec1.x()); - int x2 = Math.round(vec2.x()); - int y1 = Math.round(vec1.y()); - int y2 = Math.round(vec2.y()); - ScissorsHandler.INSTANCE.scissor(new Rectangle(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1))); + ScissorsHandler.INSTANCE.scissor(MatrixUtils.transform(matrix, bounds)); return ScissorsHandler.INSTANCE::removeLastScissor; } } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/util/MatrixUtils.java b/api/src/main/java/me/shedaniel/rei/api/client/util/MatrixUtils.java new file mode 100644 index 000000000..f03d16315 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/util/MatrixUtils.java @@ -0,0 +1,59 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.api.client.util; + +import com.mojang.math.Matrix4f; +import com.mojang.math.Transformation; +import com.mojang.math.Vector4f; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Experimental +public class MatrixUtils { + public static Matrix4f inverse(Matrix4f matrix) { + Transformation transformation = new Transformation(matrix); + Transformation inverse = transformation.inverse(); + if (inverse != null) inverse.getScale(); // This has a side effect + return inverse == null ? Transformation.identity().getMatrix() : inverse.getMatrix(); + } + + public static Rectangle transform(Matrix4f matrix, Rectangle rectangle) { + Vector4f vec1 = new Vector4f((float) rectangle.x, (float) rectangle.y, 0, 1); + vec1.transform(matrix); + Vector4f vec2 = new Vector4f((float) rectangle.getMaxX(), (float) rectangle.getMaxY(), 0, 1); + vec2.transform(matrix); + int x1 = Math.round(vec1.x()); + int x2 = Math.round(vec2.x()); + int y1 = Math.round(vec1.y()); + int y2 = Math.round(vec2.y()); + return new Rectangle(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1)); + } + + public static Point transform(Matrix4f matrix, Point point) { + Vector4f mouse = new Vector4f((float) point.x, (float) point.y, 0, 1); + mouse.transform(matrix); + return new Point(mouse.x(), mouse.y()); + } +} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ReferenceTagNodeWidget.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ReferenceTagNodeWidget.java index 06a8267c3..5418e895d 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ReferenceTagNodeWidget.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ReferenceTagNodeWidget.java @@ -29,6 +29,7 @@ import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.gui.widgets.Slot; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.util.MatrixUtils; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.util.EntryIngredients; import me.shedaniel.rei.plugin.common.displays.tag.TagNode; @@ -44,12 +45,14 @@ import java.util.function.Function; public class ReferenceTagNodeWidget extends TagNodeWidget { private final TagNode node; + private final Rectangle overflowBounds; private final Rectangle bounds; private final Slot slot; private final List children; - public ReferenceTagNodeWidget(TagNode node, Function, EntryStack> mapper) { + public ReferenceTagNodeWidget(TagNode node, Function, EntryStack> mapper, Rectangle overflowBounds) { this.node = node; + this.overflowBounds = overflowBounds; this.bounds = new Rectangle(0, 0, 24, 23); this.slot = Widgets.createSlot(new Rectangle(0, 0, 18, 18)) .disableBackground() @@ -66,13 +69,15 @@ public class ReferenceTagNodeWidget extends TagNodeWidget { @Override public void render(PoseStack poses, int mouseX, int mouseY, float delta) { - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderTexture(0, new ResourceLocation("textures/gui/advancements/widgets.png")); - this.blit(poses, bounds.x, bounds.y, 1, 128 + 27, 24, 24); - this.slot.getBounds().setLocation(bounds.getCenterX() - this.slot.getBounds().getWidth() / 2, bounds.y + (bounds.height - this.slot.getBounds().getHeight()) / 2 + 1); - this.slot.render(poses, mouseX, mouseY, delta); - if (this.containsMouse(mouseX, mouseY)) { + if (this.overflowBounds.intersects(MatrixUtils.transform(poses.last().pose(), getBounds()))) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, new ResourceLocation("textures/gui/advancements/widgets.png")); + this.blit(poses, bounds.x, bounds.y, 1, 128 + 27, 24, 24); + this.slot.getBounds().setLocation(bounds.getCenterX() - this.slot.getBounds().getWidth() / 2, bounds.y + (bounds.height - this.slot.getBounds().getHeight()) / 2 + 1); + this.slot.render(poses, mouseX, mouseY, delta); + if (this.containsMouse(mouseX, mouseY)) { Tooltip.create(Component.literal("#" + this.node.getReference().location().toString())).queue(); + } } } diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagNodeWidget.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagNodeWidget.java index 9f2216935..9fbd7734b 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagNodeWidget.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagNodeWidget.java @@ -23,6 +23,7 @@ package me.shedaniel.rei.plugin.client.categories.tag; +import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.plugin.common.displays.tag.TagNode; @@ -31,11 +32,11 @@ import net.minecraft.core.Holder; import java.util.function.Function; public abstract class TagNodeWidget extends WidgetWithBounds { - static TagNodeWidget create(TagNode node, Function, EntryStack> mapper) { + static TagNodeWidget create(TagNode node, Function, EntryStack> mapper, Rectangle overflowBounds) { if (node.getReference() != null) { - return new ReferenceTagNodeWidget<>(node, mapper); + return new ReferenceTagNodeWidget<>(node, mapper, overflowBounds); } else if (node.getValue() != null) { - return new ValueTagNodeWidget<>(node, mapper); + return new ValueTagNodeWidget<>(node, mapper, overflowBounds); } else { throw new IllegalArgumentException("TagNode has no value or reference"); } diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagTreeWidget.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagTreeWidget.java index f544d4d7f..6a8e6affa 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagTreeWidget.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagTreeWidget.java @@ -24,9 +24,9 @@ package me.shedaniel.rei.plugin.client.categories.tag; import com.mojang.blaze3d.vertex.PoseStack; -import me.shedaniel.math.Color; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; +import me.shedaniel.rei.api.client.util.MatrixUtils; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.plugin.common.displays.tag.TagNode; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -40,16 +40,18 @@ import java.util.stream.Stream; public class TagTreeWidget extends WidgetWithBounds { private final Rectangle bounds; private final TagNode node; + private final Rectangle overflowBounds; private final TagNodeWidget rootWidget; private final List> childWidgets; private final List children; - public TagTreeWidget(TagNode node, Function, EntryStack> mapper) { + public TagTreeWidget(TagNode node, Function, EntryStack> mapper, Rectangle overflowBounds) { this.node = node; - this.rootWidget = TagNodeWidget.create(node, mapper); + this.overflowBounds = overflowBounds; + this.rootWidget = TagNodeWidget.create(node, mapper, overflowBounds); this.childWidgets = new ArrayList<>(); for (TagNode childNode : node.children()) { - TagTreeWidget childWidget = new TagTreeWidget<>(childNode, mapper); + TagTreeWidget childWidget = new TagTreeWidget<>(childNode, mapper, overflowBounds); childWidget.getBounds().y = rootWidget.getBounds().getMaxY() + 16; this.childWidgets.add(childWidget); } @@ -89,7 +91,9 @@ public class TagTreeWidget extends WidgetWithBounds { rootWidget.getBounds().getMaxY() + 6, rootWidget.getBounds().getMaxY() + 16, 0xFFFFFFFF); childWidget.getBounds().setLocation(getBounds().getCenterX() - childrenTotalWidth / 2 + x, this.rootWidget.getBounds().getMaxY() + 16); - childWidget.render(poses, mouseX, mouseY, delta); + if (this.overflowBounds.intersects(MatrixUtils.transform(poses.last().pose(), childWidget.getBounds()))) { + childWidget.render(poses, mouseX, mouseY, delta); + } x += childWidget.getBounds().width + 6; } } diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagTreesWidget.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagTreesWidget.java deleted file mode 100644 index bfa0a0e56..000000000 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/TagTreesWidget.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.shedaniel.rei.plugin.client.categories.tag; - -import com.mojang.blaze3d.vertex.PoseStack; -import me.shedaniel.math.Rectangle; -import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; -import net.minecraft.client.gui.components.events.GuiEventListener; - -import java.util.List; - -public class TagTreesWidget extends WidgetWithBounds { - @Override - public Rectangle getBounds() { - return null; - } - - @Override - public void render(PoseStack poses, int mouseX, int mouseY, float delta) { - - } - - @Override - public List children() { - return null; - } -} diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ValueTagNodeWidget.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ValueTagNodeWidget.java index e0d91e258..5936e1842 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ValueTagNodeWidget.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/tag/ValueTagNodeWidget.java @@ -26,15 +26,15 @@ package me.shedaniel.rei.plugin.client.categories.tag; import com.google.common.base.Predicates; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; +import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.gui.widgets.*; +import me.shedaniel.rei.api.client.util.MatrixUtils; import me.shedaniel.rei.api.common.entry.EntryStack; -import me.shedaniel.rei.api.common.util.EntryIngredients; import me.shedaniel.rei.plugin.common.displays.tag.TagNode; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; -import net.minecraft.util.Mth; import java.util.ArrayList; import java.util.Collections; @@ -43,10 +43,13 @@ import java.util.function.Function; public class ValueTagNodeWidget extends TagNodeWidget { private final Rectangle bounds; + private final List widgets; private final WidgetWithBounds widget; private final List children; + private final Rectangle overflowBounds; - public ValueTagNodeWidget(TagNode node, Function, EntryStack> mapper) { + public ValueTagNodeWidget(TagNode node, Function, EntryStack> mapper, Rectangle overflowBounds) { + this.overflowBounds = overflowBounds; HolderSet holders = node.getValue(); int width = Math.min(4, holders.size()); int height = Math.max((int) Math.ceil(holders.size() * 1.0 / width), 1); @@ -55,19 +58,19 @@ public class ValueTagNodeWidget extends TagNodeWidget { .rendering(Predicates.alwaysTrue()); Panel slotBackground = Widgets.createSlotBase(new Rectangle(5, 5, 16 * width + 2, 16 * height + 2)); int i = 0; - List widgets = new ArrayList<>(); - widgets.add(background); - widgets.add(slotBackground); + this.widgets = new ArrayList<>(); + this.widgets.add(background); + this.widgets.add(slotBackground); for (Holder holder : holders) { int x = i % width; int y = i / width; Slot slot = Widgets.createSlot(new Rectangle(x * 16 + 5, y * 16 + 5, 18, 18)) .entry(mapper.apply(holder)) .disableBackground(); - widgets.add(slot); + this.widgets.add(slot); i++; } - this.widget = Widgets.withTranslate(Widgets.concat(widgets), + this.widget = Widgets.withTranslate(Widgets.concat(this.widgets), $ -> Matrix4f.createTranslateMatrix(getBounds().x, getBounds().y, 0)); this.children = Collections.singletonList(this.widget); } @@ -79,7 +82,19 @@ public class ValueTagNodeWidget extends TagNodeWidget { @Override public void render(PoseStack poses, int mouseX, int mouseY, float delta) { - this.widget.render(poses, mouseX, mouseY, delta); + Rectangle bounds = getBounds(); + if (this.overflowBounds.intersects(MatrixUtils.transform(poses.last().pose(), bounds))) { + poses.pushPose(); + poses.translate(bounds.x, bounds.y, 0); + Point mouse = new Point(mouseX - bounds.x, mouseY - bounds.y); + for (Widget widget : this.widgets) { + if (!(widget instanceof WidgetWithBounds withBounds) || + this.overflowBounds.intersects(MatrixUtils.transform(poses.last().pose(), withBounds.getBounds()))) { + widget.render(poses, mouse.x, mouse.y, delta); + } + } + poses.popPose(); + } } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DelegateWidgetWithTranslate.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DelegateWidgetWithTranslate.java index 9daf12aa2..e90c1cb19 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DelegateWidgetWithTranslate.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DelegateWidgetWithTranslate.java @@ -30,6 +30,7 @@ import com.mojang.math.Vector4f; import me.shedaniel.rei.api.client.gui.widgets.DelegateWidget; import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; +import me.shedaniel.rei.api.client.util.MatrixUtils; import java.util.function.Supplier; @@ -46,10 +47,7 @@ public class DelegateWidgetWithTranslate extends DelegateWidget { } protected final Matrix4f inverseTranslate() { - Transformation transformation = new Transformation(translate()); - Transformation inverse = transformation.inverse(); - if (inverse != null) inverse.getScale(); // This has a side effect - return inverse == null ? Transformation.identity().getMatrix() : inverse.getMatrix(); + return MatrixUtils.inverse(translate()); } @Override -- cgit