Fix some more text wrapping issues and catch exceptions whilst loading chapters

This commit is contained in:
Sollace 2022-09-02 12:53:14 +02:00
parent 5256f1f273
commit 37148fad51
5 changed files with 76 additions and 39 deletions

View file

@ -2,8 +2,7 @@ package com.minelittlepony.unicopia.container;
import java.util.*;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.*;
import com.minelittlepony.common.client.gui.IViewRoot;
import com.minelittlepony.common.client.gui.dimension.Bounds;
import com.minelittlepony.unicopia.client.gui.DrawableUtil;
@ -25,8 +24,8 @@ public class DynamicContent implements Content {
private Bounds bounds = Bounds.empty();
public DynamicContent(JsonArray pages) {
pages.forEach(page -> this.pages.add(new Page(page.getAsJsonObject())));
public DynamicContent(JsonArray json) {
json.forEach(element -> pages.add(new Page(element.getAsJsonObject())));
}
@Override
@ -36,8 +35,10 @@ public class DynamicContent implements Content {
getPage(pageIndex).ifPresent(page -> page.draw(matrices, mouseX, mouseY, container));
matrices.push();
matrices.translate(bounds.width / 2 + 20, 0, 0);
getPage(pageIndex + 1).ifPresent(page -> page.draw(matrices, mouseX, mouseY, container));
getPage(pageIndex + 1).ifPresent(page -> {
page.bounds.left = bounds.left + bounds.width / 2 + 20;
page.draw(matrices, mouseX, mouseY, container);
});
matrices.pop();
}
@ -45,7 +46,7 @@ public class DynamicContent implements Content {
public void copyStateFrom(Content old) {
if (old instanceof DynamicContent o) {
offset = o.offset;
bounds = o.bounds;
setBounds(o.bounds);
}
}
@ -56,10 +57,18 @@ public class DynamicContent implements Content {
return Optional.of(pages.get(index));
}
private void setBounds(Bounds bounds) {
this.bounds = bounds;
pages.forEach(page -> {
page.reset();
page.bounds.copy(bounds);
page.bounds.width /= 2;
});
}
@Override
public void init(SpellbookScreen screen) {
bounds = screen.getFrameBounds();
pages.forEach(Page::reset);
setBounds(screen.getFrameBounds());
screen.addPageButtons(187, 30, 350, incr -> {
offset = MathHelper.clamp(offset + incr, 0, (int)Math.ceil(pages.size() / 2F) - 1);
});
@ -73,6 +82,8 @@ public class DynamicContent implements Content {
private boolean compiled;
private Bounds bounds = Bounds.empty();
public Page(JsonObject json) {
title = Text.Serializer.fromJson(json.get("title"));
level = JsonHelper.getInt(json, "level", 0);
@ -82,7 +93,7 @@ public class DynamicContent implements Content {
}
protected int getLineLimitAt(int yPosition) {
return (bounds.width / 2 - 10) - elements.stream()
return (bounds.width - 10) - elements.stream()
.filter(PageElement::isFloating)
.map(PageElement::bounds)
.filter(b -> b.contains(b.left + b.width / 2, yPosition))
@ -113,6 +124,11 @@ public class DynamicContent implements Content {
@Override
public void draw(MatrixStack matrices, int mouseX, int mouseY, IViewRoot container) {
if (elements.isEmpty()) {
return;
}
if (!compiled) {
compiled = true;
int relativeY = 0;

View file

@ -54,7 +54,7 @@ interface PageElement extends Drawable {
);
}
if (el.has("recipe")) {
return new Recipe(page, new Identifier(JsonHelper.getString(el, "texture")), new Bounds(0, 0, 0, 30));
return new Recipe(page, new Identifier(JsonHelper.getString(el, "recipe")), new Bounds(0, 0, 0, 0));
}
return new TextBlock(page, Text.Serializer.fromJson(element));
}
@ -86,11 +86,10 @@ interface PageElement extends Drawable {
@Override
public void compile(int y, IViewRoot container) {
wrappedText.clear();
ParagraphWrappingVisitor visitor = new ParagraphWrappingVisitor(yPosition -> {
return page.getLineLimitAt(y + yPosition);
}, (line, yPosition) -> {
wrappedText.add(new Line(line, page.getLeftMarginAt(y + yPosition)));
});
ParagraphWrappingVisitor visitor = new ParagraphWrappingVisitor(
yPosition -> page.getLineLimitAt(y + yPosition),
(line, yPosition) -> wrappedText.add(new Line(line, page.getLeftMarginAt(y + yPosition)))
);
unwrappedText.visit(visitor, Style.EMPTY);
visitor.forceAdvance();
bounds.height = MinecraftClient.getInstance().textRenderer.fontHeight * (wrappedText.size());
@ -128,12 +127,18 @@ interface PageElement extends Drawable {
}
@Override
public void compile(int y, IViewRoot Container) {
public void compile(int y, IViewRoot container) {
if (container instanceof SpellbookScreen book) {
bounds().left = book.getX();
bounds().top = book.getY();
}
MinecraftClient.getInstance().world.getRecipeManager().get(id).ifPresent(recipe -> {
if (recipe instanceof SpellbookRecipe spellRecipe) {
IngredientTree tree = new IngredientTree(page.getBounds().left, y, page().getBounds().width / 2 - 20, 20);
IngredientTree tree = new IngredientTree(
bounds().left + page().getBounds().left,
bounds().top + page().getBounds().top + y + 10, page().getBounds().width - 20, 20);
spellRecipe.buildCraftingTree(tree);
bounds.height = tree.build(Container);
bounds.height = tree.build(container) - 10;
}
});
}

View file

@ -40,7 +40,7 @@ class ParagraphWrappingVisitor implements StyledVisitor<Object> {
int newline = s.indexOf('\n');
if (newline >= 0 && newline < trimmedLength) {
trimmedLength = newline;
trimmedLength = newline + 1;
} else {
newline = -1;
}
@ -49,17 +49,23 @@ class ParagraphWrappingVisitor implements StyledVisitor<Object> {
trimmedLength = s.length();
}
String wrappedFragment = s.substring(0, trimmedLength);
int lastSpace = wrappedFragment.lastIndexOf(' ');
trimmedLength = lastSpace > 0 ? Math.min(lastSpace, trimmedLength) : trimmedLength;
// avoid breaking in the middle of a word
if (trimmedLength < s.length() - 1 && trimmedLength > 0
&& (!Character.isWhitespace(s.charAt(trimmedLength + 1)) || !Character.isWhitespace(s.charAt(trimmedLength - 1)))) {
String wrappedFragment = s.substring(0, trimmedLength);
int lastSpace = wrappedFragment.lastIndexOf(' ');
trimmedLength = lastSpace > 0 ? Math.min(lastSpace, trimmedLength) : trimmedLength;
}
Text fragment = Text.literal(s.substring(0, trimmedLength).trim()).setStyle(style);
float grabbedWidth = handler.getWidth(fragment);
// advance if appending the next segment would cause an overflow
if (currentLineCollectedLength + grabbedWidth > pageWidth) {
advance();
}
// append the segment to the line that's being built
if (currentLineCollectedLength > 0) {
currentLine.append(" ");
currentLineCollectedLength += handler.getWidth(" ");
@ -67,6 +73,10 @@ class ParagraphWrappingVisitor implements StyledVisitor<Object> {
currentLine.append(fragment);
currentLineCollectedLength += grabbedWidth;
if (newline >= 0) {
advance();
}
if (trimmedLength <= s.length()) {
s = s.substring(trimmedLength, s.length());
}

View file

@ -4,10 +4,13 @@ import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import com.google.gson.*;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.container.SpellbookChapterList.*;
import com.minelittlepony.unicopia.util.Resources;
import com.mojang.logging.LogUtils;
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
import net.minecraft.client.MinecraftClient;
@ -17,10 +20,10 @@ import net.minecraft.util.*;
import net.minecraft.util.profiler.Profiler;
public class SpellbookChapterLoader extends JsonDataLoader implements IdentifiableResourceReloadListener {
public static boolean DEBUG = true;
private static final Logger LOGGER = LogUtils.getLogger();
private static final Identifier ID = Unicopia.id("spellbook/chapters");
private static final Executor EXECUTOR = CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS);
public static boolean DEBUG = true;
public static final SpellbookChapterLoader INSTANCE = new SpellbookChapterLoader();
@ -39,20 +42,22 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab
return new HashSet<>(chapters.values());
}
private static final Executor EXECUTOR = CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS);
@Override
protected void apply(Map<Identifier, JsonElement> data, ResourceManager manager, Profiler profiler) {
chapters = data.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> {
JsonObject json = JsonHelper.asObject(entry.getValue(), "root");
try {
chapters = data.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> {
JsonObject json = JsonHelper.asObject(entry.getValue(), "root");
return new Chapter(entry.getKey(),
TabSide.valueOf(JsonHelper.getString(json, "side")),
JsonHelper.getInt(json, "y_position"),
JsonHelper.getInt(json, "color", 0),
loadContent(JsonHelper.getObject(json, "content", new JsonObject()))
);
}));
return new Chapter(entry.getKey(),
TabSide.valueOf(JsonHelper.getString(json, "side")),
JsonHelper.getInt(json, "y_position"),
JsonHelper.getInt(json, "color", 0),
loadContent(JsonHelper.getObject(json, "content", new JsonObject()))
);
}));
} catch (IllegalStateException | JsonParseException e) {
LOGGER.error("Could not load spellbook chapters due to exception", e);
}
if (DEBUG) {
CompletableFuture.runAsync(() -> {

View file

@ -64,13 +64,14 @@ public class SpellbookProfilePageContent extends DrawableHelper implements Spell
float alphaF = (MathHelper.sin(delta / 9F) + 1) / 2F;
int alpha = (int)(alphaF * 0x10) & 0xFF;
int color = 0x10404000 | alpha;
int xpColor = 0xAA0040FF | ((int)(xpPercentage * 0xFF) & 0xFF) << 16;
int xpColor = 0xAA0040FF | ((int)((0.3F + 0.7F * xpPercentage) * 0xFF) & 0xFF) << 16;
int manaColor = 0xFF00F040 | (int)((0.3F + 0.7F * alphaF) * 0x40) << 16;
DrawableUtil.drawArc(matrices, 0, radius + 24, 0, DrawableUtil.TAU, color, false);
DrawableUtil.drawArc(matrices, radius / 3, radius + 6, 0, DrawableUtil.TAU, color, false);
DrawableUtil.drawArc(matrices, radius / 3, radius + 6, 0, xpPercentage * DrawableUtil.TAU, xpColor, false);
radius += 8;
DrawableUtil.drawArc(matrices, radius, radius + 6 + growth, 0, manaPercentage * DrawableUtil.TAU, 0xFF40F040, false);
DrawableUtil.drawArc(matrices, radius, radius + 6 + growth, 0, manaPercentage * DrawableUtil.TAU, manaColor, false);
String manaString = (int)reserves.getMana().get() + "/" + (int)reserves.getMana().getMax();