From e15d64ff3dc7509fb6d8ab75c1547f82123b16cf Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 29 Jan 2024 20:30:58 +0000 Subject: [PATCH] Implement support for displaying chapters with varying content height --- .../client/gui/spellbook/SpellbookScreen.java | 1 - .../gui/spellbook/element/DynamicContent.java | 43 +++++++----- .../client/gui/spellbook/element/Panel.java | 66 +++++++++++++++++++ 3 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Panel.java diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/SpellbookScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/SpellbookScreen.java index 490d835f..0dc0a71e 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/SpellbookScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/SpellbookScreen.java @@ -160,7 +160,6 @@ public class SpellbookScreen extends HandledScreen imple tabs.getAllTabs().forEach(tab -> { Bounds bounds = tab.bounds(); - chapters.getCurrentChapter(); boolean hover = bounds.contains(mouseX, mouseY); int color = tab.chapter().color() & 0xFFFFFF; diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/DynamicContent.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/DynamicContent.java index 80812afb..c8a64c74 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/DynamicContent.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/DynamicContent.java @@ -21,13 +21,17 @@ import net.minecraft.util.*; public class DynamicContent implements Content { private static final Text UNKNOWN = Text.of("???"); - private static final Text UNKNOWN_LEVEL = Text.literal("Level: ???").formatted(Formatting.DARK_GREEN); private SpellbookState.PageState state = new SpellbookState.PageState(); private final List pages; private Bounds bounds = Bounds.empty(); + private final Panel leftPanel = new Panel(this); + private final Panel rightPanel = new Panel(this); + + private int headerColor; + public DynamicContent(PacketByteBuf buffer) { pages = buffer.readList(Page::new); } @@ -35,32 +39,26 @@ public class DynamicContent implements Content { @Override public void draw(DrawContext context, int mouseX, int mouseY, IViewRoot container) { int pageIndex = state.getOffset() * 2; - - getPage(pageIndex).ifPresent(page -> page.draw(context, mouseX, mouseY, container)); - - context.getMatrices().push(); - getPage(pageIndex + 1).ifPresent(page -> { - page.bounds.left = bounds.left + bounds.width / 2 + 20; - page.draw(context, mouseX, mouseY, container); - }); - context.getMatrices().pop(); - TextRenderer font = MinecraftClient.getInstance().textRenderer; - int headerColor = mouseY % 255; + headerColor = mouseY % 255; - Text pageText = Text.translatable("%s/%s", (pageIndex / 2) + 1, pages.size() / 2); + Text pageText = Text.translatable("%s/%s", (pageIndex / 2) + 1, (int)Math.ceil(pages.size() / 2F)); context.drawText(font, pageText, (int)(337 - font.getWidth(pageText) / 2F), 190, headerColor, false); } @Override public void copyStateFrom(Content old) { if (old instanceof DynamicContent o) { + if (state.getOffset() == o.state.getOffset()) { + leftPanel.verticalScrollbar.getScrubber().scrollTo(o.leftPanel.verticalScrollbar.getScrubber().getPosition(), false); + rightPanel.verticalScrollbar.getScrubber().scrollTo(o.rightPanel.verticalScrollbar.getScrubber().getPosition(), false); + } state = o.state; setBounds(o.bounds); } } - private Optional getPage(int index) { + Optional getPage(int index) { if (index < 0 || index >= pages.size()) { return Optional.empty(); } @@ -71,9 +69,15 @@ public class DynamicContent implements Content { this.bounds = bounds; pages.forEach(page -> { page.reset(); + int oldHeight = page.bounds.height; page.bounds.copy(bounds); + page.bounds.left = 0; + page.bounds.top = 0; page.bounds.width /= 2; + page.bounds.height = oldHeight; }); + + leftPanel.setBounds(bounds); } @Override @@ -83,6 +87,10 @@ public class DynamicContent implements Content { screen.addPageButtons(187, 30, 350, incr -> { state.swap(incr, (int)Math.ceil(pages.size() / 2F)); }); + + int pageIndex = state.getOffset() * 2; + leftPanel.init(screen, pageIndex); + rightPanel.init(screen, pageIndex + 1); } class Page implements Drawable { @@ -145,18 +153,17 @@ public class DynamicContent implements Content { element.compile(relativeY, container); relativeY += element.bounds().height; } + bounds.height = relativeY; } boolean needsMoreXp = level < 0 || Pony.of(MinecraftClient.getInstance().player).getLevel().get() < level; - int headerColor = mouseY % 255; - MatrixStack matrices = context.getMatrices(); DrawableUtil.drawScaledText(context, needsMoreXp ? UNKNOWN : title, bounds.left, bounds.top - 10, 1.3F, headerColor); - DrawableUtil.drawScaledText(context, level < 0 ? UNKNOWN_LEVEL : Text.literal("Level: " + (level + 1)).formatted(Formatting.DARK_GREEN), bounds.left, bounds.top - 10 + 12, 0.8F, headerColor); + DrawableUtil.drawScaledText(context, Text.translatable("gui.unicopia.spellbook.page.level_requirement", level < 0 ? "???" : "" + (level + 1)).formatted(Formatting.DARK_GREEN), bounds.left, bounds.top - 10 + 12, 0.8F, headerColor); matrices.push(); - matrices.translate(bounds.left, bounds.top + 16, 0); + matrices.translate(0, 16, 0); elements.stream().filter(PageElement::isFloating).forEach(element -> { Bounds bounds = element.bounds(); matrices.push(); diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Panel.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Panel.java new file mode 100644 index 00000000..fc84e687 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Panel.java @@ -0,0 +1,66 @@ +package com.minelittlepony.unicopia.client.gui.spellbook.element; + +import java.util.Optional; + +import com.minelittlepony.common.client.gui.IViewRoot; +import com.minelittlepony.common.client.gui.ScrollContainer; +import com.minelittlepony.common.client.gui.dimension.Bounds; +import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookScreen; +import com.minelittlepony.unicopia.client.gui.spellbook.element.DynamicContent.Page; + +import net.minecraft.client.gui.DrawContext; + +class Panel extends ScrollContainer { + private final DynamicContent content; + + Panel(DynamicContent content) { + this.content = content; + } + + private Optional page = Optional.empty(); + + public void init(SpellbookScreen screen, int pageIndex) { + verticalScrollbar.layoutToEnd = true; + getContentPadding().top = 15; + page = content.getPage(pageIndex); + + margin.left = screen.getX() + 30; + margin.top = screen.getY() + 15; + margin.right = screen.width - screen.getBackgroundWidth() - screen.getX() + 20; + margin.bottom = screen.height - screen.getBackgroundHeight() - screen.getY() + 40; + + if (pageIndex % 2 == 1) { + margin.left += screen.getBackgroundWidth() / 2 - 10; + } else { + margin.right += screen.getBackgroundWidth() / 2; + } + init(() -> {}); + screen.addDrawable(this); + ((IViewRoot)screen).getChildElements().add(this); + } + + @Override + protected void renderContents(DrawContext context, int mouseX, int mouseY, float partialTicks) { + page.ifPresent(p -> { + int oldHeight = p.getBounds().height; + p.draw(context, mouseX, mouseY, this); + if (p.getBounds().height != oldHeight) { + verticalScrollbar.reposition(); + } + }); + super.renderContents(context, mouseX, mouseY, partialTicks); + } + + @Override + public Bounds getContentBounds() { + return page == null ? Bounds.empty() : page.map(page -> { + return new Bounds(0, 0, 1, page.getBounds().height); + }).orElse(Bounds.empty()); + } + + @Override + protected void drawBackground(DrawContext context, int mouseX, int mouseY, float partialTicks) { } + + @Override + protected void drawDecorations(DrawContext context, int mouseX, int mouseY, float partialTicks) { } +} \ No newline at end of file