From 0fe5d8c924508137b80eb5ba748367f163b0ebd1 Mon Sep 17 00:00:00 2001 From: Zorbatron <46525467+Zorbatron@users.noreply.github.com> Date: Thu, 18 Dec 2025 22:20:12 -0500 Subject: [PATCH] Make the alignment, shadow, and scale of StyledText/TextWidgets a supplier --- .../modularui/animation/Animator.java | 2 +- .../modularui/api/drawable/IKey.java | 32 +++++--- .../modularui/drawable/text/AnimatedText.java | 38 +--------- .../modularui/drawable/text/BaseKey.java | 15 ++-- .../modularui/drawable/text/CompoundKey.java | 6 +- .../modularui/drawable/text/DynamicKey.java | 2 +- .../modularui/drawable/text/LangKey.java | 2 +- .../modularui/drawable/text/StringKey.java | 4 +- .../modularui/drawable/text/StyledText.java | 73 ++++++++++++------ .../cleanroommc/modularui/test/TestGuis.java | 75 +++++++++++++++++++ .../modularui/widgets/TextWidget.java | 59 +++++++++++---- 11 files changed, 210 insertions(+), 98 deletions(-) diff --git a/src/main/java/com/cleanroommc/modularui/animation/Animator.java b/src/main/java/com/cleanroommc/modularui/animation/Animator.java index 17a844b61..34b6b633d 100644 --- a/src/main/java/com/cleanroommc/modularui/animation/Animator.java +++ b/src/main/java/com/cleanroommc/modularui/animation/Animator.java @@ -150,7 +150,7 @@ public Animator bounds(float min, float max) { /** * The duration of this animation in milliseconds. Note this is not 100% accurate. - * Usually it's plus minus 2ms, but can rarely be more. + * Usually it's ±2ms, but can rarely be more. * * @param duration duration in milliseconds * @return this diff --git a/src/main/java/com/cleanroommc/modularui/api/drawable/IKey.java b/src/main/java/com/cleanroommc/modularui/api/drawable/IKey.java index 96c1d796f..d883b05f4 100644 --- a/src/main/java/com/cleanroommc/modularui/api/drawable/IKey.java +++ b/src/main/java/com/cleanroommc/modularui/api/drawable/IKey.java @@ -14,6 +14,7 @@ import com.cleanroommc.modularui.screen.viewport.GuiContext; import com.cleanroommc.modularui.theme.WidgetTheme; import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.utils.FloatSupplier; import com.cleanroommc.modularui.utils.JsonHelper; import com.cleanroommc.modularui.widgets.TextWidget; @@ -25,6 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.function.BooleanSupplier; import java.util.function.IntSupplier; import java.util.function.Supplier; @@ -242,15 +244,15 @@ default int getDefaultHeight() { } default float getScale() { - return 1f; + return 1.0f; } default TextWidget asWidget() { return new TextWidget<>(this); } - default StyledText withStyle() { - return new StyledText(this); + default StyledText withStyle() { + return new StyledText<>(this); } default AnimatedText withAnimation() { @@ -284,23 +286,35 @@ default IKey removeFormatColor() { IKey removeStyle(); - default StyledText alignment(Alignment alignment) { + default StyledText alignment(@Nullable Alignment alignment) { return withStyle().alignment(alignment); } - default StyledText color(int color) { + default StyledText alignment(@Nullable Supplier<@NotNull Alignment> alignment) { + return withStyle().alignment(alignment); + } + + default StyledText color(int color) { return withStyle().color(() -> color); } - default StyledText color(@Nullable IntSupplier color) { + default StyledText color(@Nullable IntSupplier color) { return withStyle().color(color); } - default StyledText scale(float scale) { + default StyledText scale(float scale) { return withStyle().scale(scale); } - default StyledText shadow(@Nullable Boolean shadow) { + default StyledText scale(@Nullable FloatSupplier scale) { + return withStyle().scale(scale); + } + + default StyledText shadow(@Nullable Boolean shadow) { + return withStyle().shadow(shadow); + } + + default StyledText shadow(@Nullable BooleanSupplier shadow) { return withStyle().shadow(shadow); } @@ -316,7 +330,7 @@ default KeyIcon asTextIcon() { @Override default void loadFromJson(JsonObject json) { if (json.has("color") || json.has("shadow") || json.has("align") || json.has("alignment") || json.has("scale")) { - StyledText styledText = this instanceof StyledText styledText1 ? styledText1 : withStyle(); + StyledText styledText = this instanceof StyledText styledText1 ? styledText1 : withStyle(); if (json.has("color")) { styledText.color(JsonHelper.getInt(json, 0, "color")); } diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/AnimatedText.java b/src/main/java/com/cleanroommc/modularui/drawable/text/AnimatedText.java index 2c7999e67..488645fbf 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/AnimatedText.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/AnimatedText.java @@ -3,18 +3,12 @@ import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.screen.viewport.GuiContext; import com.cleanroommc.modularui.theme.WidgetTheme; -import com.cleanroommc.modularui.utils.Alignment; import net.minecraft.client.Minecraft; -import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import org.jetbrains.annotations.Nullable; - -import java.util.function.IntSupplier; - -public class AnimatedText extends StyledText { +public class AnimatedText extends StyledText { private String fullString; private String currentString = ""; @@ -104,36 +98,6 @@ public AnimatedText forward(boolean forward) { return this; } - @Override - public AnimatedText style(TextFormatting formatting) { - return (AnimatedText) super.style(formatting); - } - - @Override - public AnimatedText alignment(Alignment alignment) { - return (AnimatedText) super.alignment(alignment); - } - - @Override - public AnimatedText color(int color) { - return color(() -> color); - } - - @Override - public AnimatedText color(@Nullable IntSupplier color) { - return (AnimatedText) super.color(color); - } - - @Override - public AnimatedText scale(float scale) { - return (AnimatedText) super.scale(scale); - } - - @Override - public AnimatedText shadow(@Nullable Boolean shadow) { - return (AnimatedText) super.shadow(shadow); - } - /** * How fast the characters appear * diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/BaseKey.java b/src/main/java/com/cleanroommc/modularui/drawable/text/BaseKey.java index 1f1f12d1b..a30d1faec 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/BaseKey.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/BaseKey.java @@ -7,7 +7,7 @@ import org.apache.commons.lang3.NotImplementedException; import org.jetbrains.annotations.Nullable; -public abstract class BaseKey implements IKey { +public abstract class BaseKey> implements IKey { private FormattingState formatting; @@ -17,21 +17,21 @@ public String getFormatted(@Nullable FormattingState parentFormatting) { } @Override - public BaseKey style(@Nullable TextFormatting formatting) { + public K style(@Nullable TextFormatting formatting) { if (this.formatting == null) { this.formatting = new FormattingState(); } if (formatting == null) this.formatting.forceDefaultColor(); else this.formatting.add(formatting, false); - return this; + return getThis(); } @Override - public IKey removeStyle() { + public K removeStyle() { if (this.formatting != null) { this.formatting.reset(); } - return this; + return getThis(); } @Override @@ -39,6 +39,11 @@ public IKey removeStyle() { return formatting; } + @SuppressWarnings("unchecked") + public K getThis() { + return (K) this; + } + @Override public String toString() { return getFormatted(); diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/CompoundKey.java b/src/main/java/com/cleanroommc/modularui/drawable/text/CompoundKey.java index 21e3aef87..99cc74788 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/CompoundKey.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/CompoundKey.java @@ -2,11 +2,9 @@ import com.cleanroommc.modularui.api.drawable.IKey; -import net.minecraft.util.text.TextFormatting; - import org.jetbrains.annotations.Nullable; -public class CompoundKey extends BaseKey { +public class CompoundKey extends BaseKey { private static final IKey[] EMPTY = new IKey[0]; @@ -43,4 +41,4 @@ private String toString(boolean formatted, @Nullable FormattingState parentForma public IKey[] getKeys() { return this.keys; } -} \ No newline at end of file +} diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/DynamicKey.java b/src/main/java/com/cleanroommc/modularui/drawable/text/DynamicKey.java index ba6b1a3b9..f4f53364d 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/DynamicKey.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/DynamicKey.java @@ -6,7 +6,7 @@ import java.util.function.Supplier; -public class DynamicKey extends BaseKey { +public class DynamicKey extends BaseKey { private final Supplier supplier; diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/LangKey.java b/src/main/java/com/cleanroommc/modularui/drawable/text/LangKey.java index 377747711..f9c55c880 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/LangKey.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/LangKey.java @@ -10,7 +10,7 @@ import java.util.Objects; import java.util.function.Supplier; -public class LangKey extends BaseKey { +public class LangKey extends BaseKey { private final Supplier keySupplier; private final Supplier argsSupplier; diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/StringKey.java b/src/main/java/com/cleanroommc/modularui/drawable/text/StringKey.java index da539a46f..1b269f8d7 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/StringKey.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/StringKey.java @@ -4,7 +4,7 @@ import java.util.Objects; -public class StringKey extends BaseKey { +public class StringKey extends BaseKey { private final String string; private final Object[] args; @@ -29,4 +29,4 @@ public String getFormatted(@Nullable FormattingState parentFormatting) { String text = FontRenderHelper.formatArgs(this.args, FormattingState.merge(parentFormatting, getFormatting()), this.string, false); return FontRenderHelper.format(getFormatting(), parentFormatting, text); } -} \ No newline at end of file +} diff --git a/src/main/java/com/cleanroommc/modularui/drawable/text/StyledText.java b/src/main/java/com/cleanroommc/modularui/drawable/text/StyledText.java index beeaff8c2..aed2400c9 100644 --- a/src/main/java/com/cleanroommc/modularui/drawable/text/StyledText.java +++ b/src/main/java/com/cleanroommc/modularui/drawable/text/StyledText.java @@ -4,23 +4,31 @@ import com.cleanroommc.modularui.screen.viewport.GuiContext; import com.cleanroommc.modularui.theme.WidgetTheme; import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.utils.FloatSupplier; import com.cleanroommc.modularui.widgets.TextWidget; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.function.BooleanSupplier; import java.util.function.IntSupplier; +import java.util.function.Supplier; -public class StyledText extends BaseKey { +public class StyledText> extends BaseKey { private final IKey key; - private Alignment alignment = Alignment.Center; + @NotNull + private Supplier<@NotNull Alignment> alignment = () -> Alignment.Center; + @Nullable private IntSupplier color = null; - private Boolean shadow = null; - private float scale = 1f; + @Nullable + private BooleanSupplier shadow = null; + @Nullable + private FloatSupplier scale = null; public StyledText(IKey key) { this.key = key; @@ -39,16 +47,16 @@ public String getFormatted() { @SideOnly(Side.CLIENT) @Override public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) { - renderer.setAlignment(this.alignment, width, height); + renderer.setAlignment(getAlignment(), width, height); renderer.setColor(this.color != null ? this.color.getAsInt() : widgetTheme.getTextColor()); - renderer.setScale(this.scale); + renderer.setScale(getScale()); renderer.setPos(x, y); - renderer.setShadow(this.shadow != null ? this.shadow : widgetTheme.getTextShadow()); + renderer.setShadow(this.shadow != null ? this.shadow.getAsBoolean() : widgetTheme.getTextShadow()); renderer.draw(getFormatted()); } - public Alignment getAlignment() { - return this.alignment; + public @NotNull Alignment getAlignment() { + return this.alignment.get(); } public @Nullable IntSupplier getColor() { @@ -57,46 +65,65 @@ public Alignment getAlignment() { @Override public float getScale() { - return this.scale; + return this.scale == null ? super.getScale() : this.scale.getAsFloat(); } public @Nullable Boolean isShadow() { - return this.shadow; + return this.shadow == null ? null : this.shadow.getAsBoolean(); } @Override - public BaseKey style(TextFormatting formatting) { + public K style(TextFormatting formatting) { this.key.style(formatting); - return this; + return getThis(); } @Override - public StyledText alignment(Alignment alignment) { - this.alignment = alignment; - return this; + public K alignment(@Nullable Alignment alignment) { + return alignment(alignment == null ? null : () -> alignment); } @Override - public StyledText color(int color) { + public K alignment(@Nullable Supplier<@NotNull Alignment> alignment) { + this.alignment = alignment == null ? () -> Alignment.Center : alignment; + return getThis(); + } + + @Override + public K color(int color) { return color(() -> color); } @Override - public StyledText color(@Nullable IntSupplier color) { + public K color(@Nullable IntSupplier color) { this.color = color; - return this; + return getThis(); } @Override - public StyledText scale(float scale) { + public K scale(float scale) { + return scale(() -> scale); + } + + public K scale(@Nullable FloatSupplier scale) { this.scale = scale; - return this; + return getThis(); + } + + @Override + public K shadow(@Nullable Boolean shadow) { + if (shadow == null) { + return shadow((BooleanSupplier) null); + } else { + boolean hasShadow = shadow; + return shadow(() -> hasShadow); + } } @Override - public StyledText shadow(@Nullable Boolean shadow) { + public K shadow(@Nullable BooleanSupplier shadow) { this.shadow = shadow; - return this; + return getThis(); } @Override diff --git a/src/main/java/com/cleanroommc/modularui/test/TestGuis.java b/src/main/java/com/cleanroommc/modularui/test/TestGuis.java index c2c33dbc7..e48116191 100644 --- a/src/main/java/com/cleanroommc/modularui/test/TestGuis.java +++ b/src/main/java/com/cleanroommc/modularui/test/TestGuis.java @@ -17,6 +17,7 @@ import com.cleanroommc.modularui.drawable.SpriteDrawable; import com.cleanroommc.modularui.drawable.UITexture; import com.cleanroommc.modularui.drawable.graph.GraphDrawable; +import com.cleanroommc.modularui.drawable.text.StyledText; import com.cleanroommc.modularui.factory.ClientGUI; import com.cleanroommc.modularui.screen.CustomModularScreen; import com.cleanroommc.modularui.screen.ModularPanel; @@ -79,6 +80,7 @@ import java.util.Comparator; import java.util.List; import java.util.Random; +import java.util.function.Supplier; public class TestGuis extends CustomModularScreen { @@ -567,6 +569,79 @@ public static ModularPanel buildCollapseDisabledChildrenUI() { .overlay(); } + public static @NotNull ModularPanel buildStyledTextUI() { + Animator alignmentAnimator = new Animator() + .bounds(0.0f, 8.0f) + .curve(Interpolation.LINEAR) + .repeatsOnFinish(-1) + .duration(8000); + + Supplier alignmentSupplier = () -> { + float val = alignmentAnimator.getValue(); + if (val > 7) { + return Alignment.BottomLeft; + } else if (val > 6) { + return Alignment.BottomCenter; + } else if (val > 5) { + return Alignment.BottomRight; + } else if (val > 4) { + return Alignment.CenterRight; + } else if (val > 3) { + return Alignment.TopRight; + } else if (val > 2) { + return Alignment.TopCenter; + } else if (val > 1) { + return Alignment.TopLeft; + } + + return Alignment.CenterLeft; + }; + + alignmentAnimator.reset(); + alignmentAnimator.animate(); + + Animator colorAnimator = new Animator() + .bounds(0.0f, 360.0f) + .curve(Interpolation.LINEAR) + .repeatsOnFinish(-1) + .duration(360 * 5); + + colorAnimator.reset(); + colorAnimator.animate(); + + Animator scaleAnimator = new Animator() + .bounds(1.0f, 2.0f) + .curve(Interpolation.SINE_INOUT) + .reverseOnFinish(true) + .repeatsOnFinish(-1) + .duration(1500); + + scaleAnimator.reset(); + scaleAnimator.animate(); + + Animator shadowAnimator = new Animator() + .bounds(0.0f, 1.0f) + .curve(Interpolation.LINEAR) + .repeatsOnFinish(-1) + .duration(750); + + shadowAnimator.reset(); + shadowAnimator.animate(); + + StyledText key = IKey.str("Hello, World!") + .alignment(alignmentSupplier) + .color(() -> Color.ofHSV(colorAnimator.getValue(), 1.0f, 1.0f)) + .scale(scaleAnimator::getValue) + .shadow(() -> shadowAnimator.getValue() > 0.5f); + + return new ModularPanel("StyledText") + .size(150) + .child(key.asWidget() + .margin(4) + .align(Alignment.CENTER) + .full()); + } + private static class TestPanel extends ModularPanel { public TestPanel(String name) { diff --git a/src/main/java/com/cleanroommc/modularui/widgets/TextWidget.java b/src/main/java/com/cleanroommc/modularui/widgets/TextWidget.java index 6fc0dca79..eb0cd6556 100644 --- a/src/main/java/com/cleanroommc/modularui/widgets/TextWidget.java +++ b/src/main/java/com/cleanroommc/modularui/widgets/TextWidget.java @@ -6,24 +6,32 @@ import com.cleanroommc.modularui.theme.WidgetTheme; import com.cleanroommc.modularui.theme.WidgetThemeEntry; import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.utils.FloatSupplier; import com.cleanroommc.modularui.widget.Widget; import com.cleanroommc.modularui.widget.WidgetTree; import com.cleanroommc.modularui.widget.sizer.Box; import net.minecraft.util.text.TextFormatting; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Objects; +import java.util.function.BooleanSupplier; import java.util.function.IntSupplier; +import java.util.function.Supplier; public class TextWidget> extends Widget { private final IKey key; - private Alignment alignment = Alignment.CenterLeft; + @NotNull + private Supplier<@NotNull Alignment> alignment = () -> Alignment.Center; + @Nullable private IntSupplier color = null; - private Boolean shadow = null; - private float scale = 1f; + @Nullable + private BooleanSupplier shadow = null; + @Nullable + private FloatSupplier scale = null; private int maxWidth = -1; private String lastText = null; @@ -43,10 +51,10 @@ public void draw(ModularGuiContext context, WidgetThemeEntry widgetTheme) { String text = checkString(); WidgetTheme theme = getActiveWidgetTheme(widgetTheme, isHovering()); renderer.setColor(this.color != null ? this.color.getAsInt() : theme.getTextColor()); - renderer.setAlignment(this.alignment, getArea().paddedWidth() + this.scale, getArea().paddedHeight()); - renderer.setShadow(this.shadow != null ? this.shadow : theme.getTextShadow()); + renderer.setAlignment(getAlignment(), getArea().paddedWidth() + getScale(), getArea().paddedHeight()); + renderer.setShadow(this.shadow != null ? this.shadow.getAsBoolean() : theme.getTextShadow()); renderer.setPos(getArea().getPadding().getLeft(), getArea().getPadding().getTop()); - renderer.setScale(this.scale); + renderer.setScale(getScale()); renderer.setSimulate(false); renderer.draw(text); } @@ -70,7 +78,7 @@ private TextRenderer simulate(float maxWidth) { TextRenderer renderer = TextRenderer.SHARED; renderer.setAlignment(Alignment.TopLeft, maxWidth); renderer.setPos(padding.getLeft(), padding.getTop()); - renderer.setScale(this.scale); + renderer.setScale(getScale()); renderer.setSimulate(true); renderer.draw(getTextForDefaultSize()); renderer.setSimulate(false); @@ -81,11 +89,11 @@ private TextRenderer simulate(float maxWidth) { public int getDefaultHeight() { float maxWidth; if (resizer().isWidthCalculated()) { - maxWidth = getArea().width + this.scale; + maxWidth = getArea().width + getScale(); } else if (this.maxWidth > 0) { maxWidth = Math.max(this.maxWidth, 5); } else if (getParent().resizer().isWidthCalculated()) { - maxWidth = getParent().getArea().width + this.scale; + maxWidth = getParent().getArea().width + getScale(); } else { maxWidth = getScreen().getScreenArea().width; } @@ -143,24 +151,32 @@ public IKey getKey() { return this.key; } - public Alignment getAlignment() { - return this.alignment; + public @NotNull Alignment getAlignment() { + return this.alignment.get(); } - public float getScale() { + public @Nullable FloatSupplier getScaleSupplier() { return this.scale; } + public float getScale() { + return this.scale == null ? 1.0f : this.scale.getAsFloat(); + } + public @Nullable IntSupplier getColor() { return this.color; } public @Nullable Boolean isShadow() { - return this.shadow; + return this.shadow == null ? null : this.shadow.getAsBoolean(); + } + + public W alignment(@Nullable Alignment alignment) { + return alignment(alignment == null ? null : () -> alignment); } - public W alignment(Alignment alignment) { - this.alignment = alignment; + public W alignment(@Nullable Supplier<@NotNull Alignment> alignment) { + this.alignment = alignment == null ? () -> Alignment.Center : alignment; return getThis(); } @@ -174,11 +190,24 @@ public W color(@Nullable IntSupplier color) { } public W scale(float scale) { + return scale(() -> scale); + } + + public W scale(@Nullable FloatSupplier scale) { this.scale = scale; return getThis(); } public W shadow(@Nullable Boolean shadow) { + if (shadow == null) { + return shadow((BooleanSupplier) null); + } else { + boolean hasShadow = shadow; + return shadow(() -> hasShadow); + } + } + + public W shadow(@Nullable BooleanSupplier shadow) { this.shadow = shadow; return getThis(); }