diff options
16 files changed, 293 insertions, 6 deletions
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java index 674fd77..331f68b 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java @@ -1,6 +1,7 @@ package io.github.cottonmc.cotton.gui.client; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.LiteralText; import net.minecraft.text.Style; @@ -10,6 +11,7 @@ import io.github.cottonmc.cotton.gui.GuiDescription; import io.github.cottonmc.cotton.gui.impl.VisualLogger; import io.github.cottonmc.cotton.gui.impl.client.CottonScreenImpl; import io.github.cottonmc.cotton.gui.impl.client.MouseInputHandler; +import io.github.cottonmc.cotton.gui.impl.client.NarrationHelper; import io.github.cottonmc.cotton.gui.widget.WPanel; import io.github.cottonmc.cotton.gui.widget.WWidget; import org.jetbrains.annotations.Nullable; @@ -267,4 +269,9 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl { return true; } + + @Override + protected void addElementNarrations(NarrationMessageBuilder builder) { + if (description != null) NarrationHelper.addNarrations(description.getRootPanel(), builder); + } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java index 01a5092..953563c 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java @@ -1,6 +1,7 @@ package io.github.cottonmc.cotton.gui.client; import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.render.DiffuseLighting; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerEntity; @@ -13,6 +14,7 @@ import io.github.cottonmc.cotton.gui.SyncedGuiDescription; import io.github.cottonmc.cotton.gui.impl.VisualLogger; import io.github.cottonmc.cotton.gui.impl.client.CottonScreenImpl; import io.github.cottonmc.cotton.gui.impl.client.MouseInputHandler; +import io.github.cottonmc.cotton.gui.impl.client.NarrationHelper; import io.github.cottonmc.cotton.gui.widget.WPanel; import io.github.cottonmc.cotton.gui.widget.WWidget; import org.jetbrains.annotations.ApiStatus; @@ -313,4 +315,9 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl return true; } + + @Override + protected void addElementNarrations(NarrationMessageBuilder builder) { + if (description != null) NarrationHelper.addNarrations(description.getRootPanel(), builder); + } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationHelper.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationHelper.java new file mode 100644 index 0000000..9b44210 --- /dev/null +++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationHelper.java @@ -0,0 +1,49 @@ +package io.github.cottonmc.cotton.gui.impl.client; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; +import net.minecraft.text.TranslatableText; + +import io.github.cottonmc.cotton.gui.widget.WPanel; +import io.github.cottonmc.cotton.gui.widget.WWidget; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Environment(EnvType.CLIENT) +public final class NarrationHelper { + public static void addNarrations(WPanel rootPanel, NarrationMessageBuilder builder) { + List<WWidget> narratableWidgets = getAllWidgets(rootPanel) + .filter(WWidget::isNarratable) + .filter(WWidget::isFocused) // TODO: || isHovered + .collect(Collectors.toList()); + + for (int i = 0, childCount = narratableWidgets.size(); i < childCount; i++) { + WWidget child = narratableWidgets.get(i); + + // replicates Screen.addElementNarrations + if (narratableWidgets.size() > 1) { + builder.put(NarrationPart.POSITION, new TranslatableText(NarrationMessages.Vanilla.SCREEN_POSITION_KEY, i + 1, childCount)); + + if (child.isFocused()) { // TODO: this check is currently useless but will be used with hovering + builder.put(NarrationPart.USAGE, NarrationMessages.Vanilla.COMPONENT_LIST_USAGE); + } + } + + child.addNarrations(builder.nextMessage()); + } + } + + private static Stream<WWidget> getAllWidgets(WPanel panel) { + return Stream.concat(Stream.of(panel), panel.streamChildren().flatMap(widget -> { + if (widget instanceof WPanel nested) { + return getAllWidgets(nested); + } + + return Stream.of(widget); + })); + } +} diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationMessages.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationMessages.java new file mode 100644 index 0000000..bc9ee48 --- /dev/null +++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationMessages.java @@ -0,0 +1,29 @@ +package io.github.cottonmc.cotton.gui.impl.client; + +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; + +public final class NarrationMessages { + public static final String ITEM_SLOT_TITLE_KEY = "widget.libgui.item_slot.narration.title"; + public static final String LABELED_SLIDER_TITLE_KEY = "widget.libgui.labeled_slider.narration.title"; + public static final Text PLAYER_INVENTORY_HOTBAR = new TranslatableText("widget.libgui.player_inventory.narration.hotbar"); + public static final Text SCROLL_BAR_TITLE = new TranslatableText("widget.libgui.scroll_bar.narration.title"); + public static final String SLIDER_MESSAGE_KEY = "widget.libgui.slider.narration.title"; + public static final Text SLIDER_USAGE = new TranslatableText("widget.libgui.slider.narration.usage"); + public static final String TAB_TITLE_KEY = "widget.libgui.tab.narration.title"; + public static final String TAB_POSITION_KEY = "widget.libgui.tab.narration.position"; + public static final String TEXT_FIELD_TITLE_KEY = "widget.libgui.text_field.narration.title"; + public static final String TEXT_FIELD_SUGGESTION_KEY = "widget.libgui.text_field.narration.suggestion"; + public static final String TOGGLE_BUTTON_NAMED_KEY = "widget.libgui.toggle_button.narration.named"; + public static final Text TOGGLE_BUTTON_OFF = new TranslatableText("widget.libgui.toggle_button.narration.off"); + public static final Text TOGGLE_BUTTON_ON = new TranslatableText("widget.libgui.toggle_button.narration.on"); + public static final String TOGGLE_BUTTON_UNNAMED_KEY = "widget.libgui.toggle_button.narration.unnamed"; + + public static final class Vanilla { + public static final Text BUTTON_USAGE_FOCUSED = new TranslatableText("narration.button.usage.focused"); + public static final Text BUTTON_USAGE_HOVERED = new TranslatableText("narration.button.usage.hovered"); + public static final Text COMPONENT_LIST_USAGE = new TranslatableText("narration.component_list.usage"); + public static final Text INVENTORY = new TranslatableText("container.inventory"); + public static final String SCREEN_POSITION_KEY = "narrator.position.screen"; + } +} diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java index 7fda1d9..2af6092 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java @@ -2,8 +2,12 @@ package io.github.cottonmc.cotton.gui.widget; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; +import net.minecraft.text.TranslatableText; import net.minecraft.util.math.MathHelper; +import io.github.cottonmc.cotton.gui.impl.client.NarrationMessages; import io.github.cottonmc.cotton.gui.widget.data.Axis; import io.github.cottonmc.cotton.gui.widget.data.InputResult; import org.jetbrains.annotations.Nullable; @@ -342,6 +346,13 @@ public abstract class WAbstractSlider extends WWidget { return dragging; } + @Environment(EnvType.CLIENT) + @Override + public void addNarrations(NarrationMessageBuilder builder) { + builder.put(NarrationPart.TITLE, new TranslatableText(NarrationMessages.SLIDER_MESSAGE_KEY, value, min, max)); + builder.put(NarrationPart.USAGE, NarrationMessages.SLIDER_USAGE); + } + /** * Tests if the key should decrease sliders with the specified direction. * diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java index 15cd6bb..c6fdfc2 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java @@ -3,6 +3,8 @@ package io.github.cottonmc.cotton.gui.widget; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; import net.minecraft.client.gui.widget.ClickableWidget; import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.client.util.math.MatrixStack; @@ -12,6 +14,7 @@ import net.minecraft.util.Identifier; import io.github.cottonmc.cotton.gui.client.LibGui; import io.github.cottonmc.cotton.gui.client.ScreenDrawing; +import io.github.cottonmc.cotton.gui.impl.client.NarrationMessages; import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment; import io.github.cottonmc.cotton.gui.widget.data.InputResult; import io.github.cottonmc.cotton.gui.widget.icon.Icon; @@ -220,6 +223,21 @@ public class WButton extends WWidget { } @Environment(EnvType.CLIENT) + @Override + public void addNarrations(NarrationMessageBuilder builder) { + builder.put(NarrationPart.TITLE, ClickableWidget.getNarrationMessage(getLabel())); + + if (isEnabled()) { + if (isFocused()) { + builder.put(NarrationPart.USAGE, NarrationMessages.Vanilla.BUTTON_USAGE_FOCUSED); + } else { + // TODO: hovering, again + builder.put(NarrationPart.USAGE, NarrationMessages.Vanilla.BUTTON_USAGE_HOVERED); + } + } + } + + @Environment(EnvType.CLIENT) static Identifier getTexture() { return LibGui.isDarkMode() ? DARK_WIDGETS_LOCATION : ClickableWidget.WIDGETS_TEXTURE; } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java index a99028c..18c812d 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java @@ -3,16 +3,22 @@ package io.github.cottonmc.cotton.gui.widget; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; import io.github.cottonmc.cotton.gui.GuiDescription; import io.github.cottonmc.cotton.gui.ValidatedSlot; import io.github.cottonmc.cotton.gui.client.BackgroundPainter; import io.github.cottonmc.cotton.gui.impl.VisualLogger; +import io.github.cottonmc.cotton.gui.impl.client.NarrationMessages; import io.github.cottonmc.cotton.gui.widget.icon.Icon; import org.jetbrains.annotations.Nullable; @@ -124,7 +130,12 @@ public class WItemSlot extends WWidget { * @see WPlayerInvPanel */ public static WItemSlot ofPlayerStorage(Inventory inventory) { - WItemSlot w = new WItemSlot(); + WItemSlot w = new WItemSlot() { + @Override + Text getExtraNarrationMessage() { + return inventory instanceof PlayerInventory inv ? inv.getDisplayName() : NarrationMessages.Vanilla.INVENTORY; + } + }; w.inventory = inventory; w.startIndex = 9; w.slotsWide = 9; @@ -429,6 +440,23 @@ public class WItemSlot extends WWidget { backgroundPainter = BackgroundPainter.SLOT; } + @Environment(EnvType.CLIENT) + @Override + public void addNarrations(NarrationMessageBuilder builder) { + if (focusedSlot >= 0) { + List<Text> parts = new ArrayList<>(); + Text extra = getExtraNarrationMessage(); + if (extra != null) parts.add(extra); + parts.add(new TranslatableText(NarrationMessages.ITEM_SLOT_TITLE_KEY, focusedSlot + 1, slotsWide * slotsHigh)); + builder.put(NarrationPart.TITLE, parts.toArray(new Text[0])); + } + } + + @Nullable + Text getExtraNarrationMessage() { + return null; + } + /** * A listener for changes in an item slot. * diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java index 911d547..2f972ff 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java @@ -2,12 +2,16 @@ package io.github.cottonmc.cotton.gui.widget; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; import net.minecraft.util.Identifier; import net.minecraft.util.math.Vec3f; import io.github.cottonmc.cotton.gui.client.ScreenDrawing; +import io.github.cottonmc.cotton.gui.impl.client.NarrationMessages; import io.github.cottonmc.cotton.gui.widget.data.Axis; import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment; import org.jetbrains.annotations.Nullable; @@ -212,6 +216,17 @@ public class WLabeledSlider extends WAbstractSlider { ScreenDrawing.texturedRect(matrices, x + halfWidth, y, halfWidth, 20, texture, buttonEndLeft, buttonTop, 200 * px, buttonTop + buttonHeight, 0xFFFFFFFF); } + @Environment(EnvType.CLIENT) + @Override + public void addNarrations(NarrationMessageBuilder builder) { + if (getLabel() != null) { + builder.put(NarrationPart.TITLE, new TranslatableText(NarrationMessages.LABELED_SLIDER_TITLE_KEY, getLabel(), value, min, max)); + builder.put(NarrationPart.USAGE, NarrationMessages.SLIDER_USAGE); + } else { + super.addNarrations(builder); + } + } + /** * A label updater updates the label of a slider based on the current value. * diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java index 912c1c0..3358d0a 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java @@ -7,6 +7,7 @@ import net.minecraft.client.util.math.MatrixStack; import io.github.cottonmc.cotton.gui.GuiDescription; import io.github.cottonmc.cotton.gui.client.BackgroundPainter; import io.github.cottonmc.cotton.gui.widget.data.Insets; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.AbstractList; @@ -247,6 +248,16 @@ public abstract class WPanel extends WWidget { } } + /** + * {@return a stream of all visible widgets in this panel} + * + * @since 4.2.0 + */ + @ApiStatus.Experimental + public final Stream<WWidget> streamChildren() { + return children.stream(); + } + @Override public String toString() { return getClass().getSimpleName() + " {\n" + children.stream().map(Object::toString).map(x -> x + ",").flatMap(x -> Stream.of(x.split("\n")).filter(y -> !y.isEmpty()).map(y -> "\t" + y)).collect(Collectors.joining("\n")) + "\n}"; diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WPlayerInvPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WPlayerInvPanel.java index c105924..d86e40a 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WPlayerInvPanel.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WPlayerInvPanel.java @@ -3,9 +3,11 @@ package io.github.cottonmc.cotton.gui.widget; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.text.Text; import io.github.cottonmc.cotton.gui.GuiDescription; import io.github.cottonmc.cotton.gui.client.BackgroundPainter; +import io.github.cottonmc.cotton.gui.impl.client.NarrationMessages; import org.jetbrains.annotations.Nullable; /** @@ -54,7 +56,12 @@ public class WPlayerInvPanel extends WPlainPanel { } inv = WItemSlot.ofPlayerStorage(playerInventory); - hotbar = WItemSlot.of(playerInventory, 0, 9, 1); + hotbar = new WItemSlot(playerInventory, 0, 9, 1, false) { + @Override + Text getExtraNarrationMessage() { + return NarrationMessages.PLAYER_INVENTORY_HOTBAR; + } + }; this.add(inv, 0, y); this.add(hotbar, 0, y + 58); } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java index 0eb7818..2882dbd 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java @@ -2,10 +2,13 @@ package io.github.cottonmc.cotton.gui.widget; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; import net.minecraft.client.util.math.MatrixStack; import io.github.cottonmc.cotton.gui.client.LibGui; import io.github.cottonmc.cotton.gui.client.ScreenDrawing; +import io.github.cottonmc.cotton.gui.impl.client.NarrationMessages; import io.github.cottonmc.cotton.gui.widget.data.Axis; import io.github.cottonmc.cotton.gui.widget.data.InputResult; @@ -264,4 +267,11 @@ public class WScrollBar extends WWidget { } if (this.value<0) this.value = 0; } + + @Environment(EnvType.CLIENT) + @Override + public void addNarrations(NarrationMessageBuilder builder) { + builder.put(NarrationPart.TITLE, NarrationMessages.SCROLL_BAR_TITLE); + builder.put(NarrationPart.USAGE, NarrationMessages.SLIDER_USAGE); + } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTabPanel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTabPanel.java index 2ee7e92..88c0db5 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTabPanel.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTabPanel.java @@ -4,16 +4,20 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; import net.minecraft.util.Identifier; import io.github.cottonmc.cotton.gui.client.BackgroundPainter; import io.github.cottonmc.cotton.gui.client.LibGui; import io.github.cottonmc.cotton.gui.client.ScreenDrawing; import io.github.cottonmc.cotton.gui.impl.LibGuiCommon; +import io.github.cottonmc.cotton.gui.impl.client.NarrationMessages; import io.github.cottonmc.cotton.gui.widget.data.Axis; import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment; import io.github.cottonmc.cotton.gui.widget.data.InputResult; @@ -354,10 +358,23 @@ public class WTabPanel extends WPanel { } } + @Environment(EnvType.CLIENT) @Override public void addTooltip(TooltipBuilder tooltip) { data.addTooltip(tooltip); } + + @Environment(EnvType.CLIENT) + @Override + public void addNarrations(NarrationMessageBuilder builder) { + Text label = data.getTitle(); // TODO: a separate narration message + + if (label != null) { + builder.put(NarrationPart.TITLE, new TranslatableText(NarrationMessages.TAB_TITLE_KEY, label)); + } + + builder.put(NarrationPart.POSITION, new TranslatableText(NarrationMessages.TAB_POSITION_KEY, tabWidgets.indexOf(this) + 1, tabWidgets.size())); + } } /** diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java index 60ae5d4..e9e2692 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java @@ -7,6 +7,8 @@ import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.BufferRenderer; import net.minecraft.client.render.GameRenderer; @@ -16,11 +18,13 @@ import net.minecraft.client.render.VertexFormats; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Matrix4f; import io.github.cottonmc.cotton.gui.client.BackgroundPainter; import io.github.cottonmc.cotton.gui.client.ScreenDrawing; +import io.github.cottonmc.cotton.gui.impl.client.NarrationMessages; import io.github.cottonmc.cotton.gui.widget.data.InputResult; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; @@ -431,7 +435,16 @@ public class WTextField extends WWidget { } } } - + + @Override + public void addNarrations(NarrationMessageBuilder builder) { + builder.put(NarrationPart.TITLE, new TranslatableText(NarrationMessages.TEXT_FIELD_TITLE_KEY, text)); + + if (suggestion != null) { + builder.put(NarrationPart.HINT, new TranslatableText(NarrationMessages.TEXT_FIELD_SUGGESTION_KEY, suggestion)); + } + } + /** * From an X offset past the left edge of a TextRenderer.draw, finds out what the closest caret * position (division between letters) is. diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java index 8953f4d..d4fb728 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java @@ -3,15 +3,19 @@ package io.github.cottonmc.cotton.gui.widget; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.screen.narration.NarrationPart; import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; import net.minecraft.util.Identifier; import io.github.cottonmc.cotton.gui.client.LibGui; import io.github.cottonmc.cotton.gui.client.ScreenDrawing; import io.github.cottonmc.cotton.gui.impl.LibGuiCommon; +import io.github.cottonmc.cotton.gui.impl.client.NarrationMessages; import io.github.cottonmc.cotton.gui.widget.data.InputResult; import io.github.cottonmc.cotton.gui.widget.data.Texture; import org.jetbrains.annotations.Nullable; @@ -202,4 +206,26 @@ public class WToggleButton extends WWidget { this.focusImage = focusImage; return this; } + + @Environment(EnvType.CLIENT) + @Override + public void addNarrations(NarrationMessageBuilder builder) { + Text onOff = isOn ? NarrationMessages.TOGGLE_BUTTON_ON : NarrationMessages.TOGGLE_BUTTON_OFF; + Text title; + + if (label != null) { + title = new TranslatableText(NarrationMessages.TOGGLE_BUTTON_NAMED_KEY, label, onOff); + } else { + title = new TranslatableText(NarrationMessages.TOGGLE_BUTTON_UNNAMED_KEY, onOff); + } + + builder.put(NarrationPart.TITLE, title); + + if (isFocused()) { + builder.put(NarrationPart.USAGE, NarrationMessages.Vanilla.BUTTON_USAGE_FOCUSED); + } else { + // TODO: hovering, again + builder.put(NarrationPart.USAGE, NarrationMessages.Vanilla.BUTTON_USAGE_HOVERED); + } + } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java index 30e14d5..3beacee 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java @@ -6,6 +6,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.util.math.MatrixStack; import io.github.cottonmc.cotton.gui.GuiDescription; @@ -465,6 +466,30 @@ public class WWidget { } /** + * {@return whether this widget can be narrated} + * + * @see #addNarrations(NarrationMessageBuilder) + * @since 4.2.0 + */ + public boolean isNarratable() { + return true; + } + + /** + * Adds the narrations of this widget to a narration builder. + * Narrations will only apply if this widget {@linkplain #isNarratable() is narratable}. + * + * <p>As of LibGui 4.2.0, the widget also needs to be {@linkplain #canFocus() focusable}, but that is + * planned to be changed in the future to include "hoverable" widgets. + * + * @param builder the narration builder, cannot be null + * @since 4.2.0 + */ + @Environment(EnvType.CLIENT) + public void addNarrations(NarrationMessageBuilder builder) { + } + + /** * Tests if the provided key code is an activation key for widgets. * * <p>The activation keys are Enter, keypad Enter, and Space. diff --git a/src/main/resources/assets/libgui/lang/en_us.json b/src/main/resources/assets/libgui/lang/en_us.json index 5ed8bfb..4f0f9a1 100644 --- a/src/main/resources/assets/libgui/lang/en_us.json +++ b/src/main/resources/assets/libgui/lang/en_us.json @@ -1,4 +1,18 @@ { - "options.libgui.libgui_settings": "LibGui Settings", - "option.libgui.darkmode": "Dark Mode" -} + "options.libgui.libgui_settings": "LibGui Settings", + "option.libgui.darkmode": "Dark Mode", + "widget.libgui.item_slot.narration.title": "Item slot %s out of %s", + "widget.libgui.labeled_slider.narration.title": "%s slider: at %s between %s and %s", + "widget.libgui.player_inventory.narration.hotbar": "Hotbar", + "widget.libgui.scroll_bar.narration.title": "Scroll bar", + "widget.libgui.slider.narration.title": "Slider: at %s between %s and %s", + "widget.libgui.slider.narration.usage": "Move by dragging or with arrow keys", + "widget.libgui.tab.narration.title": "%s tab", + "widget.libgui.tab.narration.position": "Tab %s out of %s", + "widget.libgui.text_field.narration.title": "Text field: %s", + "widget.libgui.text_field.narration.suggestion": "Suggestion: %s", + "widget.libgui.toggle_button.narration.unnamed": "Toggle button: %s", + "widget.libgui.toggle_button.narration.named": "Toggle button: %s (%s)", + "widget.libgui.toggle_button.narration.on": "On", + "widget.libgui.toggle_button.narration.off": "Off" +} |