From a34752e2ee0e15a7a4feeae199f2e05998832450 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Wed, 27 Sep 2023 14:47:17 +0300 Subject: Texture: Support GUI sprites --- .../cotton/gui/client/BackgroundPainter.java | 8 ++ .../cottonmc/cotton/gui/client/ScreenDrawing.java | 50 ++++++++++- .../io/github/cottonmc/cotton/gui/widget/WBar.java | 12 ++- .../cottonmc/cotton/gui/widget/data/Texture.java | 97 +++++++++++++++++++++- .../cottonmc/test/client/LibGuiTestClient.java | 1 + .../cottonmc/test/client/TextureTestGui.java | 94 +++++++++++++++++++++ 6 files changed, 253 insertions(+), 9 deletions(-) create mode 100644 src/testMod/java/io/github/cottonmc/test/client/TextureTestGui.java diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/BackgroundPainter.java b/src/main/java/io/github/cottonmc/cotton/gui/client/BackgroundPainter.java index 52bd317..251fed7 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/client/BackgroundPainter.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/client/BackgroundPainter.java @@ -129,6 +129,9 @@ public interface BackgroundPainter { /** * Creates a new nine-patch background painter with a custom configuration. * + *
This method cannot be used for {@linkplain Texture.Type#GUI_SPRITE GUI sprites}. Instead, you can use the
+ * vanilla nine-slice mechanism or use a standalone texture referring to the same file.
+ *
* @param texture the background painter texture
* @param configurator a consumer that configures the {@link NinePatch.Builder}
* @return the created nine-patch background painter
@@ -136,8 +139,13 @@ public interface BackgroundPainter {
* @see NinePatch
* @see NinePatch.Builder
* @see NinePatchBackgroundPainter
+ * @throws IllegalArgumentException when the texture is not {@linkplain Texture.Type#STANDALONE standalone}
*/
public static NinePatchBackgroundPainter createNinePatch(Texture texture, Consumer Each texture has a type: it's either a {@linkplain Type#STANDALONE standalone texture file} or
+ * a {@linkplain Type#GUI_SPRITE sprite on the GUI sprite atlas}. Their properties are slightly different.
+ *
+ * GUI sprites can use their full range of features such as tiling, stretching and nine-slice drawing modes,
+ * while standalone textures are only drawn stretched.
+ *
+ * The format of the image ID depends on the type:
+ * Note that the image ID can only be passed to non-{@code Texture} overloads of
+ * The image IDs of standalone textures contain the full file path to the texture inside
+ * the {@code assets/ The image IDs of GUI sprites only contain the subpath to the texture inside the sprite directory without
+ * the file extension. For example, {@code my_mod:example} refers to
+ * {@code assets/my_mod/textures/gui/sprites/example.png}.
+ */
+ GUI_SPRITE,
}
}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java b/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java
index 57c2790..a9500ae 100644
--- a/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java
+++ b/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java
@@ -68,6 +68,7 @@ public class LibGuiTestClient implements ClientModInitializer {
.then(literal("#196").executes(openScreen(client -> new Issue196TestGui())))
.then(literal("darkmode").executes(openScreen(client -> new DarkModeTestGui())))
.then(literal("titlealignment").executes(openScreen(Text.literal("test title"), client -> new TitleAlignmentTestGui())))
+ .then(literal("texture").executes(openScreen(client -> new TextureTestGui())))
));
}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/TextureTestGui.java b/src/testMod/java/io/github/cottonmc/test/client/TextureTestGui.java
new file mode 100644
index 0000000..6925a3b
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/TextureTestGui.java
@@ -0,0 +1,94 @@
+package io.github.cottonmc.test.client;
+
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WLabeledSlider;
+import io.github.cottonmc.cotton.gui.widget.WPanel;
+import io.github.cottonmc.cotton.gui.widget.WSlider;
+import io.github.cottonmc.cotton.gui.widget.WSprite;
+import io.github.cottonmc.cotton.gui.widget.WTabPanel;
+import io.github.cottonmc.cotton.gui.widget.data.Axis;
+import io.github.cottonmc.cotton.gui.widget.data.Insets;
+import io.github.cottonmc.cotton.gui.widget.data.Texture;
+import io.github.cottonmc.cotton.gui.widget.icon.TextureIcon;
+
+import java.util.function.IntConsumer;
+
+public class TextureTestGui extends LightweightGuiDescription {
+ public TextureTestGui() {
+ WTabPanel root = new WTabPanel();
+
+ var panelSprite = new Texture(new Identifier("libgui:widget/panel_light"), Texture.Type.GUI_SPRITE);
+ var panelTexture = new Texture(new Identifier("libgui:textures/gui/sprites/widget/panel_light.png"), Texture.Type.STANDALONE);
+ var simpleSprite = new Texture(new Identifier("minecraft:icon/video_link"), Texture.Type.GUI_SPRITE);
+
+ root.add(createPanel(panelSprite), tab -> tab.icon(new TextureIcon(panelSprite)).tooltip(Text.literal("Nine-slice sprite")));
+ root.add(createPanel(simpleSprite), tab -> tab.icon(new TextureIcon(simpleSprite)).tooltip(Text.literal("Simple sprite")));
+ root.add(createPanel(panelTexture), tab -> tab.icon(new TextureIcon(panelTexture)).tooltip(Text.literal("Standalone")));
+ setRootPanel(root);
+ root.validate(this);
+ }
+
+ @Override
+ public void addPainters() {
+ // Remove tab panel background
+ }
+
+ private WPanel createPanel(Texture texture) {
+ WSprite sprite = new WSprite(texture);
+
+ WLabeledSlider red = new WLabeledSlider(0, 255, Axis.HORIZONTAL, Text.literal("Red"));
+ WLabeledSlider green = new WLabeledSlider(0, 255, Axis.HORIZONTAL, Text.literal("Green"));
+ WLabeledSlider blue = new WLabeledSlider(0, 255, Axis.HORIZONTAL, Text.literal("Blue"));
+ WLabeledSlider alpha = new WLabeledSlider(0, 255, Axis.HORIZONTAL, Text.literal("Alpha"));
+
+ red.setValue(255);
+ green.setValue(255);
+ blue.setValue(255);
+ alpha.setValue(255);
+
+ WSlider u1 = new WSlider(0, 100, Axis.HORIZONTAL);
+ WSlider u2 = new WSlider(0, 100, Axis.HORIZONTAL);
+ WSlider v1 = new WSlider(0, 100, Axis.VERTICAL);
+ WSlider v2 = new WSlider(0, 100, Axis.VERTICAL);
+
+ u2.setValue(100);
+ v2.setValue(100);
+
+ IntConsumer tintListener = unused -> {
+ sprite.setTint(blue.getValue() | (green.getValue() << 8) | (red.getValue() << 16) | (alpha.getValue() << 24));
+ };
+ red.setValueChangeListener(tintListener);
+ green.setValueChangeListener(tintListener);
+ blue.setValueChangeListener(tintListener);
+ alpha.setValueChangeListener(tintListener);
+
+ IntConsumer uvListener = unused -> {
+ sprite.setUv(u1.getValue() * 0.01f, v1.getValue() * 0.01f, u2.getValue() * 0.01f, v2.getValue() * 0.01f);
+ };
+ u1.setValueChangeListener(uvListener);
+ u2.setValueChangeListener(uvListener);
+ v1.setValueChangeListener(uvListener);
+ v2.setValueChangeListener(uvListener);
+
+ WGridPanel panel = new WGridPanel(20);
+ panel.setInsets(Insets.ROOT_PANEL);
+ panel.setGaps(3, 3);
+
+ panel.add(red, 0, 0, 3, 1);
+ panel.add(green, 3, 0, 3, 1);
+ panel.add(blue, 0, 1, 3, 1);
+ panel.add(alpha, 3, 1, 3, 1);
+
+ panel.add(u1, 2, 2, 4, 1);
+ panel.add(u2, 2, 3, 4, 1);
+ panel.add(v1, 0, 4, 1, 4);
+ panel.add(v2, 1, 4, 1, 4);
+
+ panel.add(sprite, 2, 4, 4, 4);
+ return panel;
+ }
+}
--
cgit
Types
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * Type
+ * File path
+ * Image ID
+ *
+ *
+ * {@link Type#STANDALONE STANDALONE}
+ * {@code assets/my_mod/textures/widget/example.png}
+ * {@code my_mod:textures/widget/example.png}
+ *
+ *
+ *
+ * {@link Type#GUI_SPRITE GUI_SPRITE}
+ * {@code assets/my_mod/textures/gui/sprites/example.png}
+ * {@code my_mod:example}
+ * {@link io.github.cottonmc.cotton.gui.client.ScreenDrawing ScreenDrawing}.texturedRect()
+ * when the {@link #type() type} is {@link Type#STANDALONE}. GUI sprites need specialised code for drawing them,
+ * and they need to be drawn with specific {@code Texture}-accepting methods
+ * or {@link net.minecraft.client.gui.DrawContext}.
+ *
* @param image the image of this texture
+ * @param type the type of this texture
* @param u1 the start U-coordinate, between 0 and 1
* @param v1 the start V-coordinate, between 0 and 1
* @param u2 the end U-coordinate, between 0 and 1
* @param v2 the end V-coordinate, between 0 and 1
* @since 3.0.0
*/
-public record Texture(Identifier image, float u1, float v1, float u2, float v2) {
+public record Texture(Identifier image, Type type, float u1, float v1, float u2, float v2) {
/**
* Constructs a new texture that uses the full image.
*
* @param image the image
+ * @param type the type
+ * @throws NullPointerException if the image or the type is null
+ */
+ public Texture(Identifier image, Type type) {
+ this(image, type, 0, 0, 1, 1);
+ }
+
+ /**
+ * Constructs a new standalone texture with custom UV values.
+ *
+ * @param image the image of this texture
+ * @param u1 the start U-coordinate, between 0 and 1
+ * @param v1 the start V-coordinate, between 0 and 1
+ * @param u2 the end U-coordinate, between 0 and 1
+ * @param v2 the end V-coordinate, between 0 and 1
+ * @throws NullPointerException if the image is null
+ */
+ public Texture(Identifier image, float u1, float v1, float u2, float v2) {
+ this(image, Type.STANDALONE, u1, v1, u2, v2);
+ }
+
+ /**
+ * Constructs a new standalone texture that uses the full image.
+ *
+ * @param image the image
* @throws NullPointerException if the image is null
*/
public Texture(Identifier image) {
- this(image, 0, 0, 1, 1);
+ this(image, Type.STANDALONE, 0, 0, 1, 1);
}
/**
* Constructs a new texture with custom UV values.
*
* @param image the image
+ * @param type the type
* @param u1 the left U coordinate
* @param v1 the top V coordinate
* @param u2 the right U coordinate
* @param v2 the bottom V coordinate
- * @throws NullPointerException if the image is null
+ * @throws NullPointerException if the image or the type is null
*/
public Texture {
Objects.requireNonNull(image, "image");
+ Objects.requireNonNull(type, "type");
}
/**
@@ -49,6 +113,31 @@ public record Texture(Identifier image, float u1, float v1, float u2, float v2)
* @return the created texture
*/
public Texture withUv(float u1, float v1, float u2, float v2) {
- return new Texture(image, u1, v1, u2, v2);
+ return new Texture(image, type, u1, v1, u2, v2);
+ }
+
+ /**
+ * A {@link Texture}'s type. It represents the location of the texture.
+ *
+ * @since 9.0.0
+ */
+ public enum Type {
+ /**
+ * A texture in a standalone texture file.
+ *
+ *