From bc2fb79b4ea5db644ef4e64641239893f349f579 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Sun, 15 Oct 2023 15:47:02 +0300 Subject: Fix WLabel/WText.getTextStyleAt with non-left-top alignments --- .../cotton/gui/impl/client/TextAlignment.java | 46 +++++++++++++ .../github/cottonmc/cotton/gui/widget/WLabel.java | 13 ++-- .../github/cottonmc/cotton/gui/widget/WText.java | 14 ++-- .../cottonmc/test/client/LibGuiTestClient.java | 1 + .../cottonmc/test/client/TextAlignmentTestGui.java | 75 ++++++++++++++++++++++ 5 files changed, 132 insertions(+), 17 deletions(-) create mode 100644 src/main/java/io/github/cottonmc/cotton/gui/impl/client/TextAlignment.java create mode 100644 src/testMod/java/io/github/cottonmc/test/client/TextAlignmentTestGui.java diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/TextAlignment.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/TextAlignment.java new file mode 100644 index 0000000..0c005eb --- /dev/null +++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/TextAlignment.java @@ -0,0 +1,46 @@ +package io.github.cottonmc.cotton.gui.impl.client; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.text.OrderedText; + +import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment; +import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment; + +public final class TextAlignment { + public static int getTextOffsetX(HorizontalAlignment alignment, int width, OrderedText text) { + return switch (alignment) { + case LEFT -> 0; + + case CENTER -> { + TextRenderer renderer = MinecraftClient.getInstance().textRenderer; + int textWidth = renderer.getWidth(text); + yield width / 2 - textWidth / 2; + } + + case RIGHT -> { + TextRenderer renderer = MinecraftClient.getInstance().textRenderer; + int textWidth = renderer.getWidth(text); + yield width - textWidth; + } + }; + } + + public static int getTextOffsetY(VerticalAlignment alignment, int height, int lines) { + return switch (alignment) { + case TOP -> 0; + + case CENTER -> { + TextRenderer renderer = MinecraftClient.getInstance().textRenderer; + int textHeight = renderer.fontHeight * lines; + yield height / 2 - textHeight / 2; + } + + case BOTTOM -> { + TextRenderer renderer = MinecraftClient.getInstance().textRenderer; + int textHeight = renderer.fontHeight * lines; + yield height - textHeight; + } + }; + } +} diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java index be0b1e4..143435e 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java @@ -3,7 +3,6 @@ package io.github.cottonmc.cotton.gui.widget; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; @@ -13,6 +12,7 @@ import net.minecraft.text.Text; import io.github.cottonmc.cotton.gui.client.ScreenDrawing; import io.github.cottonmc.cotton.gui.impl.client.LibGuiConfig; +import io.github.cottonmc.cotton.gui.impl.client.TextAlignment; import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment; import io.github.cottonmc.cotton.gui.widget.data.InputResult; import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment; @@ -63,13 +63,7 @@ public class WLabel extends WWidget { @Environment(EnvType.CLIENT) @Override public void paint(DrawContext context, int x, int y, int mouseX, int mouseY) { - MinecraftClient mc = MinecraftClient.getInstance(); - TextRenderer renderer = mc.textRenderer; - int yOffset = switch (verticalAlignment) { - case CENTER -> height / 2 - renderer.fontHeight / 2; - case BOTTOM -> height - renderer.fontHeight; - case TOP -> 0; - }; + int yOffset = TextAlignment.getTextOffsetY(verticalAlignment, height, 1); ScreenDrawing.drawString(context, text.asOrderedText(), horizontalAlignment, x, y + yOffset, this.getWidth(), shouldRenderInDarkMode() ? darkmodeColor : color); @@ -102,7 +96,8 @@ public class WLabel extends WWidget { @Nullable public Style getTextStyleAt(int x, int y) { if (isWithinBounds(x, y)) { - return MinecraftClient.getInstance().textRenderer.getTextHandler().getStyleAt(text, x); + int xOffset = TextAlignment.getTextOffsetX(horizontalAlignment, width, text.asOrderedText()); + return MinecraftClient.getInstance().textRenderer.getTextHandler().getStyleAt(text, x - xOffset); } return null; } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java index 2b4ad31..b2a44eb 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java @@ -12,6 +12,7 @@ import net.minecraft.text.Style; import net.minecraft.text.Text; import io.github.cottonmc.cotton.gui.client.ScreenDrawing; +import io.github.cottonmc.cotton.gui.impl.client.TextAlignment; import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment; import io.github.cottonmc.cotton.gui.widget.data.InputResult; import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment; @@ -73,11 +74,13 @@ public class WText extends WWidget { @Nullable public Style getTextStyleAt(int x, int y) { TextRenderer font = MinecraftClient.getInstance().textRenderer; - int lineIndex = y / font.fontHeight; + int yOffset = TextAlignment.getTextOffsetY(verticalAlignment, height, wrappedLines.size()); + int lineIndex = (y - yOffset) / font.fontHeight; if (lineIndex >= 0 && lineIndex < wrappedLines.size()) { OrderedText line = wrappedLines.get(lineIndex); - return font.getTextHandler().getStyleAt(line, x); + int xOffset = TextAlignment.getTextOffsetX(horizontalAlignment, width, line); + return font.getTextHandler().getStyleAt(line, x - xOffset); } return null; @@ -92,12 +95,7 @@ public class WText extends WWidget { } TextRenderer font = MinecraftClient.getInstance().textRenderer; - - int yOffset = switch (verticalAlignment) { - case CENTER -> height / 2 - font.fontHeight * wrappedLines.size() / 2; - case BOTTOM -> height - font.fontHeight * wrappedLines.size(); - case TOP -> 0; - }; + int yOffset = TextAlignment.getTextOffsetY(verticalAlignment, height, wrappedLines.size()); for (int i = 0; i < wrappedLines.size(); i++) { OrderedText line = wrappedLines.get(i); diff --git a/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java b/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java index a9500ae..8d44715 100644 --- a/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java +++ b/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java @@ -69,6 +69,7 @@ public class LibGuiTestClient implements ClientModInitializer { .then(literal("darkmode").executes(openScreen(client -> new DarkModeTestGui()))) .then(literal("titlealignment").executes(openScreen(Text.literal("test title"), client -> new TitleAlignmentTestGui()))) .then(literal("texture").executes(openScreen(client -> new TextureTestGui()))) + .then(literal("textalignment").executes(openScreen(client -> new TextAlignmentTestGui()))) )); } diff --git a/src/testMod/java/io/github/cottonmc/test/client/TextAlignmentTestGui.java b/src/testMod/java/io/github/cottonmc/test/client/TextAlignmentTestGui.java new file mode 100644 index 0000000..600bf9f --- /dev/null +++ b/src/testMod/java/io/github/cottonmc/test/client/TextAlignmentTestGui.java @@ -0,0 +1,75 @@ +package io.github.cottonmc.test.client; + +import net.minecraft.text.HoverEvent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription; +import io.github.cottonmc.cotton.gui.widget.WGridPanel; +import io.github.cottonmc.cotton.gui.widget.WLabel; +import io.github.cottonmc.cotton.gui.widget.WLabeledSlider; +import io.github.cottonmc.cotton.gui.widget.WTabPanel; +import io.github.cottonmc.cotton.gui.widget.WText; +import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment; +import io.github.cottonmc.cotton.gui.widget.data.Insets; +import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment; + +import java.util.function.Consumer; +import java.util.stream.IntStream; + +public final class TextAlignmentTestGui extends LightweightGuiDescription { + public TextAlignmentTestGui() { + WTabPanel tabPanel = new WTabPanel(); + + WGridPanel labelPanel = new WGridPanel(); + labelPanel.setInsets(Insets.ROOT_PANEL); + labelPanel.setGaps(0, 1); + Text labelStyled = Text.literal("world") + .styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of("test")))); + Text labelText = Text.literal("hello, ").append(labelStyled); + WLabel label = new WLabel(labelText); + WLabeledSlider labelSliderH = forEnum(HorizontalAlignment.class, label::setHorizontalAlignment); + WLabeledSlider labelSliderV = forEnum(VerticalAlignment.class, label::setVerticalAlignment); + labelPanel.add(label, 0, 0, 5, 3); + labelPanel.add(labelSliderH, 0, 3, 5, 1); + labelPanel.add(labelSliderV, 0, 4, 5, 1); + + WGridPanel textPanel = new WGridPanel(); + textPanel.setInsets(Insets.ROOT_PANEL); + textPanel.setGaps(0, 1); + Text textText = IntStream.rangeClosed(1, 3) + .mapToObj(line -> { + Text textStyled = Text.literal("world").styled(style -> style + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of("test"))) + .withColor(Formatting.values()[line + 9]) + ); + return Text.literal("hell" + "o".repeat(line * 3) + ", ").append(textStyled).append("\n"); + }) + .reduce(Text.empty(), MutableText::append); + WText text = new WText(textText); + WLabeledSlider textSliderH = forEnum(HorizontalAlignment.class, text::setHorizontalAlignment); + WLabeledSlider textSliderV = forEnum(VerticalAlignment.class, text::setVerticalAlignment); + textPanel.add(text, 0, 0, 5, 4); + textPanel.add(textSliderH, 0, 4, 5, 1); + textPanel.add(textSliderV, 0, 5, 5, 1); + + tabPanel.add(labelPanel, builder -> builder.title(Text.of("WLabel"))); + tabPanel.add(textPanel, builder -> builder.title(Text.of("WText"))); + setRootPanel(tabPanel); + tabPanel.validate(this); + } + + private static > WLabeledSlider forEnum(Class type, Consumer consumer) { + E[] values = type.getEnumConstants(); + var slider = new WLabeledSlider(1, values.length); + slider.setLabel(Text.of(type.getSimpleName() + ": " + values[0])); + slider.setLabelUpdater(value -> Text.of(type.getSimpleName() + ": " + values[value - 1])); + slider.setValueChangeListener(value -> consumer.accept(values[value - 1])); + return slider; + } + + @Override + public void addPainters() { + } +} -- cgit