}
protected Json getJsonLoader (final FileHandle skinFile) {
final Skin skin = this;
final Json json = new Json();
json.setTypeName(null);
json.setUsePrototypes(false);
// Writes names of resources instead of objects.
class AliasWriter implements Serializer {
final ObjectMap<String, ?> map;
public AliasWriter (Class type) {
map = resources.get(type);
}
public void write (Json json, Object object, Class valueType) {
for (Entry<String, ?> entry : map.entries()) {
if (entry.value.equals(object)) {
json.writeValue(entry.key);
return;
}
}
throw new SerializationException(object.getClass().getSimpleName() + " not found: " + object);
}
public Object read (Json json, Object jsonData, Class type) {
throw new UnsupportedOperationException();
}
}
json.setSerializer(Skin.class, new Serializer<Skin>() {
public void write (Json json, Skin skin, Class valueType) {
json.writeObjectStart();
json.writeValue("resources", skin.resources);
for (Entry<Class, ObjectMap<String, Object>> entry : resources.entries())
json.setSerializer(entry.key, new AliasWriter(entry.key));
json.writeField(skin, "styles");
json.writeObjectEnd();
}
public Skin read (Json json, Object jsonData, Class ignored) {
ObjectMap map = (ObjectMap)jsonData;
readTypeMap(json, (ObjectMap)map.get("resources"), true);
readTypeMap(json, (ObjectMap)map.get("styles"), false);
return skin;
}
private void readTypeMap (Json json, ObjectMap<String, ObjectMap> typeToValueMap, boolean isResource) {
if (typeToValueMap == null)
throw new SerializationException("Skin file is missing a \"" + (isResource ? "resources" : "styles")
+ "\" section.");
for (Entry<String, ObjectMap> typeEntry : typeToValueMap.entries()) {
String className = typeEntry.key;
ObjectMap<String, ObjectMap> valueMap = (ObjectMap)typeEntry.value;
try {
readNamedObjects(json, Class.forName(className), valueMap, isResource);
} catch (ClassNotFoundException ex) {
throw new SerializationException(ex);
}
}
}
private void readNamedObjects (Json json, Class type, ObjectMap<String, ObjectMap> valueMap, boolean isResource) {
for (Entry<String, ObjectMap> valueEntry : valueMap.entries()) {
String name = valueEntry.key;
Object object = json.readValue(type, valueEntry.value);
if (object == null) continue;
try {
if (isResource)
addResource(name, object);
else
addStyle(name, object);
} catch (Exception ex) {
throw new SerializationException("Error reading " + type.getSimpleName() + ": " + valueEntry.key, ex);
}
}
}
});
json.setSerializer(TextureRegion.class, new Serializer<TextureRegion>() {
public void write (Json json, TextureRegion region, Class valueType) {
json.writeObjectStart();
json.writeValue("x", region.getRegionX());
json.writeValue("y", region.getRegionY());
json.writeValue("width", region.getRegionWidth());
json.writeValue("height", region.getRegionHeight());
json.writeObjectEnd();
}
public TextureRegion read (Json json, Object jsonData, Class type) {
if (jsonData instanceof String) return getResource((String)jsonData, TextureRegion.class);
int x = json.readValue("x", int.class, jsonData);
int y = json.readValue("y", int.class, jsonData);
int width = json.readValue("width", int.class, jsonData);
int height = json.readValue("height", int.class, jsonData);
return new TextureRegion(skin.texture, x, y, width, height);
}
});
json.setSerializer(BitmapFont.class, new Serializer<BitmapFont>() {
public void write (Json json, BitmapFont font, Class valueType) {
json.writeObjectStart();
json.writeValue("file", font.getData().getFontFile().toString().replace('\\', '/'));
json.writeObjectEnd();
}
public BitmapFont read (Json json, Object jsonData, Class type) {
if (jsonData instanceof String) return getResource((String)jsonData, BitmapFont.class);
String path = json.readValue("file", String.class, jsonData);
FileHandle fontFile = skinFile.parent().child(path);
if (!fontFile.exists()) fontFile = Gdx.files.internal(path);
if (!fontFile.exists()) throw new SerializationException("Font file not found: " + fontFile);
// Use a region with the same name as the font, else use a PNG file in the same directory as the FNT file.
String regionName = fontFile.nameWithoutExtension();
try {
if (skin.hasResource(regionName, TextureRegion.class))
return new BitmapFont(fontFile, skin.getResource(regionName, TextureRegion.class), false);
else {
FileHandle imageFile = fontFile.parent().child(regionName + ".png");
if (imageFile.exists())
return new BitmapFont(fontFile, imageFile, false);
else
return new BitmapFont(fontFile, false);
}
} catch (RuntimeException ex) {
throw new SerializationException("Error loading bitmap font: " + fontFile, ex);
}
}
});
json.setSerializer(NinePatch.class, new Serializer<NinePatch>() {
public void write (Json json, NinePatch ninePatch, Class valueType) {
TextureRegion[] patches = ninePatch.getPatches();
boolean singlePatch = patches[0] == null && patches[1] == null && patches[2] == null && patches[3] == null
&& patches[4] != null && patches[5] == null && patches[6] == null && patches[7] == null && patches[8] == null;
if (ninePatch.getColor() != null) {
json.writeObjectStart();
json.writeValue("color", ninePatch.getColor());
if (singlePatch)
json.writeValue("region", patches[4]);
else
json.writeValue("regions", patches);
json.writeObjectEnd();
} else {
if (singlePatch)
json.writeValue(patches[4]);
else
json.writeValue(patches);
}
}
public NinePatch read (Json json, Object jsonData, Class type) {
if (jsonData instanceof String) return getResource((String)jsonData, NinePatch.class);
if (jsonData instanceof Array) {
TextureRegion[] regions = json.readValue(TextureRegion[].class, jsonData);
if (regions.length == 1) return new NinePatch(regions[0]);
return new NinePatch(regions);
} else {
ObjectMap map = (ObjectMap)jsonData;
NinePatch ninePatch;
if (map.containsKey("regions"))
ninePatch = new NinePatch(json.readValue("regions", TextureRegion[].class, jsonData));
else if (map.containsKey("region"))
ninePatch = new NinePatch(json.readValue("region", TextureRegion.class, jsonData));
else
ninePatch = new NinePatch(json.readValue(TextureRegion.class, jsonData));
// throw new SerializationException("Missing ninepatch regions: " + map);
if (map.containsKey("color")) ninePatch.setColor(json.readValue("color", Color.class, jsonData));
return ninePatch;
}
}
});
json.setSerializer(Color.class, new Serializer<Color>() {
public void write (Json json, Color color, Class valueType) {
json.writeObjectStart();
json.writeFields(color);
json.writeObjectEnd();
}
public Color read (Json json, Object jsonData, Class type) {
if (jsonData instanceof String) return getResource((String)jsonData, Color.class);
ObjectMap map = (ObjectMap)jsonData;
float r = json.readValue("r", float.class, 0f, jsonData);
float g = json.readValue("g", float.class, 0f, jsonData);
float b = json.readValue("b", float.class, 0f, jsonData);
float a = json.readValue("a", float.class, 1f, jsonData);
return new Color(r, g, b, a);
}
});
json.setSerializer(TintedNinePatch.class, new Serializer() {
public void write (Json json, Object tintedPatch, Class valueType) {
json.writeObjectStart();
json.writeField(tintedPatch, "name");
json.writeField(tintedPatch, "color");
json.writeObjectEnd();
}
public Object read (Json json, Object jsonData, Class type) {
String name = json.readValue("name", String.class, jsonData);
Color color = json.readValue("color", Color.class, jsonData);
return new NinePatch(getResource(name, NinePatch.class), color);
}
});
return json;