aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java22
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java26
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/CottonScreenImpl.java3
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java38
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationHelper.java49
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationMessages.java29
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java11
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java17
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java59
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java8
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java15
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WPanel.java12
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WPlayerInvPanel.java9
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WScrollBar.java10
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WTabPanel.java17
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java8
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WTextField.java15
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java25
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java69
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/data/ObservableProperty.java162
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/data/ObservableView.java75
-rw-r--r--src/main/resources/assets/libgui/lang/en_us.json20
22 files changed, 669 insertions, 30 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 cb80707..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;
@@ -36,6 +38,8 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
@Nullable
protected WWidget lastResponder = null;
+
+ private final MouseInputHandler<CottonClientScreen> mouseInputHandler = new MouseInputHandler<>(this);
public CottonClientScreen(GuiDescription description) {
this(new LiteralText(""), description);
@@ -46,7 +50,8 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
this.description = description;
description.getRootPanel().validate(description);
}
-
+
+ @Override
public GuiDescription getDescription() {
return description;
}
@@ -176,7 +181,7 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return true;
- MouseInputHandler.onMouseDown(description, this, containerX, containerY, mouseButton);
+ mouseInputHandler.onMouseDown(containerX, containerY, mouseButton);
return true;
}
@@ -187,7 +192,7 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
super.mouseReleased(mouseX, mouseY, mouseButton);
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
- MouseInputHandler.onMouseUp(description, this, containerX, containerY, mouseButton);
+ mouseInputHandler.onMouseUp(containerX, containerY, mouseButton);
return true;
}
@@ -199,7 +204,7 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
- MouseInputHandler.onMouseDrag(description, this, containerX, containerY, mouseButton, deltaX, deltaY);
+ mouseInputHandler.onMouseDrag(containerX, containerY, mouseButton, deltaX, deltaY);
return true;
}
@@ -210,7 +215,7 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
- MouseInputHandler.onMouseScroll(description, containerX, containerY, amount);
+ mouseInputHandler.onMouseScroll(containerX, containerY, amount);
return true;
}
@@ -221,7 +226,7 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
- MouseInputHandler.onMouseMove(description, containerX, containerY);
+ mouseInputHandler.onMouseMove(containerX, containerY);
}
@Override
@@ -264,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 87d9453..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;
@@ -8,12 +9,15 @@ import net.minecraft.text.LiteralText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
+import io.github.cottonmc.cotton.gui.GuiDescription;
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;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL11;
@@ -26,6 +30,7 @@ import org.lwjgl.opengl.GL11;
public class CottonInventoryScreen<T extends SyncedGuiDescription> extends HandledScreen<T> implements CottonScreenImpl {
protected SyncedGuiDescription description;
@Nullable protected WWidget lastResponder = null;
+ private final MouseInputHandler<CottonInventoryScreen<T>> mouseInputHandler = new MouseInputHandler<>(this);
/**
* Constructs a new screen without a title.
@@ -83,6 +88,12 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
VisualLogger.reset();
}
+ @ApiStatus.Internal
+ @Override
+ public GuiDescription getDescription() {
+ return description;
+ }
+
@Nullable
@Override
public WWidget getLastResponder() {
@@ -187,7 +198,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return result;
- MouseInputHandler.onMouseDown(description, this, containerX, containerY, mouseButton);
+ mouseInputHandler.onMouseDown(containerX, containerY, mouseButton);
return true;
}
@@ -197,7 +208,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
super.mouseReleased(mouseX, mouseY, mouseButton);
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
- MouseInputHandler.onMouseUp(description, this, containerX, containerY, mouseButton);
+ mouseInputHandler.onMouseUp(containerX, containerY, mouseButton);
return true;
}
@@ -208,7 +219,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
- MouseInputHandler.onMouseDrag(description, this, containerX, containerY, mouseButton, deltaX, deltaY);
+ mouseInputHandler.onMouseDrag(containerX, containerY, mouseButton, deltaX, deltaY);
return true;
}
@@ -219,7 +230,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
- MouseInputHandler.onMouseScroll(description, containerX, containerY, amount);
+ mouseInputHandler.onMouseScroll(containerX, containerY, amount);
return true;
}
@@ -230,7 +241,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
- MouseInputHandler.onMouseMove(description, containerX, containerY);
+ mouseInputHandler.onMouseMove(containerX, containerY);
}
@Override
@@ -304,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/CottonScreenImpl.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/CottonScreenImpl.java
index 2ef9632..cd215b3 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/CottonScreenImpl.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/CottonScreenImpl.java
@@ -5,11 +5,14 @@ import net.fabricmc.api.Environment;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Style;
+import io.github.cottonmc.cotton.gui.GuiDescription;
import io.github.cottonmc.cotton.gui.widget.WWidget;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public interface CottonScreenImpl {
+ GuiDescription getDescription();
+
@Nullable
WWidget getLastResponder();
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java
index 45fc17f..055df75 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java
@@ -2,9 +2,9 @@ package io.github.cottonmc.cotton.gui.impl.client;
import net.minecraft.client.gui.screen.Screen;
-import io.github.cottonmc.cotton.gui.GuiDescription;
import io.github.cottonmc.cotton.gui.widget.WWidget;
import io.github.cottonmc.cotton.gui.widget.data.InputResult;
+import io.github.cottonmc.cotton.gui.widget.data.ObservableProperty;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
@@ -12,10 +12,21 @@ import java.util.function.Function;
/**
* The implementation for mouse inputs.
*/
-public final class MouseInputHandler {
- public static void onMouseDown(GuiDescription description, CottonScreenImpl screen, int containerX, int containerY, int mouseButton) {
+public final class MouseInputHandler<S extends Screen & CottonScreenImpl> {
+ private final S screen;
+ private final ObservableProperty<WWidget> hovered = ObservableProperty.of(null);
+
+ public MouseInputHandler(S screen) {
+ this.screen = screen;
+ hovered.addListener((property, from, to) -> {
+ if (from != null) from.setHovered(false);
+ if (to != null) to.setHovered(true);
+ });
+ }
+
+ public void onMouseDown(int containerX, int containerY, int mouseButton) {
if (screen.getLastResponder() == null) {
- WWidget lastResponder = description.getRootPanel().hit(containerX, containerY);
+ WWidget lastResponder = screen.getDescription().getRootPanel().hit(containerX, containerY);
screen.setLastResponder(lastResponder);
if (lastResponder != null) {
runTree(
@@ -28,7 +39,7 @@ public final class MouseInputHandler {
}
}
- public static <S extends Screen & CottonScreenImpl> void onMouseUp(GuiDescription description, S screen, int containerX, int containerY, int mouseButton) {
+ public void onMouseUp(int containerX, int containerY, int mouseButton) {
WWidget lastResponder = screen.getLastResponder();
if (lastResponder != null) {
@@ -48,7 +59,7 @@ public final class MouseInputHandler {
}
} else {
runTree(
- description.getRootPanel().hit(containerX, containerY),
+ screen.getDescription().getRootPanel().hit(containerX, containerY),
widget -> widget.onMouseUp(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), mouseButton)
);
}
@@ -56,7 +67,7 @@ public final class MouseInputHandler {
screen.setLastResponder(null);
}
- public static <S extends Screen & CottonScreenImpl> void onMouseDrag(GuiDescription description, S screen, int containerX, int containerY, int mouseButton, double deltaX, double deltaY) {
+ public void onMouseDrag(int containerX, int containerY, int mouseButton, double deltaX, double deltaY) {
WWidget lastResponder = screen.getLastResponder();
if (lastResponder != null) {
@@ -68,22 +79,25 @@ public final class MouseInputHandler {
if (containerX < 0 || containerY < 0 || containerX >= width || containerY >= height) return;
runTree(
- description.getRootPanel().hit(containerX, containerY),
+ screen.getDescription().getRootPanel().hit(containerX, containerY),
widget -> widget.onMouseDrag(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), mouseButton, deltaX, deltaY)
);
}
}
- public static void onMouseScroll(GuiDescription description, int containerX, int containerY, double amount) {
+ public void onMouseScroll(int containerX, int containerY, double amount) {
runTree(
- description.getRootPanel().hit(containerX, containerY),
+ screen.getDescription().getRootPanel().hit(containerX, containerY),
widget -> widget.onMouseScroll(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), amount)
);
}
- public static void onMouseMove(GuiDescription description, int containerX, int containerY) {
+ public void onMouseMove(int containerX, int containerY) {
+ WWidget hit = screen.getDescription().getRootPanel().hit(containerX, containerY);
+ hovered.set(hit);
+
runTree(
- description.getRootPanel().hit(containerX, containerY),
+ hit,
widget -> widget.onMouseMove(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY())
);
}
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..54567be
--- /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)
+ .collect(Collectors.toList());
+
+ for (int i = 0, childCount = narratableWidgets.size(); i < childCount; i++) {
+ WWidget child = narratableWidgets.get(i);
+ if (!child.isFocused() && !child.isHovered()) continue;
+
+ // replicates Screen.addElementNarrations
+ if (narratableWidgets.size() > 1) {
+ builder.put(NarrationPart.POSITION, new TranslatableText(NarrationMessages.Vanilla.SCREEN_POSITION_KEY, i + 1, childCount));
+
+ if (child.isFocused()) {
+ 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..533e436 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,20 @@ 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 if (isHovered()) {
+ 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..a05b364 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,23 @@ 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.data.InputResult;
import io.github.cottonmc.cotton.gui.widget.icon.Icon;
import org.jetbrains.annotations.Nullable;
@@ -75,10 +82,12 @@ public class WItemSlot extends WWidget {
private boolean insertingAllowed = true;
private boolean takingAllowed = true;
private int focusedSlot = -1;
+ private int hoveredSlot = -1;
private Predicate<ItemStack> filter = DEFAULT_FILTER;
private final Set<ChangeListener> listeners = new HashSet<>();
public WItemSlot(Inventory inventory, int startIndex, int slotsWide, int slotsHigh, boolean big) {
+ this();
this.inventory = inventory;
this.startIndex = startIndex;
this.slotsWide = slotsWide;
@@ -87,7 +96,12 @@ public class WItemSlot extends WWidget {
//this.ltr = ltr;
}
- private WItemSlot() {}
+ private WItemSlot() {
+ hoveredProperty().addListener((property, from, to) -> {
+ assert to != null;
+ if (!to) hoveredSlot = -1;
+ });
+ }
public static WItemSlot of(Inventory inventory, int index) {
WItemSlot w = new WItemSlot();
@@ -124,7 +138,12 @@ public class WItemSlot extends WWidget {
* @see WPlayerInvPanel
*/
public static WItemSlot ofPlayerStorage(Inventory inventory) {
- WItemSlot w = new WItemSlot();
+ WItemSlot w = new WItemSlot() {
+ @Override
+ protected Text getNarrationName() {
+ return inventory instanceof PlayerInventory inv ? inv.getDisplayName() : NarrationMessages.Vanilla.INVENTORY;
+ }
+ };
w.inventory = inventory;
w.startIndex = 9;
w.slotsWide = 9;
@@ -415,6 +434,14 @@ public class WItemSlot extends WWidget {
}
@Override
+ public InputResult onMouseMove(int x, int y) {
+ int slotX = x / 18;
+ int slotY = y / 18;
+ hoveredSlot = slotX + slotY * slotsWide;
+ return InputResult.PROCESSED;
+ }
+
+ @Override
public void onHidden() {
super.onHidden();
@@ -429,6 +456,34 @@ public class WItemSlot extends WWidget {
backgroundPainter = BackgroundPainter.SLOT;
}
+ @Environment(EnvType.CLIENT)
+ @Override
+ public void addNarrations(NarrationMessageBuilder builder) {
+ List<Text> parts = new ArrayList<>();
+ Text name = getNarrationName();
+ if (name != null) parts.add(name);
+
+ if (focusedSlot >= 0) {
+ parts.add(new TranslatableText(NarrationMessages.ITEM_SLOT_TITLE_KEY, focusedSlot + 1, slotsWide * slotsHigh));
+ } else if (hoveredSlot >= 0) {
+ parts.add(new TranslatableText(NarrationMessages.ITEM_SLOT_TITLE_KEY, hoveredSlot + 1, slotsWide * slotsHigh));
+ }
+
+ builder.put(NarrationPart.TITLE, parts.toArray(new Text[0]));
+ }
+
+ /**
+ * Returns a "narration name" for this slot.
+ * It's narrated before the slot index. One example of a narration name would be "hotbar" for the player's hotbar.
+ *
+ * @return the narration name, or null if there's none for this slot
+ * @since 4.2.0
+ */
+ @Nullable
+ protected Text getNarrationName() {
+ return null;
+ }
+
/**
* A listener for changes in an item slot.
*
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
index 5c6b2da..83f0700 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
@@ -5,6 +5,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.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Style;
@@ -261,4 +263,10 @@ public class WLabel extends WWidget {
this.verticalAlignment = align;
return this;
}
+
+ @Environment(EnvType.CLIENT)
+ @Override
+ public void addNarrations(NarrationMessageBuilder builder) {
+ builder.put(NarrationPart.TITLE, text);
+ }
}
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..204ea93 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,17 @@ public abstract class WPanel extends WWidget {
}
}
+ /**
+ * {@return a stream of all visible widgets in this panel}
+ *
+ * @experimental
+ * @since 4.2.0
+ */
+ @ApiStatus.Experimental
+ public final Stream<WWidget> streamChildren() {
+ return children.stream();
+ }
+
@Override