diff options
author | syeyoung <cyoung06@naver.com> | 2023-01-20 16:52:54 +0900 |
---|---|---|
committer | syeyoung <cyoung06@naver.com> | 2023-01-20 16:52:54 +0900 |
commit | a5726156d3941d5b6b6c9c6a968212297fd112c4 (patch) | |
tree | 78089f2b72b8ece409d3bbca7b902c7c599f5882 /mod | |
parent | e1cdaf7b769abc115f2c2eb569c2bae775b2ede9 (diff) | |
download | Skyblock-Dungeons-Guide-a5726156d3941d5b6b6c9c6a968212297fd112c4.tar.gz Skyblock-Dungeons-Guide-a5726156d3941d5b6b6c9c6a968212297fd112c4.tar.bz2 Skyblock-Dungeons-Guide-a5726156d3941d5b6b6c9c6a968212297fd112c4.zip |
- Do not post events asynchronously
- Text HUD Features now use rich text!!
- FASSSSSTTTT rendering
Signed-off-by: syeyoung <cyoung06@naver.com>
Diffstat (limited to 'mod')
18 files changed, 753 insertions, 204 deletions
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/location/GuiGuiLocationConfig.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/location/GuiGuiLocationConfig.java index ca15128d..0f0846b5 100755 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/location/GuiGuiLocationConfig.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/location/GuiGuiLocationConfig.java @@ -19,6 +19,7 @@ package kr.syeyoung.dungeonsguide.mod.config.guiconfig.location; import kr.syeyoung.dungeonsguide.mod.features.AbstractFeature; +import kr.syeyoung.dungeonsguide.mod.features.AbstractHUDFeature; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.mod.features.GuiFeature; import kr.syeyoung.dungeonsguide.mod.gui.MGui; @@ -56,8 +57,8 @@ public class GuiGuiLocationConfig extends MGui { public GuiGuiLocationConfig(final GuiScreen before, AbstractFeature featureWhitelist) { this.before = before; for (AbstractFeature feature : FeatureRegistry.getFeatureList()) { - if (feature instanceof GuiFeature && feature.isEnabled()) { - getMainPanel().add(new PanelDelegate((GuiFeature) feature, featureWhitelist == null || feature == featureWhitelist, this)); + if (feature instanceof AbstractHUDFeature && feature.isEnabled()) { + getMainPanel().add(new PanelDelegate((AbstractHUDFeature) feature, featureWhitelist == null || feature == featureWhitelist, this)); } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/location/PanelDelegate.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/location/PanelDelegate.java index 28cea414..6b639749 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/location/PanelDelegate.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/location/PanelDelegate.java @@ -20,6 +20,7 @@ package kr.syeyoung.dungeonsguide.mod.config.guiconfig.location; import kr.syeyoung.dungeonsguide.mod.config.types.GUIRectangle; +import kr.syeyoung.dungeonsguide.mod.features.AbstractHUDFeature; import kr.syeyoung.dungeonsguide.mod.features.GuiFeature; import kr.syeyoung.dungeonsguide.mod.gui.MPanel; import kr.syeyoung.dungeonsguide.mod.gui.elements.MPopupMenu; @@ -41,12 +42,12 @@ import java.util.List; import java.util.*; public class PanelDelegate extends MPanel { - private final GuiFeature guiFeature; + private final AbstractHUDFeature guiFeature; private boolean draggable = false; private GuiGuiLocationConfig guiGuiLocationConfig; private Set<Marker> markerSet = new HashSet<>(); - public PanelDelegate(GuiFeature guiFeature, boolean draggable, GuiGuiLocationConfig guiGuiLocationConfig) { + public PanelDelegate(AbstractHUDFeature guiFeature, boolean draggable, GuiGuiLocationConfig guiGuiLocationConfig) { this.guiFeature = guiFeature; this.draggable = draggable; this.guiGuiLocationConfig = guiGuiLocationConfig; diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java index 1f638faf..601783cd 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java @@ -34,6 +34,7 @@ import kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer.Reply; import kr.syeyoung.dungeonsguide.mod.party.PartyContext; import kr.syeyoung.dungeonsguide.mod.party.PartyManager; import lombok.Getter; +import net.minecraft.client.Minecraft; import net.minecraftforge.common.MinecraftForge; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; @@ -133,7 +134,9 @@ public class DiscordIntegrationManager implements IPCListener { JSONObject data = packet.getJson().getJSONObject("data"); JDiscordRelation relation = JDiscordRelation.parse(data); JDiscordRelation old = relationMap.put(relation.getDiscordUser().getIdLong(), relation); - MinecraftForge.EVENT_BUS.post(new DiscordUserUpdateEvent(old, relation)); + Minecraft.getMinecraft().addScheduledTask(() -> { + MinecraftForge.EVENT_BUS.post(new DiscordUserUpdateEvent(old, relation)); + }); } private void onActivityJoinRequest(Packet packet) { JSONObject data = packet.getJson().getJSONObject("data"); @@ -145,27 +148,31 @@ public class DiscordIntegrationManager implements IPCListener { .getString("id")), data.getJSONObject("user") .getString("avatar")); - MinecraftForge.EVENT_BUS.post(new DiscordUserJoinRequestEvent(user)); + Minecraft.getMinecraft().addScheduledTask(() -> { + MinecraftForge.EVENT_BUS.post(new DiscordUserJoinRequestEvent(user)); + }); } private void onActivityInvite(Packet packet) { JSONObject data = packet.getJson().getJSONObject("data"); if (!data.getJSONObject("activity").getString("application_id").equals("816298079732498473")) return; - MinecraftForge.EVENT_BUS.post(new DiscordUserInvitedEvent( - new User(data.getJSONObject("user") - .getString("username"), - data.getJSONObject("user") - .getString("discriminator"), - Long.parseUnsignedLong(data.getJSONObject("user") - .getString("id")), - data.getJSONObject("user") - .getString("avatar")), - new InviteHandle( - data.getJSONObject("user").getString("id"), - data.getJSONObject("activity").getString("session_id"), - data.getString("channel_id"), - data.getString("message_id") - ))); + Minecraft.getMinecraft().addScheduledTask(() -> { + MinecraftForge.EVENT_BUS.post(new DiscordUserInvitedEvent( + new User(data.getJSONObject("user") + .getString("username"), + data.getJSONObject("user") + .getString("discriminator"), + Long.parseUnsignedLong(data.getJSONObject("user") + .getString("id")), + data.getJSONObject("user") + .getString("avatar")), + new InviteHandle( + data.getJSONObject("user").getString("id"), + data.getJSONObject("activity").getString("session_id"), + data.getString("channel_id"), + data.getString("message_id") + ))); + }); } private void onRelationshipLoad(Packet object) { diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractGuiFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractGuiFeature.java index c8112dbe..420b1329 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractGuiFeature.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractGuiFeature.java @@ -39,15 +39,18 @@ public abstract class AbstractGuiFeature extends AbstractFeature { private boolean wasVisible = false; private OverlayWidget widget; public OverlayWidget getWidget() { - if (widget == null) widget = instantiateWidget(); + if (widget == null || widget.wrappingWidget == null) widget = instantiateWidget(); + if (widget.wrappingWidget == null) return null; return widget; } public void checkVisibility() { boolean shouldBeVisible = isVisible(); + OverlayWidget widget = getWidget(); + if (widget == null) return; if (!wasVisible && shouldBeVisible) { - OverlayManager.getInstance().addOverlay(getWidget()); + OverlayManager.getInstance().addOverlay(widget); } else if (wasVisible && !shouldBeVisible) { - OverlayManager.getInstance().removeOverlay(getWidget()); + OverlayManager.getInstance().removeOverlay(widget); } wasVisible = shouldBeVisible; } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractHUDFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractHUDFeature.java new file mode 100644 index 00000000..55c6499c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractHUDFeature.java @@ -0,0 +1,141 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.features; + +import com.google.gson.JsonObject; +import kr.syeyoung.dungeonsguide.mod.config.guiconfig.GuiConfigV2; +import kr.syeyoung.dungeonsguide.mod.config.guiconfig.location.GuiGuiLocationConfig; +import kr.syeyoung.dungeonsguide.mod.config.types.GUIRectangle; +import kr.syeyoung.dungeonsguide.mod.config.types.TypeConverterRegistry; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MPassiveLabelAndElement; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MToggleButton; +import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement; +import kr.syeyoung.dungeonsguide.mod.guiv2.Widget; +import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter; +import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.ConstraintBox; +import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect; +import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size; +import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.Renderer; +import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.RenderingContext; +import kr.syeyoung.dungeonsguide.mod.overlay.OverlayType; +import kr.syeyoung.dungeonsguide.mod.overlay.OverlayWidget; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Getter +public abstract class AbstractHUDFeature extends AbstractGuiFeature { + private GUIRectangle featureRect; + + public void setFeatureRect(GUIRectangle featureRect) { + this.featureRect = featureRect; + updatePosition(); + } + + @Setter(value = AccessLevel.PROTECTED) + private boolean keepRatio; + @Setter(value = AccessLevel.PROTECTED) + private double defaultWidth; + @Setter(value = AccessLevel.PROTECTED) + private double defaultHeight; + private final double defaultRatio; + + protected AbstractHUDFeature(String category, String name, String description, String key, boolean keepRatio, int width, int height) { + super(category, name, description, key); + this.keepRatio = keepRatio; + this.defaultWidth = width; + this.defaultHeight = height; + this.defaultRatio = defaultWidth / defaultHeight; + this.featureRect = new GUIRectangle(0, 0, width, height); + } + + + public Rect getWidgetPosition() { + Rectangle loc = featureRect.getRectangleNoScale(); + return new Rect(loc.x, loc.y, loc.width, loc.height); + } + public abstract void drawDemo(float partialTicks); + + @Override + public void loadConfig(JsonObject jsonObject) { + super.loadConfig(jsonObject); + this.featureRect = TypeConverterRegistry.getTypeConverter("guirect",GUIRectangle.class).deserialize(jsonObject.get("$bounds")); + updatePosition(); + } + + @Override + public JsonObject saveConfig() { + JsonObject object = super.saveConfig(); + object.add("$bounds", TypeConverterRegistry.getTypeConverter("guirect", GUIRectangle.class).serialize(featureRect)); + return object; + } + + public List<MPanel> getTooltipForEditor(GuiGuiLocationConfig guiGuiLocationConfig) { + ArrayList<MPanel> mPanels = new ArrayList<>(); + mPanels.add(new MLabel(){ + { + setText(getName()); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(Minecraft.getMinecraft().fontRendererObj.getStringWidth(getName()), 20); + } + }); + mPanels.add(new MButton() { + { + setText("Edit"); + setOnActionPerformed(() -> { + GuiScreen guiScreen = guiGuiLocationConfig.getBefore(); + if (guiScreen == null) { + guiScreen = new GuiConfigV2(); + } + Minecraft.getMinecraft().displayGuiScreen(guiScreen); + if (guiScreen instanceof GuiConfigV2) { + ((GuiConfigV2) guiScreen).getRootConfigPanel().setCurrentPageAndPushHistory(getEditRoute(((GuiConfigV2) guiScreen).getRootConfigPanel())); + } + }); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(100,20); + } + }); + mPanels.add(new MPassiveLabelAndElement("Enabled", new MToggleButton() {{ + setEnabled(AbstractHUDFeature.this.isEnabled()); + setOnToggle(() ->{ + AbstractHUDFeature.this.setEnabled(isEnabled()); + }); } + })); + return mPanels; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/GuiFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/GuiFeature.java index fba7aa86..d0de4225 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/GuiFeature.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/GuiFeature.java @@ -58,29 +58,10 @@ import java.util.Collections; import java.util.List; @Getter -public abstract class GuiFeature extends AbstractGuiFeature { - private GUIRectangle featureRect; - - public void setFeatureRect(GUIRectangle featureRect) { - this.featureRect = featureRect; - updatePosition(); - } - - @Setter(value = AccessLevel.PROTECTED) - private boolean keepRatio; - @Setter(value = AccessLevel.PROTECTED) - private double defaultWidth; - @Setter(value = AccessLevel.PROTECTED) - private double defaultHeight; - private final double defaultRatio; +public abstract class GuiFeature extends AbstractHUDFeature { protected GuiFeature(String category, String name, String description, String key, boolean keepRatio, int width, int height) { - super(category, name, description, key); - this.keepRatio = keepRatio; - this.defaultWidth = width; - this.defaultHeight = height; - this.defaultRatio = defaultWidth / defaultHeight; - this.featureRect = new GUIRectangle(0, 0, width, height); + super(category, name, description, key, keepRatio, width, height); } public class WidgetFeatureWrapper extends Widget implements Renderer, Layouter { @@ -104,15 +85,12 @@ public abstract class GuiFeature extends AbstractGuiFeature { return new OverlayWidget( new WidgetFeatureWrapper(), OverlayType.UNDER_CHAT, - () -> { - Rectangle loc = featureRect.getRectangleNoScale(); - return new Rect(loc.x, loc.y, loc.width, loc.height); - } + this::getWidgetPosition ); } public void drawScreen(float partialTicks) { - Rectangle featureRect = this.featureRect.getRectangleNoScale(); + Rectangle featureRect = this.getFeatureRect().getRectangleNoScale(); clip(featureRect.x, featureRect.y, featureRect.width, featureRect.height); GL11.glEnable(GL11.GL_SCISSOR_TEST); drawHUD(partialTicks); @@ -136,59 +114,4 @@ public abstract class GuiFeature extends AbstractGuiFeature { FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; return fr; } - - @Override - public void loadConfig(JsonObject jsonObject) { - super.loadConfig(jsonObject); - this.featureRect = TypeConverterRegistry.getTypeConverter("guirect",GUIRectangle.class).deserialize(jsonObject.get("$bounds")); - updatePosition(); - } - - @Override - public JsonObject saveConfig() { - JsonObject object = super.saveConfig(); - object.add("$bounds", TypeConverterRegistry.getTypeConverter("guirect", GUIRectangle.class).serialize(featureRect)); - return object; - } - - public List<MPanel> getTooltipForEditor(GuiGuiLocationConfig guiGuiLocationConfig) { - ArrayList<MPanel> mPanels = new ArrayList<>(); - mPanels.add(new MLabel(){ - { - setText(getName()); - } - - @Override - public Dimension getPreferredSize() { - return new Dimension(Minecraft.getMinecraft().fontRendererObj.getStringWidth(getName()), 20); - } - }); - mPanels.add(new MButton() { - { - setText("Edit"); - setOnActionPerformed(() -> { - GuiScreen guiScreen = guiGuiLocationConfig.getBefore(); - if (guiScreen == null) { - guiScreen = new GuiConfigV2(); - } - Minecraft.getMinecraft().displayGuiScreen(guiScreen); - if (guiScreen instanceof GuiConfigV2) { - ((GuiConfigV2) guiScreen).getRootConfigPanel().setCurrentPageAndPushHistory(getEditRoute(((GuiConfigV2) guiScreen).getRootConfigPanel())); - } - }); - } - - @Override - public Dimension getPreferredSize() { - return new Dimension(100,20); - } - }); - mPanels.add(new MPassiveLabelAndElement("Enabled", new MToggleButton() {{ - setEnabled(GuiFeature.this.isEnabled()); - setOnToggle(() ->{ - GuiFeature.this.setEnabled(isEnabled()); - }); } - })); - return mPanels; - } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextHUDFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextHUDFeature.java index 73f33898..28143c40 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextHUDFeature.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextHUDFeature.java @@ -26,18 +26,31 @@ import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MParameterEdit; import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel; import kr.syeyoung.dungeonsguide.mod.config.guiconfig.location.GuiGuiLocationConfig; import kr.syeyoung.dungeonsguide.mod.config.types.AColor; +import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler; +import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent; +import kr.syeyoung.dungeonsguide.mod.features.AbstractHUDFeature; import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter; import kr.syeyoung.dungeonsguide.mod.features.GuiFeature; import kr.syeyoung.dungeonsguide.mod.gui.MPanel; import kr.syeyoung.dungeonsguide.mod.gui.elements.MFloatSelectionButton; import kr.syeyoung.dungeonsguide.mod.gui.elements.MPassiveLabelAndElement; import kr.syeyoung.dungeonsguide.mod.gui.elements.MStringSelectionButton; +import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement; +import kr.syeyoung.dungeonsguide.mod.guiv2.Widget; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.BreakWord; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.RichText; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.TextSpan; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles.ITextStyle; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles.ParentDelegatingTextStyle; +import kr.syeyoung.dungeonsguide.mod.overlay.OverlayType; +import kr.syeyoung.dungeonsguide.mod.overlay.OverlayWidget; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.GlStateManager; import java.util.*; -public abstract class TextHUDFeature extends GuiFeature implements StyledTextProvider { +public abstract class TextHUDFeature extends AbstractHUDFeature implements StyledTextProvider { protected TextHUDFeature(String category, String name, String description, String key, boolean keepRatio, int width, int height) { super(category, name, description, key, keepRatio, width, height); addParameter("textStylesNEW", new FeatureParameter<List<TextStyle>>("textStylesNEW", "", "", new ArrayList<TextStyle>(), "list_textStyle")); @@ -46,23 +59,55 @@ public abstract class TextHUDFeature extends GuiFeature implements StyledTextPro } @Override - public void drawHUD(float partialTicks) { - if (isHUDViewable()) { - List<StyledText> asd = getText(); - - double scale = 1; - if (doesScaleWithHeight()) { - FontRenderer fr = getFontRenderer(); - scale = getFeatureRect().getRectangle().getHeight() / (fr.FONT_HEIGHT* countLines(asd)); - } else { - scale = this.<Float>getParameter("scale").getValue(); + public boolean isVisible() { + return super.isVisible() && isHUDViewable(); + } + + private final RichText richText = new RichText(new TextSpan( + ParentDelegatingTextStyle.ofDefault(), + "" + ), BreakWord.WORD, true, RichText.TextAlign.LEFT); + + @Override + public OverlayWidget instantiateWidget() { + return new OverlayWidget(richText, OverlayType.UNDER_CHAT, this::getWidgetPosition); + } + + private Map<String, ParentDelegatingTextStyle> builtTextStyles = new HashMap<>(); + + @DGEventHandler + public void onTick(DGTickEvent dgTickEvent) { + try { + checkVisibility(); + if (isHUDViewable()) { + List<StyledText> asd = getText(); + + ParentDelegatingTextStyle defaultStyle = ParentDelegatingTextStyle.ofDefault(); + if (doesScaleWithHeight()) { + if (getWidget() == null || getWidget().getDomElement() == null || getWidget().getDomElement().getSize() == null) return; + defaultStyle.setSize(getFeatureRect().getRectangleNoScale().getHeight() / countLines(asd)); + } else { + defaultStyle.setSize((double) (this.<Float>getParameter("scale").getValue() * 8)); + } + + TextSpan span = new TextSpan(defaultStyle, ""); + + for (StyledText styledText : asd) { + TextStyle style = getStylesMap().get(styledText.getGroup()); + TextSpan textSpan = new TextSpan(style.getLinked(), styledText.getText()); + span.addChild(textSpan); + } + richText.setRootSpan(span); } - GlStateManager.scale(scale, scale, 0); - StyledTextRenderer.drawTextWithStylesAssociated(asd, 0, 0, (int) (Math.abs(getFeatureRect().getWidth())/scale), getStylesMap(), - StyledTextRenderer.Alignment.valueOf(TextHUDFeature.this.<String>getParameter("alignment").getValue())); + } catch (Exception e) { + e.printStackTrace(); } } + public static FontRenderer getFontRenderer() { + return Minecraft.getMinecraft().fontRendererObj; + } + public boolean doesScaleWithHeight() { return true; } @@ -72,7 +117,7 @@ public abstract class TextHUDFeature extends GuiFeature implements StyledTextPro List<StyledText> asd = getDummyText(); double scale = 1; if (doesScaleWithHeight()) { - FontRenderer fr = getFontRenderer(); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; scale = getFeatureRect().getRectangle().getHeight() / (fr.FONT_HEIGHT* countLines(asd)); } else { scale = this.<Float>getParameter("scale").getValue(); @@ -107,6 +152,8 @@ public abstract class TextHUDFeature extends GuiFeature implements StyledTextPro public List<TextStyle> getStyles() { return this.<List<TextStyle>>getParameter("textStylesNEW").getValue(); } + + private Map<String, TextStyle> stylesMap; public Map<String, TextStyle> getStylesMap() { if (stylesMap == null) { @@ -117,7 +164,7 @@ public abstract class TextHUDFeature extends GuiFeature implements StyledTextPro } for (String str : getUsedTextStyle()) { if (!res.containsKey(str)) - res.put(str, new TextStyle(str, new AColor(0xffffffff, true), new AColor(0x00777777, true), false)); + res.put(str, new TextStyle(str, new AColor(0xffffffff, true), new AColor(0x00777777, true), false, new ParentDelegatingTextStyle())); } stylesMap = res; } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextStyle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextStyle.java index 16cb4b66..8a89ae25 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextStyle.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextStyle.java @@ -19,6 +19,9 @@ package kr.syeyoung.dungeonsguide.mod.features.text; import kr.syeyoung.dungeonsguide.mod.config.types.AColor; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.ChromaShader; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.SingleColorShader; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles.ParentDelegatingTextStyle; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -31,4 +34,29 @@ public class TextStyle { private AColor color; private AColor background; private boolean shadow = false; + + public TextStyle(String groupName, AColor color, AColor background, boolean shadow) { + this.groupName = groupName; + this.color = color; + this.background = background; + this.shadow = shadow; + } + + public void setColor(AColor color) { + this.color = color; + if (!color.isChroma()) + linked.textShader = new SingleColorShader(color.getRGB()); + else + linked.textShader = new ChromaShader(color.getChromaSpeed(), color.getRGB()); + } + + public void setBackground(AColor background) { + this.background = background; + if (!background.isChroma()) + linked.backgroundShader = new SingleColorShader(background.getRGB()); + else + linked.backgroundShader = new ChromaShader(background.getChromaSpeed(), background.getRGB()); + } + + private ParentDelegatingTextStyle linked = new ParentDelegatingTextStyle(); } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/FlatTextSpan.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/FlatTextSpan.java index f4ba08c8..71f3ca0e 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/FlatTextSpan.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/FlatTextSpan.java @@ -18,12 +18,14 @@ package kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles.ITextStyle; + public class FlatTextSpan { - public final TextStyle textStyle; + public final ITextStyle textStyle; public final char[] value; - public FlatTextSpan(TextStyle textStyle, char[] value) { + public FlatTextSpan(ITextStyle textStyle, char[] value) { this.textStyle = textStyle; this.value = value; } @@ -36,10 +38,10 @@ public class FlatTextSpan { return sum; } public double getHeight() { - return textStyle.getSize() * textStyle.getLineHeight(); + return (1 + textStyle.getTopAscent() + textStyle.getBottomAscent()) * textStyle.getSize(); } public double getBaseline() { - return textStyle.getSize() * (textStyle.getLineHeight()-1) + textStyle.getFontRenderer().getBaselineHeight(textStyle); + return textStyle.getSize() * (textStyle.getFontRenderer().getBaselineHeight(textStyle) + textStyle.getTopAscent()); } public BrokenWordData breakWord(double remainingWidth, double nextLineWidth, BreakWord breakWord) { @@ -55,6 +57,7 @@ public class FlatTextSpan { int potentialBreak = -1; int endIdx = value.length; + boolean lineBroken = false; for (int i = 0; i < value.length; i++) { char character = value[i]; charWidth = textStyle.getFontRenderer().getWidth(character, textStyle); @@ -67,22 +70,26 @@ public class FlatTextSpan { } else if (scaledNextLineWidth < wordWidth) { // Break at potential, word is greater than next line endIdx = potentialBreak; + lineBroken = true; break; } else { // Delegate to next line. endIdx = wordStart; + lineBroken = true; break; } // Force break. if (character == '\n') { - endIdx = i; + endIdx = i+1; + lineBroken = true; break; } // Since adding space exceeded remaining width, break without adding space. if (totalWidth > scaledRemainingWidth) { endIdx = i; + lineBroken = true; break; } @@ -96,16 +103,27 @@ public class FlatTextSpan { potentialBreak = i; } } + if (potentialBreak == -1) { + } else if (scaledNextLineWidth < wordWidth) { + // Break at potential, word is greater than next line + endIdx = potentialBreak; + lineBroken = true; + } else { + // Delegate to next line. + endIdx = wordStart; + lineBroken = true; + } char[] first = new char[endIdx]; System.arraycopy(value, 0, first, 0, endIdx); char[] second = null; - if (endIdx != value.length) { + if (lineBroken) { int startRealWord = -1; for (int i = endIdx; i< value.length; i++) { - if (value[i] == ' ' || value[i] == '\n') continue; + if (value[i] == ' ') continue; startRealWord = i; + break; } if (startRealWord != -1) { second = new char[value.length - startRealWord]; @@ -124,13 +142,14 @@ public class FlatTextSpan { resultingWidth += textStyle.getFontRenderer().getWidth(c, textStyle); } - return new BrokenWordData(flatTextSpan, secondSpan, endIdx != value.length, resultingWidth); + return new BrokenWordData(flatTextSpan, secondSpan, lineBroken, resultingWidth); } else { // break anywhere double scaledRemainingWidth = remainingWidth; double totalWidth = 0; double effectiveWidth = 0; + boolean lineBroken =false; int endIdx = value.length; for (int i = 0; i < value.length; i++) { @@ -141,13 +160,15 @@ public class FlatTextSpan { if (character == '\n') { // Force break. - endIdx = i; + endIdx = i + 1; + lineBroken = true; break; } if (totalWidth > scaledRemainingWidth) { // break here. endIdx = i; + lineBroken = true; break; } effectiveWidth += charWidth; @@ -157,11 +178,12 @@ public class FlatTextSpan { System.arraycopy(value, 0, first, 0, endIdx); char[] second = null; - if (endIdx != value.length) { + if (lineBroken) { int startRealWord = -1; for (int i = endIdx; i< value.length; i++) { - if (value[i] == ' ' || value[i] == '\n') continue; + if (value[i] == ' ') continue; startRealWord = i; + break; } if (startRealWord != -1) { second = new char[value.length - startRealWord]; @@ -174,7 +196,7 @@ public class FlatTextSpan { if (second != null) secondSpan = new FlatTextSpan(textStyle, second); - return new BrokenWordData(flatTextSpan, secondSpan, endIdx != value.length, effectiveWidth); + return new BrokenWordData(flatTextSpan, secondSpan, lineBroken, effectiveWidth); } } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/RichText.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/RichText.java index 6822a27d..b207292b 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/RichText.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/RichText.java @@ -88,6 +88,10 @@ public class RichText extends Widget implements Layouter, Renderer { usedUp += brokenWordData.getFirstWidth(); line.add(brokenWordData.getFirst()); + if (brokenWordData.getFirst().value.length == 0 && first.value.length != 0 && remaining == constraintBox.getMaxWidth()) { + throw new IllegalStateException("Can not fit stuff into this"); + } + maxHeight = Math.max(maxHeight, first.getHeight()); maxBaseline = Math.max(maxBaseline, first.getBaseline()); @@ -97,7 +101,7 @@ public class RichText extends Widget implements Layouter, Renderer { if (brokenWordData.isBroken()) { lines.add(new RichLine(line, usedUp, maxHeight, maxBaseline)); - line.clear(); + line = new LinkedList<>(); maxWidth = Math.max(maxWidth, usedUp); sumHeight += maxHeight; @@ -195,6 +199,8 @@ public class RichText extends Widget implements Layouter, Renderer { x = width - richLine.getWidth(); else if (align == TextAlign.CENTER) x = (width - richLine.getWidth()) / 2; + else + x = 0; for (FlatTextSpan lineElement : richLine.getLineElements()) { lineElement.textStyle.getFontRenderer() .render(lineElement, x, y + richLine.getBaseline() - lineElement.getBaseline(), currentScale); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/TextSpan.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/TextSpan.java index fde3e4d0..e8e562dc 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/TextSpan.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/TextSpan.java @@ -18,21 +18,31 @@ package kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles.CompiledTextStyle; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles.ITextStyle; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles.ParentDelegatingTextStyle; + import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; public class TextSpan { - private TextStyle textStyle; + private ITextStyle textStyle; private String text; private List<TextSpan> children = new ArrayList<>(); - public TextSpan(TextStyle textStyle, String text) { + public TextSpan(ITextStyle textStyle, String text) { this.textStyle = textStyle; this.text = text; } + public void addChild(TextSpan textSpan) { + if (textSpan.textStyle instanceof ParentDelegatingTextStyle) + ((ParentDelegatingTextStyle) textSpan.textStyle).setParent(textStyle); + children.add(textSpan); + } + public void flattenTextSpan(Consumer<FlatTextSpan> appender) { - appender.accept(new FlatTextSpan(textStyle, text.toCharArray())); + appender.accept(new FlatTextSpan(new CompiledTextStyle(textStyle), text.toCharArray())); children.forEach(a -> a.flattenTextSpan(appender)); } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/fonts/DefaultFontRenderer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/fonts/DefaultFontRenderer.java index 245fc6d2..ade7b519 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/fonts/DefaultFontRenderer.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/fonts/DefaultFontRenderer.java @@ -19,7 +19,7 @@ package kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.fonts; import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.FlatTextSpan; -import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.TextStyle; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles.ITextStyle; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; @@ -127,7 +127,7 @@ public class DefaultFontRenderer implements FontRenderer { } @Override - public double getWidth(char text, TextStyle textStyle) { + public double getWidth(char text, ITextStyle textStyle) { double val; if (text == ' ') { val = 4; @@ -147,7 +147,7 @@ public class DefaultFontRenderer implements FontRenderer { } @Override - public double getBaselineHeight(TextStyle textStyle) { + public double getBaselineHeight(ITextStyle textStyle) { return 7 * textStyle.getSize() / 8.0; } @@ -161,29 +161,30 @@ public class DefaultFontRenderer implements FontRenderer { for (char c : lineElement.value) { x += renderChar(worldRenderer, x, y+1, c, lineElement.textStyle); } - if (!isShadow) lineElement.textStyle.getTextShader().freeShader(); draw(worldRenderer); + if (!isShadow) lineElement.textStyle.getTextShader().freeShader(); GlStateManager.disableTexture2D(); + double baseline = getBaselineHeight(lineElement.textStyle); if (lineElement.textStyle.isStrikeThrough()) { - worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); if (!isShadow) lineElement.textStyle.getStrikeThroughShader().useShader(); - worldRenderer.pos(startX, y + lineElement.textStyle.getSize()/2, 0); - worldRenderer.pos(x, y + lineElement.textStyle.getSize()/2, 0); - worldRenderer.pos(x, y + lineElement.textStyle.getSize()/2+1, 0); - worldRenderer.pos(startX, y + lineElement.textStyle.getSize()/2+1, 0); - if (!isShadow) lineElement.textStyle.getStrikeThroughShader().freeShader(); + worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); + worldRenderer.pos(startX, y + baseline/2, 0).endVertex(); + worldRenderer.pos(x, y + baseline/2, 0).endVertex(); + worldRenderer.pos(x, y +baseline/2+1, 0).endVertex(); + worldRenderer.pos(startX, y + baseline/2+1, 0).endVertex(); draw(worldRenderer); + if (!isShadow) lineElement.textStyle.getStrikeThroughShader().freeShader(); } if (lineElement.textStyle.isUnderline()) { - worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); if (!isShadow) lineElement.textStyle.getUnderlineShader().useShader(); - worldRenderer.pos(startX, y + lineElement.textStyle.getSize(), 0); - worldRenderer.pos(x, y + lineElement.textStyle.getSize(), 0); - worldRenderer.pos(x, y + lineElement.textStyle.getSize()+1, 0); - worldRenderer.pos(startX, y + lineElement.textStyle.getSize()+1, 0); - if (!isShadow) lineElement.textStyle.getUnderlineShader().freeShader(); + worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); + worldRenderer.pos(startX, y + baseline, 0).endVertex(); + worldRenderer.pos(x, y + baseline, 0).endVertex(); + worldRenderer.pos(x, y + baseline+1, 0).endVertex(); + worldRenderer.pos(startX, y + baseline+1, 0).endVertex(); draw(worldRenderer); + if (!isShadow) lineElement.textStyle.getUnderlineShader().freeShader(); } if (isShadow) lineElement.textStyle.getShadowShader().freeShader(); @@ -192,17 +193,21 @@ public class DefaultFontRenderer implements FontRenderer { @Override public void render(FlatTextSpan lineElement, double x, double y, double currentScale) { + lastBound = null; WorldRenderer worldRenderer = Tessellator.getInstance().getWorldRenderer(); GlStateManager.disableTexture2D(); + GlStateManager.enableAlpha(); if (lineElement.textStyle.getBackgroundShader() != null) { lineElement.textStyle.getBackgroundShader().useShader(); - worldRenderer.pos(x, y, 0); - worldRenderer.pos(x + lineElement.getWidth(), y, 0); - worldRenderer.pos(x + lineElement.getWidth(), y + lineElement.textStyle.getSize()+1, 0); - worldRenderer.pos(x, y + lineElement.textStyle.getSize()+1, 0); - lineElement.textStyle.getBackgroundShader().freeShader(); + worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); + worldRenderer.pos(x, y, 0).endVertex(); + worldRenderer.pos(x + lineElement.getWidth(), y, 0).endVertex(); + worldRenderer.pos(x + lineElement.getWidth(), y + lineElement.textStyle.getSize(), 0).endVertex(); + worldRenderer.pos(x, y + lineElement.textStyle.getSize(), 0).endVertex(); draw(worldRenderer); + lineElement.textStyle.getBackgroundShader().freeShader(); } + y += lineElement.textStyle.getTopAscent(); if (lineElement.textStyle.isShadow()) render(worldRenderer, lineElement, x+1,y+1, true); @@ -211,9 +216,9 @@ public class DefaultFontRenderer implements FontRenderer { - private double renderChar(WorldRenderer worldRenderer, double x, double y, char ch, TextStyle textStyle) { + private double renderChar(WorldRenderer worldRenderer, double x, double y, char ch, ITextStyle textStyle) { if (ch == ' ') { - return 4.0F; + return 4.0F * textStyle.getSize() / 8.0; } else { int i = "ÀÁÂÈÊËÍÓÔÕÚßãõğİıŒœŞşŴŵžȇ\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø׃áíóúñѪº¿®¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αβΓπΣσμτΦΘΩδ∞∅∈∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■\u0000".indexOf(ch); return i != -1 ? this.renderDefaultChar(worldRenderer, x, y, i, textStyle) : this.renderUnicodeChar(worldRenderer, x, y, ch, textStyle); @@ -247,29 +252,34 @@ public class DefaultFontRenderer implements FontRenderer { renderer.reset(); } + private ResourceLocation lastBound; public void bindTexture(WorldRenderer worldRenderer, ResourceLocation resourceLocation) { + if (resourceLocation.equals(lastBound)) return; + lastBound = resourceLocation; draw(worldRenderer); Minecraft.getMinecraft().getTextureManager().bindTexture(resourceLocation); + worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); } - private double renderDefaultChar(WorldRenderer worldRenderer, double posX, double posY, int ch, TextStyle textStyle) { + private double renderDefaultChar(WorldRenderer worldRenderer, double posX, double posY, int ch, ITextStyle textStyle) { int texX = ch % 16 * 8; int texY = ch / 16 * 8; - int italicsAddition = textStyle.italics ? 1 : 0; + int italicsAddition = textStyle.isItalics() ? 1 : 0; bindTexture(worldRenderer, this.locationFontTexture); - double charWidth = (this.charWidth[ch] - 1.0F) * textStyle.getSize() / 8.0; + double texWidth = (this.charWidth[ch]); + double charWidth = (texWidth-1) * textStyle.getSize() / 8.0; double charHeight = textStyle.getSize(); // char width contains the gap between next char - worldRenderer.pos(posX + (float)italicsAddition, posY, 0.0F).tex((float)texX / 128.0F, (float)texY / 128.0F); - worldRenderer.pos(posX - (float)italicsAddition, posY + charHeight - 0.01F, 0.0F).tex((float)texX / 128.0F, ((float)texY + 7.99F) / 128.0F); - worldRenderer.pos(posX + charWidth+ (float)italicsAddition - 0.01F , posY, 0.0F).tex(((float)texX + charWidth - 1.01F) / 128.0F, (float)texY / 128.0F); - worldRenderer.pos(posX + charWidth - (float)italicsAddition - 0.01F, posY + charHeight - 0.01F, 0.0F).tex(((float)texX + charWidth - 1.01F) / 128.0F, ((float)texY + 7.99F) / 128.0F); + worldRenderer.pos(posX + (float)italicsAddition, posY, 0.0F).tex((float)texX / 128.0F, (float)texY / 128.0F).endVertex(); + worldRenderer.pos(posX - (float)italicsAddition, posY + charHeight - 0.01F, 0.0F).tex((float)texX / 128.0F, ((float)texY + 7.99F) / 128.0F).endVertex(); + worldRenderer.pos(posX + charWidth+ (float)italicsAddition - 0.01F , posY+ charHeight - 0.01F, 0.0F).tex(((float)texX + texWidth - 1.01F) / 128.0F, ((float)texY + 7.99F) / 128.0F).endVertex(); + worldRenderer.pos(posX + charWidth - (float)italicsAddition - 0.01F, posY , 0.0F).tex(((float)texX + texWidth - 1.01F) / 128.0F, (float)texY / 128.0F).endVertex(); - return charWidth + textStyle.getSize() / 8.0; + return texWidth * textStyle.getSize() / 8.0; } - private double renderUnicodeChar(WorldRenderer worldRenderer, double posX, double posY, char ch, TextStyle textStyle) { + private double renderUnicodeChar(WorldRenderer worldRenderer, double posX, double posY, char ch, ITextStyle textStyle) { if (this.glyphData[ch] == 0) { return 0.0F; } else { @@ -281,19 +291,19 @@ public class DefaultFontRenderer implements FontRenderer { float texX = (float)(ch % 16 * 16) + xStart; float texY = (float)((ch & 255) / 16 * 16); float texWidth = xEnd - xStart - 0.02F; - float italicSlope = textStyle.italics ? 1.0F : 0.0F; + float italicSlope = textStyle.isItalics() ? 1.0F : 0.0F; double charWidth = texWidth * textStyle.getSize() / 16.0; double charHeight = textStyle.getSize(); worldRenderer.pos(posX + italicSlope, posY, 0.0F) - .tex(texX / 256.0F, texY / 256.0F); + .tex(texX / 256.0F, texY / 256.0F).endVertex(); worldRenderer.pos(posX - italicSlope, posY + charHeight - 0.01F, 0.0F) - .tex(texX / 256.0F, (texY + 15.98F) / 256.0F); - worldRenderer.pos(posX + charWidth + italicSlope, posY, 0.0F) - .tex((texX + texWidth) / 256.0F, texY / 256.0F); - worldRenderer.pos(posX + charWidth - italicSlope, posY + charHeight - 0.01F, 0.0F) - .tex((texX + texWidth) / 256.0F, (texY + 15.98F) / 256.0F); + .tex(texX / 256.0F, (texY + 15.98F) / 256.0F).endVertex(); + worldRenderer.pos(posX + charWidth + italicSlope, posY + charHeight - 0.01F, 0.0F) + .tex((texX + texWidth) / 256.0F, (texY+15.98F) / 256.0F).endVertex(); + worldRenderer.pos(posX + charWidth - italicSlope, posY, 0.0F) + .tex((texX + texWidth) / 256.0F, (texY) / 256.0F).endVertex(); return charWidth + textStyle.getSize() / 8.0; } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/fonts/FontRenderer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/fonts/FontRenderer.java index b9f52c06..193a2758 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/fonts/FontRenderer.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/fonts/FontRenderer.java @@ -19,12 +19,12 @@ package kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.fonts; import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.FlatTextSpan; -import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.TextStyle; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles.ITextStyle; public interface FontRenderer { - double getWidth(char text, TextStyle textStyle); + double getWidth(char text, ITextStyle textStyle); // from y 0 going downward - double getBaselineHeight(TextStyle textStyle); + double getBaselineHeight(ITextStyle textStyle); void render(FlatTextSpan lineElement, double x, double v, double currentScale); } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/TextStyle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/shaders/ChromaShader.java index eb49baa2..5e1e8bb1 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/TextStyle.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/shaders/ChromaShader.java @@ -16,33 +16,26 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -package kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext; +package kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders; -import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.fonts.FontRenderer; -import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader; -import lombok.Data; +import net.minecraft.client.renderer.GlStateManager; -@Data -public class TextStyle { - public Double size; - public Double lineHeight; +public class ChromaShader implements Shader { + private float r, g, b, a; + public ChromaShader(float chromaSpeed, int color) { + r = ((color >> 16) & 0xFF) / 255.0f; + g = ((color >> 8) & 0xFF) / 255.0f; + b = ((color) & 0xFF) / 255.0f; + a = ((color >> 24) & 0xFF) / 255.0f; + } - public boolean bold; - public boolean italics; - public boolean strikeThrough; - public boolean underline; - public boolean outline; - public boolean shadow; - public Shader backgroundShader; - public Shader textShader; - public Shader strikeThroughShader; - public Shader underlineShader; - public Shader outlineShader; - public Shader shadowShader; + // argb= + @Override + public void useShader() { + GlStateManager.color(r,g,b,a); + } - - - public TextStyle parent; - public FontRenderer fontRenderer; + @Override + public void freeShader() {} } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/shaders/SingleColorShader.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/shaders/SingleColorShader.java index bd686968..806452dc 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/shaders/SingleColorShader.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/shaders/SingleColorShader.java @@ -28,7 +28,7 @@ public class SingleColorShader implements Shader{ r = ((color >> 16) & 0xFF) / 255.0f; g = ((color >> 8) & 0xFF) / 255.0f; b = ((color) & 0xFF) / 255.0f; - r = ((color >> 24) & 0xFF) / 255.0f; + a = ((color >> 24) & 0xFF) / 255.0f; } @Override public void useShader() { diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/styles/CompiledTextStyle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/styles/CompiledTextStyle.java new file mode 100644 index 00000000..124e47de --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/styles/CompiledTextStyle.java @@ -0,0 +1,148 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles; + +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.fonts.FontRenderer; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader; +import lombok.Getter; +import lombok.Setter; + +public class CompiledTextStyle implements ITextStyle { + public Double size; + public Double topAscent; + public Double bottomAscent; + + public boolean bold; + public boolean italics; + public boolean strikeThrough; + public boolean underline; + public boolean outline; + public boolean shadow; + + public Shader backgroundShader; + public Shader textShader; + public Shader strikeThroughShader; + public Shader underlineShader; + public Shader outlineShader; + public Shader shadowShader; + + + public FontRenderer fontRenderer; + + public CompiledTextStyle(ITextStyle from) { + this.size = from.getSize(); + this.topAscent = from.getTopAscent(); + this.bottomAscent = from.getBottomAscent(); + + this.bold = from.isBold(); + this.italics = from.isItalics(); + this.strikeThrough = from.isStrikeThrough(); + this.underline = from.isUnderline(); + this.outline = from.isOutline(); + this.shadow = from.isShadow(); + + this.backgroundShader = from.getBackgroundShader(); + this.textShader = from.getTextShader(); + this.strikeThroughShader = from.getStrikeThroughShader(); + this.underlineShader = from.getUnderlineShader(); + this.outlineShader = from.getOutlineShader(); + this.shadowShader = from.getShadowShader(); + this.fontRenderer = from.getFontRenderer(); + } + + @Override + public Double getSize() { + return size; + } + + @Override + public Double getTopAscent() { + return topAscent; + } + + @Override + public Double getBottomAscent() { + return bottomAscent; + } + + @Override + public Boolean isBold() { + return bold; + } + + @Override + public Boolean isItalics() { + return italics; + } + + @Override + public Boolean isStrikeThrough() { + return strikeThrough; + } + + @Override + public Boolean isUnderline() { + return underline; + } + + @Override + public Boolean isOutline() { + return outline; + } + + @Override + public Boolean isShadow() { + return shadow; + } + + @Override + public Shader getBackgroundShader() { + return backgroundShader; + } + + @Override + public Shader getTextShader() { + return textShader; + } + + @Override + public Shader getStrikeThroughShader() { + return strikeThroughShader; + } + + @Override + public Shader getUnderlineShader() { + return underlineShader; + } + + @Override + public Shader getOutlineShader() { + return outlineShader; + } + + @Override + public Shader getShadowShader() { + return shadowShader; + } + + @Override + public FontRenderer getFontRenderer() { + return fontRenderer; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/styles/ITextStyle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/styles/ITextStyle.java new file mode 100644 index 00000000..285ed79e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/styles/ITextStyle.java @@ -0,0 +1,52 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles; + +public interface ITextStyle { + Double getSize(); + + Double getTopAscent(); + Double getBottomAscent(); + + Boolean isBold(); + + Boolean isItalics(); + + Boolean isStrikeThrough(); + + Boolean isUnderline(); + + Boolean isOutline(); + + Boolean isShadow(); + + kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getBackgroundShader(); + + kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getTextShader(); + + kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getStrikeThroughShader(); + + kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getUnderlineShader(); + + kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getOutlineShader(); + + kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader getShadowShader(); + + kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.fonts.FontRenderer getFontRenderer(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/styles/ParentDelegatingTextStyle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/styles/ParentDelegatingTextStyle.java new file mode 100644 index 00000000..9889c98e --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/richtext/styles/ParentDelegatingTextStyle.java @@ -0,0 +1,157 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.styles; + +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.fonts.DefaultFontRenderer; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.fonts.FontRenderer; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.Shader; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.shaders.SingleColorShader; +import lombok.Getter; +import lombok.Setter; + +@Setter +public class ParentDelegatingTextStyle implements ITextStyle { + public Double size; + public Double topAscent; + public Double bottomAscent; + + + + public Boolean bold; + public Boolean italics; + public Boolean strikeThrough; + public Boolean underline; + public Boolean outline; + public Boolean shadow; + + public Shader backgroundShader; + public Shader textShader; + public Shader strikeThroughShader; + public Shader underlineShader; + public Shader outlineShader; + public Shader shadowShader; + + + @Getter @Setter + public ITextStyle parent; + public FontRenderer fontRenderer; + + public static ParentDelegatingTextStyle ofDefault() { + ParentDelegatingTextStyle parentDelegatingTextStyle = new ParentDelegatingTextStyle(); + parentDelegatingTextStyle.size = 8.0; + parentDelegatingTextStyle.topAscent = 0.0; + parentDelegatingTextStyle.bottomAscent = 1 / 8.0; + parentDelegatingTextStyle.bold = false; + parentDelegatingTextStyle.italics = false; + parentDelegatingTextStyle.strikeThrough = false; + parentDelegatingTextStyle.underline = false; + parentDelegatingTextStyle.shadow = false; + parentDelegatingTextStyle.outline = false; + + parentDelegatingTextStyle.backgroundShader = new SingleColorShader(0xFFFFFFFF); + parentDelegatingTextStyle.textShader = new SingleColorShader(0xFFFFFFFF); + parentDelegatingTextStyle.strikeThroughShader = new SingleColorShader(0xFF000000); + parentDelegatingTextStyle.underlineShader = new SingleColorShader(0xFF000000); + parentDelegatingTextStyle.outlineShader = new SingleColorShader(0xFF000000); + parentDelegatingTextStyle.shadowShader = new SingleColorShader(0xFF000000); + + parentDelegatingTextStyle.fontRenderer = DefaultFontRenderer.DEFAULT_RENDERER; + return parentDelegatingTextStyle; + } + + @Override + public Double getSize() { + return parent != null && size == null ? parent.getSize() : size; + } + + @Override + public Double getTopAscent() { + return parent != null && topAscent == null ? parent.getTopAscent() : topAscent; + } + + @Override + public Double getBottomAscent() { + return parent != null && bottomAscent == null ? parent.getBottomAscent() : bottomAscent; + } + + @Override + public Boolean isBold() { + return parent != null && bold == null ? parent.isBold() : bold; + } + + @Override + public Boolean isItalics() { + return parent != null && italics == null ? parent.isItalics() : italics; + } + + @Override + public Boolean isOutline() { + return parent != null && outline == null ? parent.isOutline() : outline; + } + + @Override + public Boolean isShadow() { + return parent != null && shadow == null ? parent.isShadow() : shadow; + } + + @Override + public Boolean isStrikeThrough() { + return parent != null && strikeThrough == null ? parent.isStrikeThrough() : strikeThrough; + } + + @Override + public Boolean isUnderline() { + return parent != null && underline == null ? parent.isUnderline() : underline; + } + + @Override + public FontRenderer getFontRenderer() { + return parent != null && fontRenderer == null ? parent.getFontRenderer() : fontRenderer; + } + + @Override + public Shader getShadowShader() { + return parent != null && shadowShader == null ? parent.getShadowShader() : shadowShader; + } + + @Override + public Shader getBackgroundShader() { + return parent != null && backgroundShader == null ? parent.getBackgroundShader() : backgroundShader; + } + + @Override + public Shader getOutlineShader() { + return parent != null && outlineShader == null ? parent.getOutlineShader() : outlineShader; + } + + @Override + public Shader getStrikeThroughShader() { + return parent != null && strikeThroughShader == null ? parent.getStrikeThroughShader() : strikeThroughShader; + } + + @Override + public Shader getTextShader() { + return parent != null && textShader == null ? parent.getTextShader() : textShader; + } + + @Override + public Shader getUnderlineShader() { + return parent != null && underlineShader == null ? parent.getUnderlineShader() : underlineShader; + } +} |