Skip to content

Commit b85bc5a

Browse files
committed
fix and improve texture serialization
1 parent 58b1cf3 commit b85bc5a

6 files changed

Lines changed: 166 additions & 26 deletions

File tree

src/main/java/com/cleanroommc/modularui/drawable/AdaptableUITexture.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import com.google.gson.JsonObject;
1010

11+
import java.util.Objects;
12+
1113
/**
1214
* This class is a <a href="https://en.wikipedia.org/wiki/9-slice_scaling">9-slice texture</a>. It can be created using
1315
* {@link UITexture.Builder#adaptable(int, int, int, int)}.
@@ -32,6 +34,11 @@ public class AdaptableUITexture extends UITexture {
3234
this.tiled = tiled;
3335
}
3436

37+
@Override
38+
public AdaptableUITexture register(String name) {
39+
return (AdaptableUITexture) super.register(name);
40+
}
41+
3542
@Override
3643
public AdaptableUITexture getSubArea(float uStart, float vStart, float uEnd, float vEnd) {
3744
return new AdaptableUITexture(this.location, lerpU(uStart), lerpV(vStart), lerpU(uEnd), lerpV(vEnd), this.colorType, this.nonOpaque,
@@ -167,17 +174,15 @@ public void drawTiled(float x, float y, float width, float height) {
167174
}
168175

169176
@Override
170-
public boolean saveToJson(JsonObject json) {
177+
protected void saveTextureToJson(JsonObject json) {
171178
super.saveToJson(json);
172-
if (json.entrySet().size() == 1) return true;
173179
json.addProperty("imageWidth", this.imageWidth);
174180
json.addProperty("imageHeight", this.imageHeight);
175181
json.addProperty("bl", this.bl);
176182
json.addProperty("br", this.br);
177183
json.addProperty("bt", this.bt);
178184
json.addProperty("bb", this.bb);
179185
json.addProperty("tiled", this.tiled);
180-
return true;
181186
}
182187

183188
@Override
@@ -189,4 +194,19 @@ protected AdaptableUITexture copy() {
189194
public AdaptableUITexture withColorOverride(int color) {
190195
return (AdaptableUITexture) super.withColorOverride(color);
191196
}
197+
198+
@Override
199+
public boolean equals(Object o) {
200+
return o != null && getClass() == o.getClass() && isEqual((AdaptableUITexture) o);
201+
}
202+
203+
protected boolean isEqual(AdaptableUITexture texture) {
204+
return super.isEqual(texture) && imageWidth == texture.imageWidth && imageHeight == texture.imageHeight &&
205+
bl == texture.bl && bt == texture.bt && br == texture.br && bb == texture.bb && tiled == texture.tiled;
206+
}
207+
208+
@Override
209+
public int hashCode() {
210+
return Objects.hash(super.hashCode(), imageWidth, imageHeight, bl, bt, br, bb, tiled);
211+
}
192212
}

src/main/java/com/cleanroommc/modularui/drawable/ColorType.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
66

77
import java.util.Map;
8+
import java.util.Objects;
89
import java.util.function.ToIntFunction;
910

1011
public class ColorType {
@@ -35,4 +36,16 @@ public String getName() {
3536
public int getColor(WidgetTheme theme) {
3637
return colorGetter.applyAsInt(theme);
3738
}
39+
40+
@Override
41+
public boolean equals(Object o) {
42+
if (o == null || getClass() != o.getClass()) return false;
43+
ColorType colorType = (ColorType) o;
44+
return Objects.equals(name, colorType.name);
45+
}
46+
47+
@Override
48+
public int hashCode() {
49+
return Objects.hashCode(name);
50+
}
3851
}

src/main/java/com/cleanroommc/modularui/drawable/DrawableSerialization.java

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.cleanroommc.modularui.drawable;
22

33
import com.cleanroommc.modularui.ModularUI;
4+
import com.cleanroommc.modularui.ModularUIConfig;
45
import com.cleanroommc.modularui.api.IJsonSerializable;
56
import com.cleanroommc.modularui.api.drawable.IDrawable;
67
import com.cleanroommc.modularui.api.drawable.IKey;
@@ -20,6 +21,7 @@
2021
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
2122
import org.jetbrains.annotations.ApiStatus;
2223
import org.jetbrains.annotations.NotNull;
24+
import org.jetbrains.annotations.Nullable;
2325

2426
import java.lang.reflect.Type;
2527
import java.util.ArrayList;
@@ -34,15 +36,59 @@ public class DrawableSerialization implements JsonSerializer<IDrawable>, JsonDes
3436
private static final Map<String, UITexture> TEXTURES = new Object2ObjectOpenHashMap<>();
3537
private static final Map<UITexture, String> REVERSE_TEXTURES = new Object2ObjectOpenHashMap<>();
3638

37-
public static void registerTexture(String s, UITexture texture) {
38-
TEXTURES.put(s, texture);
39-
REVERSE_TEXTURES.put(texture, s);
39+
private static void registerTextureInternal(String name, UITexture texture) {
40+
if (texture == null) return;
41+
UITexture current = TEXTURES.put(name, texture);
42+
REVERSE_TEXTURES.put(texture, name);
43+
if (current != null && (ModularUI.isDev || ModularUIConfig.guiDebugMode)) {
44+
ModularUI.LOGGER.warn("[DEBUG] Replacing texture with name '{}' and location '{}' with texture with location '{}'", name, current.location, texture.location);
45+
}
46+
}
47+
48+
public static void registerTexture(String name, UITexture texture) {
49+
String current = REVERSE_TEXTURES.get(texture);
50+
if (current != null) {
51+
if (name != null && !current.equals(name)) {
52+
TEXTURES.put(name, texture);
53+
REVERSE_TEXTURES.put(texture, name);
54+
TEXTURES.remove(current);
55+
}
56+
return;
57+
}
58+
if (name == null) {
59+
registerTextureAutoName(texture);
60+
} else {
61+
registerTextureInternal(name, texture);
62+
}
63+
}
64+
65+
public static void registerTextureAutoName(UITexture texture) {
66+
if (texture == null) return;
67+
String[] p = texture.location.getPath().split("/");
68+
p = p[p.length - 1].split("\\.");
69+
String baseName = texture.location.getNamespace() + ":" + p[0];
70+
String name = baseName;
71+
int number = 0;
72+
UITexture current;
73+
while ((current = TEXTURES.get(name)) != null) {
74+
if (current.equals(texture)) return;
75+
number++;
76+
name = baseName + "_" + number;
77+
if (number == 20 && (ModularUI.isDev || ModularUIConfig.guiDebugMode)) {
78+
ModularUI.LOGGER.warn("[DEBUG] Trying to register a UITexture with location '{}' for at least 20 times. This is likely a bug and should be fixed.", texture.location);
79+
} else if (number == 10000) {
80+
throw new IllegalStateException("Trying to register a UITexture with location '" + texture.location + "' 10000 times.");
81+
}
82+
}
83+
registerTexture(name, texture);
4084
}
4185

86+
@Nullable
4287
public static UITexture getTexture(String s) {
4388
return TEXTURES.get(s);
4489
}
4590

91+
@Nullable
4692
public static String getTextureId(UITexture texture) {
4793
return REVERSE_TEXTURES.get(texture);
4894
}
@@ -70,11 +116,11 @@ public static void init() {
70116
}
71117

72118
public static IDrawable deserialize(JsonElement json) {
73-
return JsonHelper.deserialize(json, IDrawable.class);
119+
return JsonHelper.DESERIALIZER.deserialize(json, IDrawable.class);
74120
}
75121

76122
public static JsonElement serialize(IDrawable drawable) {
77-
return JsonHelper.serialize(drawable);
123+
return JsonHelper.SERIALIZER.serialize(drawable, IDrawable.class);
78124
}
79125

80126
@Override

src/main/java/com/cleanroommc/modularui/drawable/TiledUITexture.java

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import com.google.gson.JsonObject;
66

7+
import java.util.Objects;
8+
79
public class TiledUITexture extends UITexture {
810

911
private final int imageWidth, imageHeight;
@@ -18,6 +20,11 @@ public class TiledUITexture extends UITexture {
1820
this.imageHeight = imageHeight;
1921
}
2022

23+
@Override
24+
public TiledUITexture register(String name) {
25+
return (TiledUITexture) super.register(name);
26+
}
27+
2128
@Override
2229
public void draw(float x, float y, float width, float height) {
2330
if (width == this.imageWidth && height == this.imageHeight) {
@@ -28,12 +35,11 @@ public void draw(float x, float y, float width, float height) {
2835
}
2936

3037
@Override
31-
public boolean saveToJson(JsonObject json) {
38+
protected void saveTextureToJson(JsonObject json) {
3239
super.saveToJson(json);
33-
if (json.entrySet().size() > 1) {
34-
json.addProperty("tiled", true);
35-
}
36-
return true;
40+
json.addProperty("imageWidth", this.imageWidth);
41+
json.addProperty("imageHeight", this.imageHeight);
42+
json.addProperty("tiled", true);
3743
}
3844

3945
@Override
@@ -45,4 +51,18 @@ protected TiledUITexture copy() {
4551
public TiledUITexture withColorOverride(int color) {
4652
return (TiledUITexture) super.withColorOverride(color);
4753
}
54+
55+
@Override
56+
public boolean equals(Object o) {
57+
return o != null && getClass() == o.getClass() && isEqual((TiledUITexture) o);
58+
}
59+
60+
protected boolean isEqual(TiledUITexture texture) {
61+
return super.isEqual(texture) && imageWidth == texture.imageWidth && imageHeight == texture.imageHeight;
62+
}
63+
64+
@Override
65+
public int hashCode() {
66+
return Objects.hash(super.hashCode(), imageWidth, imageHeight);
67+
}
4868
}

src/main/java/com/cleanroommc/modularui/drawable/UITexture.java

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import org.jetbrains.annotations.ApiStatus;
2020
import org.jetbrains.annotations.Nullable;
2121

22+
import java.util.Objects;
23+
2224
public class UITexture implements IDrawable, IJsonSerializable {
2325

2426
public static final UITexture DEFAULT = fullImage("gui/options_background", ColorType.DEFAULT);
@@ -120,6 +122,11 @@ public static UITexture fullImage(String mod, String location, ColorType colorTy
120122
return fullImage(new ResourceLocation(mod, location), colorType);
121123
}
122124

125+
public UITexture register(String name) {
126+
DrawableSerialization.registerTexture(name, this);
127+
return this;
128+
}
129+
123130
public UITexture getSubArea(Area bounds) {
124131
return getSubArea(bounds.x, bounds.y, bounds.ex(), bounds.ey());
125132
}
@@ -189,6 +196,8 @@ public static UITexture parseFromJson(JsonObject json) {
189196
if (name != null) {
190197
UITexture drawable = DrawableSerialization.getTexture(name);
191198
if (drawable != null) return drawable;
199+
ModularUI.LOGGER.error("Tried to parse UITexture from json, but no texture with name '{}' is registered!", name);
200+
return GuiTextures.HELP;
192201
}
193202
Builder builder = builder();
194203
builder.location(JsonHelper.getString(json, ModularUI.ID + ":gui/widgets/error", "location"))
@@ -237,14 +246,34 @@ public boolean saveToJson(JsonObject json) {
237246
json.addProperty("id", name);
238247
return true;
239248
}
249+
saveTextureToJson(json);
250+
return true;
251+
}
252+
253+
protected void saveTextureToJson(JsonObject json) {
240254
json.addProperty("location", this.location.toString());
241255
json.addProperty("u0", this.u0);
242256
json.addProperty("v0", this.v0);
243257
json.addProperty("u1", this.u1);
244258
json.addProperty("v1", this.v1);
245259
if (this.colorType != null) json.addProperty("colorType", this.colorType.getName());
246260
json.addProperty("colorOverride", this.colorOverride);
247-
return true;
261+
}
262+
263+
@Override
264+
public boolean equals(Object o) {
265+
return o != null && getClass() == o.getClass() && isEqual((UITexture) o);
266+
}
267+
268+
protected boolean isEqual(UITexture texture) {
269+
return Objects.equals(location, texture.location) && Float.compare(u0, texture.u0) == 0 && Float.compare(v0, texture.v0) == 0 &&
270+
Float.compare(u1, texture.u1) == 0 && Float.compare(v1, texture.v1) == 0 && nonOpaque == texture.nonOpaque &&
271+
colorOverride == texture.colorOverride && Objects.equals(colorType, texture.colorType);
272+
}
273+
274+
@Override
275+
public int hashCode() {
276+
return Objects.hash(location, u0, v0, u1, v1, colorType, nonOpaque, colorOverride);
248277
}
249278

250279
protected UITexture copy() {
@@ -542,14 +571,6 @@ public Builder nonOpaque() {
542571
*/
543572
public UITexture build() {
544573
UITexture texture = create();
545-
if (this.name == null) {
546-
String[] p = texture.location.getPath().split("/");
547-
p = p[p.length - 1].split("\\.");
548-
this.name = texture.location.getNamespace().equals(ModularUI.ID) ? p[0] : texture.location.getNamespace() + ":" + p[0];
549-
if (DrawableSerialization.getTexture(this.name) != null) {
550-
return texture;
551-
}
552-
}
553574
DrawableSerialization.registerTexture(this.name, texture);
554575
return texture;
555576
}

