From b87ea0f98f73702e468ec0971a8afeff0d50ccb6 Mon Sep 17 00:00:00 2001 From: deirn Date: Tue, 4 Jun 2024 21:43:27 +0700 Subject: [PATCH] add narration to tooltip components --- .../mobius/waila/api/ITooltipComponent.java | 9 +++++++++ .../waila/api/component/ArmorComponent.java | 8 ++++++++ .../waila/api/component/BarComponent.java | 6 ++++++ .../waila/api/component/HealthComponent.java | 11 ++++++++++- .../waila/api/component/ItemComponent.java | 8 ++++++++ .../api/component/ItemListComponent.java | 16 ++++++++++++++++ .../api/component/NamedItemComponent.java | 8 ++++++++ .../api/component/NamedItemListComponent.java | 17 +++++++++++++++++ .../waila/api/component/PairComponent.java | 12 ++++++++++++ .../api/component/SpriteBarComponent.java | 6 ++++++ .../waila/api/component/WrappedComponent.java | 6 ++++++ .../mobius/waila/gui/hud/TooltipRenderer.java | 19 +++++++++++-------- .../resources/assets/waila/lang/en_us.json | 4 ++++ 13 files changed, 121 insertions(+), 9 deletions(-) diff --git a/src/api/java/mcp/mobius/waila/api/ITooltipComponent.java b/src/api/java/mcp/mobius/waila/api/ITooltipComponent.java index 9c0b5057b..6ad08c547 100644 --- a/src/api/java/mcp/mobius/waila/api/ITooltipComponent.java +++ b/src/api/java/mcp/mobius/waila/api/ITooltipComponent.java @@ -2,7 +2,9 @@ import mcp.mobius.waila.api.__internal__.ApiSide; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; /** * The base type of all Waila tooltip components. @@ -34,6 +36,13 @@ public interface ITooltipComponent { */ void render(GuiGraphics ctx, int x, int y, float delta); + /** + * Returns the message that will be read out loud when TTS is enabled. + */ + default @Nullable Component getNarration() { + return null; + } + /** * A component that will grow in size relative to overall tooltip width. *

diff --git a/src/api/java/mcp/mobius/waila/api/component/ArmorComponent.java b/src/api/java/mcp/mobius/waila/api/component/ArmorComponent.java index a2ba49f21..594beb7fe 100644 --- a/src/api/java/mcp/mobius/waila/api/component/ArmorComponent.java +++ b/src/api/java/mcp/mobius/waila/api/component/ArmorComponent.java @@ -2,9 +2,12 @@ import mcp.mobius.waila.api.ITooltipComponent; import mcp.mobius.waila.api.__internal__.ApiSide; +import mcp.mobius.waila.buildconst.Tl; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; +import org.jetbrains.annotations.Nullable; /** * Component that renders an armor bar. @@ -39,6 +42,11 @@ public int getHeight() { return (Mth.positiveCeilDiv(iconCount, lineWidth) * 3) + 6; } + @Override + public @Nullable Component getNarration() { + return Component.translatable(Tl.Tts.Component.ARMOR, armor); + } + @Override public void render(GuiGraphics ctx, int x, int y, float delta) { var filled = armor / 2 - 1; diff --git a/src/api/java/mcp/mobius/waila/api/component/BarComponent.java b/src/api/java/mcp/mobius/waila/api/component/BarComponent.java index 1c5a0f49e..9ac65fbfc 100644 --- a/src/api/java/mcp/mobius/waila/api/component/BarComponent.java +++ b/src/api/java/mcp/mobius/waila/api/component/BarComponent.java @@ -15,6 +15,7 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; /** * Component that renders a colored bar. @@ -74,6 +75,11 @@ public int getHeight() { return HEIGHT; } + @Override + public @Nullable Component getNarration() { + return text; + } + @Override public void render(GuiGraphics ctx, int x, int y, float delta) { renderBar(ctx.pose(), x, y, WIDTH, V0_BG, U1, V1_BG, color); diff --git a/src/api/java/mcp/mobius/waila/api/component/HealthComponent.java b/src/api/java/mcp/mobius/waila/api/component/HealthComponent.java index 540e06006..b8c31f29b 100644 --- a/src/api/java/mcp/mobius/waila/api/component/HealthComponent.java +++ b/src/api/java/mcp/mobius/waila/api/component/HealthComponent.java @@ -2,9 +2,12 @@ import mcp.mobius.waila.api.ITooltipComponent; import mcp.mobius.waila.api.__internal__.ApiSide; +import mcp.mobius.waila.buildconst.Tl; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; +import org.jetbrains.annotations.Nullable; /** * Component that renders a health bar. @@ -26,12 +29,13 @@ public class HealthComponent implements ITooltipComponent { */ public HealthComponent(float health, float maxHealth, int maxPerLine, boolean absorption) { this.health = Mth.ceil(health); + this.maxHealth = Mth.ceil(maxHealth); this.iconCount = Mth.positiveCeilDiv(Mth.ceil(Math.max(health, maxHealth)), 2); this.lineWidth = Math.min(iconCount, maxPerLine); this.absorption = absorption; } - private final int health; + private final int health, maxHealth; private final int iconCount; private final int lineWidth; private final boolean absorption; @@ -46,6 +50,11 @@ public int getHeight() { return (Mth.positiveCeilDiv(iconCount, lineWidth) * 3) + 6; } + @Override + public @Nullable Component getNarration() { + return Component.translatable(Tl.Tts.Component.HEALTH, health, maxHealth); + } + @Override public void render(GuiGraphics ctx, int x, int y, float delta) { var filled = health / 2 - 1; diff --git a/src/api/java/mcp/mobius/waila/api/component/ItemComponent.java b/src/api/java/mcp/mobius/waila/api/component/ItemComponent.java index c8d9992b5..cf593af54 100644 --- a/src/api/java/mcp/mobius/waila/api/component/ItemComponent.java +++ b/src/api/java/mcp/mobius/waila/api/component/ItemComponent.java @@ -3,11 +3,14 @@ import mcp.mobius.waila.api.ITooltipComponent; import mcp.mobius.waila.api.WailaHelper; import mcp.mobius.waila.api.__internal__.ApiSide; +import mcp.mobius.waila.buildconst.Tl; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ItemLike; +import org.jetbrains.annotations.Nullable; /** * Component that renders an {@link ItemStack}. @@ -37,6 +40,11 @@ public int getHeight() { return stack.isEmpty() ? 0 : 18; } + @Override + public @Nullable Component getNarration() { + return Component.translatable(Tl.Tts.Component.ITEM, stack.getCount(), stack.getDisplayName()); + } + @Override public void render(GuiGraphics ctx, int x, int y, float delta) { ctx.renderItem(stack, x + 1, y + 1); diff --git a/src/api/java/mcp/mobius/waila/api/component/ItemListComponent.java b/src/api/java/mcp/mobius/waila/api/component/ItemListComponent.java index 6f24cbcb5..e1dfe372c 100644 --- a/src/api/java/mcp/mobius/waila/api/component/ItemListComponent.java +++ b/src/api/java/mcp/mobius/waila/api/component/ItemListComponent.java @@ -4,9 +4,12 @@ import mcp.mobius.waila.api.ITooltipComponent; import mcp.mobius.waila.api.__internal__.ApiSide; +import mcp.mobius.waila.buildconst.Tl; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; /** * Component that renders items that dynamically grow based on available space. @@ -42,6 +45,19 @@ public void setGrownWidth(int grownWidth) { maxIndex = gridWidth * gridHeight - 1; } + @Override + public @Nullable Component getNarration() { + if (items.isEmpty()) return null; + + var narration = Component.empty(); + for (var item : items) { + narration.append(Component.translatable(Tl.Tts.Component.ITEM, item.getCount(), item.getDisplayName())); + narration.append("\n"); + } + narration.getSiblings().removeLast(); + return narration; + } + @Override public int getHeight() { return gridHeight * 18; diff --git a/src/api/java/mcp/mobius/waila/api/component/NamedItemComponent.java b/src/api/java/mcp/mobius/waila/api/component/NamedItemComponent.java index 00383b1be..5fd1dad3c 100644 --- a/src/api/java/mcp/mobius/waila/api/component/NamedItemComponent.java +++ b/src/api/java/mcp/mobius/waila/api/component/NamedItemComponent.java @@ -4,11 +4,14 @@ import mcp.mobius.waila.api.WailaHelper; import mcp.mobius.waila.api.__internal__.ApiSide; import mcp.mobius.waila.api.__internal__.IApiService; +import mcp.mobius.waila.buildconst.Tl; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ItemLike; +import org.jetbrains.annotations.Nullable; /** * Component that renders an {@link ItemStack} with its name. @@ -43,6 +46,11 @@ public int getHeight() { return getFont().lineHeight; } + @Override + public @Nullable Component getNarration() { + return Component.translatable(Tl.Tts.Component.ITEM, stack.getCount(), stack.getDisplayName()); + } + @Override public void render(GuiGraphics ctx, int x, int y, float delta) { var pose = ctx.pose(); diff --git a/src/api/java/mcp/mobius/waila/api/component/NamedItemListComponent.java b/src/api/java/mcp/mobius/waila/api/component/NamedItemListComponent.java index 8e71a30b6..d4c8dc70f 100644 --- a/src/api/java/mcp/mobius/waila/api/component/NamedItemListComponent.java +++ b/src/api/java/mcp/mobius/waila/api/component/NamedItemListComponent.java @@ -9,7 +9,9 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; /** * Component that renders items with their names. @@ -56,6 +58,21 @@ public int getHeight() { return height; } + @Override + public @Nullable Component getNarration() { + if (components.isEmpty()) return null; + + var narration = Component.empty(); + for (var component : components) { + var childNarration = component.getNarration(); + if (childNarration == null) continue; + narration.append(childNarration); + narration.append("\n"); + } + narration.getSiblings().removeLast(); + return narration; + } + @Override public void render(GuiGraphics ctx, int x, int y, float delta) { var iy = y; diff --git a/src/api/java/mcp/mobius/waila/api/component/PairComponent.java b/src/api/java/mcp/mobius/waila/api/component/PairComponent.java index b9686146e..f820638f6 100644 --- a/src/api/java/mcp/mobius/waila/api/component/PairComponent.java +++ b/src/api/java/mcp/mobius/waila/api/component/PairComponent.java @@ -7,6 +7,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; /** * Component that renders key-value pair that would be aligned at the colon. @@ -38,6 +39,17 @@ public int getHeight() { return height; } + @Override + public @Nullable Component getNarration() { + var keyNarration = key.getNarration(); + var valueNarration = value.getNarration(); + if (keyNarration != null) { + if (valueNarration != null) return keyNarration.copy().append(valueNarration); + else return keyNarration; + } + return valueNarration; + } + @Override public void render(GuiGraphics ctx, int x, int y, float delta) { var offset = key.getHeight() < height ? (height - key.getHeight()) / 2 : 0; diff --git a/src/api/java/mcp/mobius/waila/api/component/SpriteBarComponent.java b/src/api/java/mcp/mobius/waila/api/component/SpriteBarComponent.java index d97f12789..022898e5e 100644 --- a/src/api/java/mcp/mobius/waila/api/component/SpriteBarComponent.java +++ b/src/api/java/mcp/mobius/waila/api/component/SpriteBarComponent.java @@ -12,6 +12,7 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.Nullable; /** * Component that renders a bar with a texture as the foreground. @@ -53,6 +54,11 @@ public int getHeight() { return BarComponent.HEIGHT; } + @Override + public @Nullable Component getNarration() { + return text; + } + @Override public void render(GuiGraphics ctx, int x, int y, float delta) { var matrices = ctx.pose(); diff --git a/src/api/java/mcp/mobius/waila/api/component/WrappedComponent.java b/src/api/java/mcp/mobius/waila/api/component/WrappedComponent.java index 18b610f9b..916fe85d2 100644 --- a/src/api/java/mcp/mobius/waila/api/component/WrappedComponent.java +++ b/src/api/java/mcp/mobius/waila/api/component/WrappedComponent.java @@ -9,6 +9,7 @@ import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; /** * Component that renders a vanilla {@link Component}. @@ -36,6 +37,11 @@ public int getHeight() { return getFont().lineHeight; } + @Override + public @Nullable Component getNarration() { + return component; + } + @Override public void render(GuiGraphics ctx, int x, int y, float delta) { ctx.drawString(getFont(), component, x, y, IApiService.INSTANCE.getFontColor()); diff --git a/src/main/java/mcp/mobius/waila/gui/hud/TooltipRenderer.java b/src/main/java/mcp/mobius/waila/gui/hud/TooltipRenderer.java index 8b8588b49..320c2c6ee 100644 --- a/src/main/java/mcp/mobius/waila/gui/hud/TooltipRenderer.java +++ b/src/main/java/mcp/mobius/waila/gui/hud/TooltipRenderer.java @@ -20,7 +20,6 @@ import mcp.mobius.waila.api.WailaConstants; import mcp.mobius.waila.api.component.EmptyComponent; import mcp.mobius.waila.api.component.PairComponent; -import mcp.mobius.waila.api.component.WrappedComponent; import mcp.mobius.waila.config.PluginConfig; import mcp.mobius.waila.event.EventCanceller; import mcp.mobius.waila.mixin.BossHealthOverlayAccess; @@ -43,6 +42,7 @@ public class TooltipRenderer { private static final Supplier RECT = Suppliers.memoize(Rectangle::new); private static boolean started; + private static StringBuilder narrationBuilder = new StringBuilder(); private static String lastNarration = ""; private static ITooltipComponent icon = EmptyComponent.INSTANCE; private static int topOffset; @@ -60,6 +60,7 @@ public static void beginBuild(State state) { started = true; TooltipRenderer.state = state; TOOLTIP.clear(); + narrationBuilder = new StringBuilder(); icon = EmptyComponent.INSTANCE; topOffset = 0; colonOffset = 0; @@ -83,6 +84,11 @@ public static void add(Line line) { } for (var component : line.components) { + if (state.enableTextToSpeech() && !WailaConstants.MOD_NAME_TAG.equals(line.tag)) { + var narration = component.getNarration(); + if (narration != null) narrationBuilder.append("\n").append(narration.getString().replaceAll("§[a-z0-9]", "")); + } + if (component instanceof PairComponent pair) { colonOffset = Math.max(pair.key.getWidth(), colonOffset); break; @@ -332,13 +338,10 @@ private static void narrateObjectName(Minecraft client) { return; } - var objectName = TOOLTIP.getLine(WailaConstants.OBJECT_NAME_TAG); - if (objectName != null && objectName.components.get(0) instanceof WrappedComponent component) { - var narrate = component.component.getString().replaceAll("§[a-z0-9]", ""); - if (!lastNarration.equalsIgnoreCase(narrate)) { - CompletableFuture.runAsync(() -> narrator.say(narrate, true)); - lastNarration = narrate; - } + var narration = narrationBuilder.toString(); + if (!lastNarration.equalsIgnoreCase(narration)) { + CompletableFuture.runAsync(() -> narrator.say(narration, true)); + lastNarration = narration; } } diff --git a/src/resources/resources/assets/waila/lang/en_us.json b/src/resources/resources/assets/waila/lang/en_us.json index 09d186f73..740dadfbd 100644 --- a/src/resources/resources/assets/waila/lang/en_us.json +++ b/src/resources/resources/assets/waila/lang/en_us.json @@ -87,6 +87,10 @@ "tooltip.waila.harvest.tier.diamond" : "Diamond", "tooltip.waila.harvest.tier.netherite" : "Netherite", + "tts.waila.component.armor" : "Armor: %s", + "tts.waila.component.health" : "Health: %s/%s", + "tts.waila.component.item" : "%s of %s", + "gui.waila.configuration" : "%s Configuration", "gui.waila.waila_settings" : "%s Settings",