Kaynağa Gözat

[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!).
NathanSweet 6 yıl önce
ebeveyn
işleme
7249fd6e4d

+ 76 - 57
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java

@@ -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);
+		}
+	}
 }