From f12c906de61d340cfe537f4f166aa20c4bdc52a1 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 22 Jun 2022 23:01:35 +0800 Subject: Finish Collapsible Entries Visuals --- .../widget/entrylist/CollapsedEntriesTooltip.java | 88 +++++++++++++++++++++ .../entrylist/CollapsingEntryListWidget.java | 7 ++ .../gui/widget/entrylist/EntryListStackEntry.java | 90 ++++++++++++++++++++++ .../widget/entrylist/PaginatedEntryListWidget.java | 14 +--- .../entry/type/collapsed/CollapsedStack.java | 9 +++ .../collapsed/CollapsibleEntryRegistryImpl.java | 24 ++++-- .../assets/roughlyenoughitems/lang/en_us.json | 3 + 7 files changed, 217 insertions(+), 18 deletions(-) create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsedEntriesTooltip.java (limited to 'runtime') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsedEntriesTooltip.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsedEntriesTooltip.java new file mode 100644 index 000000000..38fd4ca01 --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsedEntriesTooltip.java @@ -0,0 +1,88 @@ +/* + * 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.impl.client.gui.widget.entrylist; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.impl.common.entry.type.collapsed.CollapsedStack; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.util.Mth; +import net.minecraft.world.inventory.tooltip.TooltipComponent; + +public class CollapsedEntriesTooltip implements ClientTooltipComponent, TooltipComponent { + private static final int MAX_WIDTH = 140; + private final CollapsedStack stack; + + public CollapsedEntriesTooltip(CollapsedStack stack) { + this.stack = stack; + } + + @Override + public int getHeight() { + int entrySize = EntryListWidget.entrySize(); + int w = Math.max(1, MAX_WIDTH / entrySize); + return Math.min(3, Mth.ceil(stack.getIngredient().size() / (float) w)) * entrySize + 2; + } + + @Override + public int getWidth(Font font) { + int entrySize = EntryListWidget.entrySize(); + int w = Math.max(1, MAX_WIDTH / entrySize); + int size = stack.getIngredient().size(); + return Math.min(size, w) * entrySize; + } + + @Override + public void renderImage(Font font, int x, int y, PoseStack poses, ItemRenderer renderer, int z) { + int entrySize = EntryListWidget.entrySize(); + int w = Math.max(1, MAX_WIDTH / entrySize); + int i = 0; + poses.pushPose(); + poses.translate(0, 0, z + 50); + for (EntryStack entry : stack.getIngredient()) { + int x1 = x + (i % w) * entrySize; + int y1 = y + 1 + (i / w) * entrySize; + i++; + if (i / w > 3 - 1) { + poses.translate(0, 0, 200); + MultiBufferSource.BufferSource source = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder()); + Component text = new TextComponent("+" + (stack.getIngredient().size() - w * 3 + 1)).withStyle(ChatFormatting.GRAY); + font.drawInBatch(text, x1 + entrySize / 2 - font.width(text) / 2, y1 + entrySize / 2 - 1, -1, true, poses.last().pose(), source, false, 0, 15728880); + source.endBatch(); + break; + } else { + entry.render(poses, new Rectangle(x1, y1, entrySize, entrySize), -1000, -1000, 0); + } + } + poses.popPose(); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsingEntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsingEntryListWidget.java index 77e59d6f4..af0fb2900 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsingEntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/CollapsingEntryListWidget.java @@ -97,6 +97,13 @@ public abstract class CollapsingEntryListWidget extends EntryListWidget { if (collapsedStack != null) { collapsedStackIndexed.put(index, collapsedStack); + + if (collapsedStack.isExpanded()) { + int size = collapsedStack.getIngredient().size(); + for (int i = 1; i < size; i++) { + collapsedStackIndexed.put(index + i, collapsedStack); + } + } } index++; diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListStackEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListStackEntry.java index a4117d202..b5277f69b 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListStackEntry.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListStackEntry.java @@ -26,15 +26,25 @@ package me.shedaniel.rei.impl.client.gui.widget.entrylist; import com.mojang.blaze3d.vertex.PoseStack; import me.shedaniel.clothconfig2.api.animator.NumberAnimator; import me.shedaniel.clothconfig2.api.animator.ValueAnimator; +import me.shedaniel.math.FloatingPoint; +import me.shedaniel.math.FloatingRectangle; import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; import me.shedaniel.math.impl.PointHelper; +import me.shedaniel.rei.api.client.ClientHelper; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.gui.widgets.Widgets; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.impl.client.gui.widget.CachedEntryListRender; import me.shedaniel.rei.impl.client.gui.widget.DisplayedEntryWidget; import me.shedaniel.rei.impl.common.entry.type.collapsed.CollapsedStack; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.world.inventory.tooltip.TooltipComponent; import org.jetbrains.annotations.Nullable; +import java.util.List; + import static me.shedaniel.rei.impl.client.gui.widget.entrylist.EntryListWidget.entrySize; @SuppressWarnings("UnstableApiUsage") @@ -43,6 +53,7 @@ public class EntryListStackEntry extends DisplayedEntryWidget { public EntryStack our; private NumberAnimator size = null; private CollapsedStack collapsedStack = null; + private List collapsedBounds = null; public EntryListStackEntry(CollapsingEntryListWidget parent, int x, int y, int entrySize, boolean zoomed) { super(new Point(x, y), entrySize); @@ -89,6 +100,51 @@ public class EntryListStackEntry extends DisplayedEntryWidget { return super.containsMouse(mouseX, mouseY) && parent.containsChecked(mouseX, mouseY, true); } + @Override + protected void drawBackground(PoseStack matrices, int mouseX, int mouseY, float delta) { + Rectangle bounds = getBounds(); + + if (collapsedStack != null) { + fillGradient(matrices, bounds.x, bounds.y, bounds.getMaxX(), bounds.getMaxY(), 0x34FFFFFF, 0x34FFFFFF); + } + + super.drawBackground(matrices, mouseX, mouseY, delta); + } + + @Override + protected void drawCurrentEntry(PoseStack matrices, int mouseX, int mouseY, float delta) { + if (collapsedStack != null && !collapsedStack.isExpanded()) { + Rectangle bounds = getBounds(); + List> stacks = collapsedStack.getIngredient(); + float fullSize = bounds.getWidth(); + + matrices.pushPose(); + matrices.translate(0, 0, 10); + + for (int i = stacks.size() - 1; i >= 0; i--) { + EntryStack stack = stacks.get(i); + + if (i >= collapsedBounds.size()) { + continue; + } + + FloatingRectangle value = collapsedBounds.get(i); + double x = bounds.x + value.x * fullSize; + double y = bounds.y + value.y * fullSize; + + double scaledSize = value.width * fullSize; + + stack.render(matrices, new Rectangle(x - scaledSize / 2, y - scaledSize / 2, scaledSize, scaledSize), mouseX, mouseY, delta); + + matrices.translate(0, 0, 10); + } + + matrices.popPose(); + } else { + super.drawCurrentEntry(matrices, mouseX, mouseY, delta); + } + } + @Override protected boolean doAction(double mouseX, double mouseY, int button) { if (collapsedStack != null) { @@ -104,6 +160,40 @@ public class EntryListStackEntry extends DisplayedEntryWidget { public void collapsed(CollapsedStack collapsedStack) { this.collapsedStack = collapsedStack; + if (collapsedStack == null) { + this.collapsedBounds = null; + } else { + List> ingredient = collapsedStack.getIngredient(); + if (ingredient.size() == 0) this.collapsedBounds = null; + else if (ingredient.size() == 1) { + this.collapsedBounds = List.of(new FloatingRectangle(0, 0, 1, 1)); + } else { + this.collapsedBounds = List.of(new FloatingRectangle(0.44, 0.56, 0.9, 0.8), + new FloatingRectangle(0.56, 0.44, 0.9, 0.8)); + } + } + } + + @Override + @Nullable + public Tooltip getCurrentTooltip(Point point) { + if (this.collapsedStack != null) { + if (!this.collapsedStack.isExpanded()) { + Tooltip tooltip = Tooltip.create(point, new TranslatableComponent("text.rei.collapsed.entry", collapsedStack.getName())); + tooltip.add((TooltipComponent) new CollapsedEntriesTooltip(collapsedStack)); + tooltip.add(new TranslatableComponent("text.rei.collapsed.entry.hint.expand", collapsedStack.getName(), collapsedStack.getIngredient().size()) + .withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC)); + ClientHelper.getInstance().appendModIdToTooltips(tooltip, collapsedStack.getModId()); + return tooltip; + } + } + + Tooltip tooltip = super.getCurrentTooltip(point); + if (tooltip != null && this.collapsedStack != null) { + tooltip.add(new TranslatableComponent("text.rei.collapsed.entry.hint.collapse", collapsedStack.getName(), collapsedStack.getIngredient().size()) + .withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC)); + } + return tooltip; } @Nullable diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java index 672c16aa3..7d82a41f5 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/PaginatedEntryListWidget.java @@ -24,28 +24,16 @@ package me.shedaniel.rei.impl.client.gui.widget.entrylist; import com.google.common.collect.Lists; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.*; -import com.mojang.math.Matrix4f; +import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.config.ConfigObject; -import me.shedaniel.rei.api.client.entry.renderer.BatchedEntryRenderer; -import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer; -import me.shedaniel.rei.api.client.gui.widgets.Tooltip; -import me.shedaniel.rei.api.client.gui.widgets.TooltipContext; import me.shedaniel.rei.api.client.util.ClientEntryStacks; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.impl.client.gui.widget.BatchedEntryRendererManager; import me.shedaniel.rei.impl.client.gui.widget.CachedEntryListRender; import me.shedaniel.rei.impl.client.gui.widget.EntryWidget; import me.shedaniel.rei.impl.common.entry.type.collapsed.CollapsedStack; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; import net.minecraft.util.Mth; -import net.minecraft.util.Unit; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/collapsed/CollapsedStack.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/collapsed/CollapsedStack.java index a34febbec..348b3a0f2 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/collapsed/CollapsedStack.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/collapsed/CollapsedStack.java @@ -24,6 +24,7 @@ package me.shedaniel.rei.impl.common.entry.type.collapsed; import me.shedaniel.rei.api.common.entry.EntryStack; +import net.minecraft.network.chat.Component; import java.util.List; @@ -47,4 +48,12 @@ public class CollapsedStack { public void setExpanded(boolean expanded) { this.entry.setExpanded(expanded); } + + public Component getName() { + return entry.getName(); + } + + public String getModId() { + return entry.getModId(); + } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/collapsed/CollapsibleEntryRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/collapsed/CollapsibleEntryRegistryImpl.java index 8a7028ffa..cf937adfc 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/collapsed/CollapsibleEntryRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/common/entry/type/collapsed/CollapsibleEntryRegistryImpl.java @@ -29,6 +29,8 @@ import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; import java.util.ArrayList; import java.util.List; @@ -39,15 +41,15 @@ public class CollapsibleEntryRegistryImpl implements CollapsibleEntryRegistry { private final List entries = new ArrayList<>(); @Override - public void group(List> stacks) { + public void group(ResourceLocation id, Component name, List> stacks) { Objects.requireNonNull(stacks, "stacks"); - this.entries.add(new Entry(new ListMatcher(stacks))); + this.entries.add(new Entry(id.getNamespace(), name, new ListMatcher(stacks))); } @Override - public void group(Predicate> predicate) { + public void group(ResourceLocation id, Component name, Predicate> predicate) { Objects.requireNonNull(predicate, "predicate"); - this.entries.add(new Entry((stack, hashExact) -> ((Predicate>) predicate).test(stack))); + this.entries.add(new Entry(id.getNamespace(), name, (stack, hashExact) -> ((Predicate>) predicate).test(stack))); } @Override @@ -65,13 +67,25 @@ public class CollapsibleEntryRegistryImpl implements CollapsibleEntryRegistry { } public static class Entry { + private final String modId; + private final Component name; private final Matcher matcher; private boolean expanded; - public Entry(Matcher matcher) { + public Entry(String modId, Component name, Matcher matcher) { + this.modId = modId; + this.name = name; this.matcher = matcher; } + public String getModId() { + return modId; + } + + public Component getName() { + return name; + } + public Matcher getMatcher() { return matcher; } diff --git a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json index 765085e09..e5b6b8f0c 100755 --- a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json +++ b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json @@ -156,6 +156,9 @@ "text.rei.changelog.title": "REI Changelog", "text.rei.changelog.error.missingChangelogFile": "Missing changelog File!", "text.rei.changelog.error.failedToReadChangelogFile": "Failed to read changelog File!", + "text.rei.collapsed.entry": "Collapsed Entry: %s", + "text.rei.collapsed.entry.hint.expand": "Click to expand all %s (%d entries)", + "text.rei.collapsed.entry.hint.collapse": "Click to collapse all %s (%d entries)", "favorite.section.gamemode": "Game Mode", "favorite.section.weather": "Weather", "favorite.section.time": "Time", -- cgit