[libgdx] Binary format, added a string table.

The binary export for a project with many attachment keys went from 3.5MB to 640KB (63.7KB zipped!).
This commit is contained in:
NathanSweet 2019-06-03 16:26:46 +02:00
parent ec5b721557
commit 7249fd6e4d

View File

@ -133,43 +133,7 @@ public class SkeletonBinary {
SkeletonData skeletonData = new SkeletonData();
skeletonData.name = file.nameWithoutExtension();
DataInput input = new DataInput(file.read(512)) {
private char[] chars = new char[32];
public String readString () throws IOException {
int byteCount = readInt(true);
switch (byteCount) {
case 0:
return null;
case 1:
return "";
}
byteCount--;
if (chars.length < byteCount) chars = new char[byteCount];
char[] chars = this.chars;
int charCount = 0;
for (int i = 0; i < byteCount;) {
int b = read();
switch (b >> 4) {
case -1:
throw new EOFException();
case 12:
case 13:
chars[charCount++] = (char)((b & 0x1F) << 6 | read() & 0x3F);
i += 2;
break;
case 14:
chars[charCount++] = (char)((b & 0x0F) << 12 | (read() & 0x3F) << 6 | read() & 0x3F);
i += 3;
break;
default:
chars[charCount++] = (char)b;
i++;
}
}
return new String(chars, 0, charCount);
}
};
SkeletonInput input = new SkeletonInput(file);
try {
skeletonData.hash = input.readString();
if (skeletonData.hash.isEmpty()) skeletonData.hash = null;
@ -194,6 +158,12 @@ public class SkeletonBinary {
int n;
Object[] o;
// Strings.
input.strings = new Array(n = input.readInt(true));
o = input.strings.setSize(n);
for (int i = 0; i < n; i++)
o[i] = input.readString();
// Bones.
o = skeletonData.bones.setSize(n = input.readInt(true));
for (int i = 0; i < n; i++) {
@ -225,7 +195,7 @@ public class SkeletonBinary {
int darkColor = input.readInt();
if (darkColor != -1) Color.rgb888ToColor(data.darkColor = new Color(), darkColor);
data.attachmentName = input.readString();
data.attachmentName = input.readStringRef();
data.blendMode = BlendMode.values[input.readInt(true)];
o[i] = data;
}
@ -328,7 +298,7 @@ public class SkeletonBinary {
// Events.
o = skeletonData.events.setSize(n = input.readInt(true));
for (int i = 0; i < n; i++) {
EventData data = new EventData(input.readString());
EventData data = new EventData(input.readStringRef());
data.intValue = input.readInt(false);
data.floatValue = input.readFloat();
data.stringValue = input.readString();
@ -356,10 +326,10 @@ public class SkeletonBinary {
return skeletonData;
}
private Skin readSkin (DataInput input, SkeletonData skeletonData, boolean defaultSkin, boolean nonessential)
private Skin readSkin (SkeletonInput input, SkeletonData skeletonData, boolean defaultSkin, boolean nonessential)
throws IOException {
Skin skin = new Skin(defaultSkin ? "default" : input.readString());
Skin skin = new Skin(defaultSkin ? "default" : input.readStringRef());
if (!defaultSkin) {
Object[] bones = skeletonData.bones.setSize(input.readInt(true));
@ -378,7 +348,7 @@ public class SkeletonBinary {
for (int i = 0, n = input.readInt(true); i < n; i++) {
int slotIndex = input.readInt(true);
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) {
String name = input.readString();
String name = input.readStringRef();
Attachment attachment = readAttachment(input, skeletonData, skin, slotIndex, name, nonessential);
if (attachment != null) skin.setAttachment(slotIndex, name, attachment);
}
@ -386,17 +356,17 @@ public class SkeletonBinary {
return skin;
}
private Attachment readAttachment (DataInput input, SkeletonData skeletonData, Skin skin, int slotIndex, String attachmentName,
boolean nonessential) throws IOException {
private Attachment readAttachment (SkeletonInput input, SkeletonData skeletonData, Skin skin, int slotIndex,
String attachmentName, boolean nonessential) throws IOException {
float scale = this.scale;
String name = input.readString();
String name = input.readStringRef();
if (name == null) name = attachmentName;
AttachmentType type = AttachmentType.values[input.readByte()];
switch (type) {
case region: {
String path = input.readString();
String path = input.readStringRef();
float rotation = input.readFloat();
float x = input.readFloat();
float y = input.readFloat();
@ -435,7 +405,7 @@ public class SkeletonBinary {
return box;
}
case mesh: {
String path = input.readString();
String path = input.readStringRef();
int color = input.readInt();
int vertexCount = input.readInt(true);
float[] uvs = readFloatArray(input, vertexCount << 1, 1);
@ -470,10 +440,10 @@ public class SkeletonBinary {
return mesh;
}
case linkedmesh: {
String path = input.readString();
String path = input.readStringRef();
int color = input.readInt();
String skinName = input.readString();
String parent = input.readString();
String skinName = input.readStringRef();
String parent = input.readStringRef();
boolean inheritDeform = input.readBoolean();
float width = 0, height = 0;
if (nonessential) {
@ -547,7 +517,7 @@ public class SkeletonBinary {
return null;
}
private Vertices readVertices (DataInput input, int vertexCount) throws IOException {
private Vertices readVertices (SkeletonInput input, int vertexCount) throws IOException {
int verticesLength = vertexCount << 1;
Vertices vertices = new Vertices();
if (!input.readBoolean()) {
@ -571,7 +541,7 @@ public class SkeletonBinary {
return vertices;
}
private float[] readFloatArray (DataInput input, int n, float scale) throws IOException {
private float[] readFloatArray (SkeletonInput input, int n, float scale) throws IOException {
float[] array = new float[n];
if (scale == 1) {
for (int i = 0; i < n; i++)
@ -583,7 +553,7 @@ public class SkeletonBinary {
return array;
}
private short[] readShortArray (DataInput input) throws IOException {
private short[] readShortArray (SkeletonInput input) throws IOException {
int n = input.readInt(true);
short[] array = new short[n];
for (int i = 0; i < n; i++)
@ -591,7 +561,7 @@ public class SkeletonBinary {
return array;
}
private Animation readAnimation (DataInput input, String name, SkeletonData skeletonData) {
private Animation readAnimation (SkeletonInput input, String name, SkeletonData skeletonData) {
Array<Timeline> timelines = new Array(32);
float scale = this.scale;
float duration = 0;
@ -608,7 +578,7 @@ public class SkeletonBinary {
AttachmentTimeline timeline = new AttachmentTimeline(frameCount);
timeline.slotIndex = slotIndex;
for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
timeline.setFrame(frameIndex, input.readFloat(), input.readString());
timeline.setFrame(frameIndex, input.readFloat(), input.readStringRef());
timelines.add(timeline);
duration = Math.max(duration, timeline.getFrames()[frameCount - 1]);
break;
@ -769,7 +739,7 @@ public class SkeletonBinary {
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) {
int slotIndex = input.readInt(true);
for (int iii = 0, nnn = input.readInt(true); iii < nnn; iii++) {
VertexAttachment attachment = (VertexAttachment)skin.getAttachment(slotIndex, input.readString());
VertexAttachment attachment = (VertexAttachment)skin.getAttachment(slotIndex, input.readStringRef());
boolean weighted = attachment.getBones() != null;
float[] vertices = attachment.getVertices();
int deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;
@ -872,7 +842,7 @@ public class SkeletonBinary {
return new Animation(name, timelines, duration);
}
private void readCurve (DataInput input, int frameIndex, CurveTimeline timeline) throws IOException {
private void readCurve (SkeletonInput input, int frameIndex, CurveTimeline timeline) throws IOException {
switch (input.readByte()) {
case CURVE_STEPPED:
timeline.setStepped(frameIndex);
@ -891,4 +861,53 @@ public class SkeletonBinary {
int[] bones;
float[] vertices;
}
static class SkeletonInput extends DataInput {
private char[] chars = new char[32];
Array<String> strings;
public SkeletonInput (FileHandle file) {
super(file.read(512));
}
/** @return May be null. */
public String readStringRef () throws IOException {
int index = readInt(true);
return index == 0 ? null : strings.get(index - 1);
}
public String readString () throws IOException {
int byteCount = readInt(true);
switch (byteCount) {
case 0:
return null;
case 1:
return "";
}
byteCount--;
if (chars.length < byteCount) chars = new char[byteCount];
char[] chars = this.chars;
int charCount = 0;
for (int i = 0; i < byteCount;) {
int b = read();
switch (b >> 4) {
case -1:
throw new EOFException();
case 12:
case 13:
chars[charCount++] = (char)((b & 0x1F) << 6 | read() & 0x3F);
i += 2;
break;
case 14:
chars[charCount++] = (char)((b & 0x0F) << 12 | (read() & 0x3F) << 6 | read() & 0x3F);
i += 3;
break;
default:
chars[charCount++] = (char)b;
i++;
}
}
return new String(chars, 0, charCount);
}
}
}