src/main/java/com/cleanroommc/modularui/utils/JsonHelper.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,53 @@
33
import com.cleanroommc.modularui.api.drawable.IDrawable;
44
import com.cleanroommc.modularui.drawable.DrawableSerialization;
55

6-
import com.google.gson.*;
6+
import com.google.gson.Gson;
7+
import com.google.gson.GsonBuilder;
8+
import com.google.gson.JsonDeserializationContext;
9+
import com.google.gson.JsonElement;
10+
import com.google.gson.JsonObject;
11+
import com.google.gson.JsonParser;
12+
import com.google.gson.JsonSerializationContext;
713
import org.jetbrains.annotations.NotNull;
814
import org.jetbrains.annotations.Nullable;
915

1016
import java.io.InputStream;
1117
import java.io.InputStreamReader;
18+
import java.lang.reflect.Type;
1219
import java.nio.charset.StandardCharsets;
1320
import java.util.Map;
1421
import java.util.function.Consumer;
1522
import java.util.function.Function;
1623

1724
public class JsonHelper {
1825

19-
public static final Gson gson = new GsonBuilder()
26+
public static final Gson GSON = new GsonBuilder()
2027
.setPrettyPrinting()
2128
.registerTypeAdapter(IDrawable.class, new DrawableSerialization())
2229
.registerTypeAdapter(Alignment.class, new Alignment.Json())
2330
.create();
2431

32+
public static final JsonDeserializationContext DESERIALIZER = GSON::fromJson;
33+
public static final JsonSerializationContext SERIALIZER = new JsonSerializationContext() {
34+
@Override
35+
public JsonElement serialize(Object o) {
36+
return GSON.toJsonTree(o);
37+
}
38+
39+
@Override
40+
public JsonElement serialize(Object o, Type type) {
41+
return GSON.toJsonTree(o, type);
42+
}
43+
};
44+
2545
public static final JsonParser parser = new JsonParser();
2646

2747
public static JsonElement serialize(Object object) {
28-
return gson.toJsonTree(object);
48+
return GSON.toJsonTree(object);
2949
}
3050

3151
public static <T> T deserialize(JsonElement json, Class<T> clazz) {
32-
return gson.fromJson(json, clazz);
52+
return GSON.fromJson(json, clazz);
3353
}
3454

3555
public static <T> T deserialize(JsonObject json, Class<T> clazz, T defaultValue, String... keys) {

0 commit comments

Comments
 (0)