aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.gradle2
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/BackgroundPainter.java60
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiClient.java4
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/NinePatchMetadataLoader.java91
4 files changed, 137 insertions, 20 deletions
diff --git a/build.gradle b/build.gradle
index 0bf075b..1bd45f8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -59,7 +59,7 @@ dependencies {
compileOnly ("com.google.code.findbugs:jsr305:3.0.2") { transitive = false }
- def modmenu = "1.8.1+build.17"
+ def modmenu = "1.8.5+build.23"
modCompileOnly "io.github.prospector:modmenu:$modmenu"
modRuntime "io.github.prospector:modmenu:$modmenu" // for testing
}
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 65cf95f..24cf6ab 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
@@ -5,6 +5,8 @@ import io.github.cottonmc.cotton.gui.widget.WWidget;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
+import javax.annotation.Nullable;
+
/**
* Background painters are used to paint the background of a widget.
* The background painter instance of a widget can be changed to customize the look of a widget.
@@ -128,11 +130,30 @@ public interface BackgroundPainter {
*
* <p>Nine-patch textures are separated into nine sections: four corners, four edges and a center part.
* The edges and the center are either tiled or stretched, depending on the {@linkplain BackgroundPainter.NinePatch.Mode mode},
- * to fill the area between the corners. The default mode is {@link BackgroundPainter.NinePatch.Mode#TILING}.
+ * to fill the area between the corners. By default, the texture mode is loaded from the texture metadata.
+ * The default mode for that is {@link BackgroundPainter.NinePatch.Mode#STRETCHING}.
*
* <p>{@code NinePatch} painters have a customizable padding that can be applied.
* For example, a GUI panel for a container block might have a padding of 8 pixels, like {@link BackgroundPainter#VANILLA}.
* You can set the padding using {@link NinePatch#setPadding(int)}.
+ *
+ * <h2>Nine-patch metadata</h2>
+ * You can specify metadata for a nine-patch texture in a resource pack by creating a metadata file.
+ * Metadata files can currently specify the filling mode of the painter that paints the texture.
+ * <p>The metadata file for a texture has to be placed in the same directory as the texture.
+ * The file name must be {@code X.9patch} where X is the texture file name (including .png).
+ * <p>Metadata files use {@linkplain java.util.Properties .properties format} with the following keys:
+ * <table border="1">
+ * <caption>Properties</caption>
+ * <tr>
+ * <th>Key</th>
+ * <th>Value</th>
+ * </tr>
+ * <tr>
+ * <td>{@code mode}</td>
+ * <td>{@link Mode#STRETCHING stretching} | {@link Mode#TILING tiling}</td>
+ * </tr>
+ * </table>
*/
public static class NinePatch implements BackgroundPainter {
private final Identifier texture;
@@ -142,7 +163,7 @@ public interface BackgroundPainter {
private int leftPadding = 0;
private int bottomPadding = 0;
private int rightPadding = 0;
- private Mode mode = Mode.STRETCHING;
+ private Mode mode = null;
/**
* Creates a nine-patch background painter with 4 px corners and a 0.25 cornerUv (corner fraction of whole texture).
@@ -234,28 +255,18 @@ public interface BackgroundPainter {
return cornerUv;
}
+ @Nullable
public Mode getMode() {
return mode;
}
- public NinePatch setMode(Mode mode) {
- this.mode = mode;
- return this;
- }
-
- /**
- * Sets the {@linkplain Mode mode} of this painter to {@link Mode#STRETCHING}.
- */
- public NinePatch stretch() {
- this.mode = Mode.STRETCHING;
- return this;
- }
-
/**
- * Sets the {@linkplain Mode mode} of this painter to {@link Mode#TILING}.
+ * Sets the {@linkplain Mode mode} of this painter to the specified mode.
+ * <p>If the {@code mode} is not null, it will override the one specified in the texture metadata.
+ * A null mode uses the texture metadata.
*/
- public NinePatch tile() {
- this.mode = Mode.TILING;
+ public NinePatch setMode(@Nullable Mode mode) {
+ this.mode = mode;
return this;
}
@@ -271,6 +282,7 @@ public interface BackgroundPainter {
int y2 = top + height - cornerSize;
float uv1 = cornerUv;
float uv2 = 1.0f - cornerUv;
+ Mode mode = this.mode != null ? this.mode : NinePatchMetadataLoader.INSTANCE.getProperties(texture).getMode();
ScreenDrawing.texturedRect(left, top, cornerSize, cornerSize, texture, 0, 0, uv1, uv1, 0xFF_FFFFFF);
ScreenDrawing.texturedRect(x2, top, cornerSize, cornerSize, texture, uv2, 0, 1, uv1, 0xFF_FFFFFF);
@@ -322,14 +334,24 @@ public interface BackgroundPainter {
public enum Mode {
/**
* The texture is stretched to fill the edges and the center.
+ * This is the default mode.
*/
STRETCHING,
/**
* The texture is tiled to fill the edges and the center.
- * This is the default mode.
*/
TILING;
+
+ @Nullable
+ static Mode fromString(String str) {
+ if (str == null) return null;
+
+ if (str.equalsIgnoreCase("stretching")) return STRETCHING;
+ if (str.equalsIgnoreCase("tiling")) return TILING;
+
+ return null;
+ }
}
}
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiClient.java b/src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiClient.java
index b06369a..d457e50 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiClient.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/LibGuiClient.java
@@ -5,8 +5,10 @@ import blue.endless.jankson.JsonElement;
import blue.endless.jankson.JsonObject;
import io.github.cottonmc.jankson.JanksonFactory;
import net.fabricmc.api.ClientModInitializer;
+import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.loader.api.FabricLoader;
+import net.minecraft.resource.ResourceType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -24,6 +26,8 @@ public class LibGuiClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
config = loadConfig();
+
+ ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(NinePatchMetadataLoader.INSTANCE);
}
public static LibGuiConfig loadConfig() {
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/NinePatchMetadataLoader.java b/src/main/java/io/github/cottonmc/cotton/gui/client/NinePatchMetadataLoader.java
new file mode 100644
index 0000000..daa1b45
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/NinePatchMetadataLoader.java
@@ -0,0 +1,91 @@
+package io.github.cottonmc.cotton.gui.client;
+
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
+import net.minecraft.resource.Resource;
+import net.minecraft.resource.ResourceManager;
+import net.minecraft.resource.SinglePreparationResourceReloadListener;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.profiler.Profiler;
+
+import java.io.InputStream;
+import java.util.*;
+
+@Environment(EnvType.CLIENT)
+public class NinePatchMetadataLoader extends SinglePreparationResourceReloadListener<Map<Identifier, Properties>> implements IdentifiableResourceReloadListener {
+ public static final NinePatchMetadataLoader INSTANCE = new NinePatchMetadataLoader();
+
+ private static final Identifier ID = new Identifier("libgui", "9patch_metadata");
+ private static final String SUFFIX = ".9patch";
+
+ private Map<Identifier, TextureProperties> properties = Collections.emptyMap();
+
+ public TextureProperties getProperties(Identifier texture) {
+ return properties.getOrDefault(texture, TextureProperties.DEFAULT);
+ }
+
+ @Override
+ public Identifier getFabricId() {
+ return ID;
+ }
+
+ @Override
+ protected Map<Identifier, Properties> prepare(ResourceManager manager, Profiler profiler) {
+ Collection<Identifier> ids = manager.findResources("textures", s -> s.endsWith(SUFFIX));
+ Map<Identifier, Properties> result = new HashMap<>();
+
+ for (Identifier input : ids) {
+ try (Resource resource = manager.getResource(input);
+ InputStream stream = resource.getInputStream()) {
+ Properties props = new Properties();
+ props.load(stream);
+ Identifier textureId = new Identifier(input.getNamespace(), input.getPath().substring(0, input.getPath().length() - SUFFIX.length()));
+ result.put(textureId, props);
+ } catch (Exception e) {
+ LibGuiClient.logger.error("Error while loading metadata file {}, skipping...", input, e);
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ protected void apply(Map<Identifier, Properties> meta, ResourceManager manager, Profiler profiler) {
+ properties = new HashMap<>();
+ for (Map.Entry<Identifier, Properties> entry : meta.entrySet()) {
+ Identifier id = entry.getKey();
+ Properties props = entry.getValue();
+
+ if (!props.containsKey("mode")) {
+ LibGuiClient.logger.error("Metadata file for nine-patch texture {} is missing required key 'mode'", id);
+ continue;
+ }
+
+ String modeStr = props.getProperty("mode");
+ BackgroundPainter.NinePatch.Mode mode = BackgroundPainter.NinePatch.Mode.fromString(modeStr);
+
+ if (mode == null) {
+ LibGuiClient.logger.error("Invalid mode '{}' in nine-patch metadata file for texture {}", modeStr, id);
+ continue;
+ }
+
+ TextureProperties texProperties = new TextureProperties(mode);
+ properties.put(id, texProperties);
+ }
+ }
+
+ public static class TextureProperties {
+ public static final TextureProperties DEFAULT = new TextureProperties(BackgroundPainter.NinePatch.Mode.STRETCHING);
+
+ private final BackgroundPainter.NinePatch.Mode mode;
+
+ public TextureProperties(BackgroundPainter.NinePatch.Mode mode) {
+ this.mode = mode;
+ }
+
+ public BackgroundPainter.NinePatch.Mode getMode() {
+ return mode;
+ }
+ }
+}