- * See Scaling in the Spine Runtimes Guide. */ - public float getScale () { - return scale; - } - - public void setScale (float scale) { - if (scale == 0) throw new IllegalArgumentException("scale cannot be 0."); - this.scale = scale; + super(atlas); } public SkeletonData readSkeletonData (FileHandle file) { @@ -610,10 +591,10 @@ public class SkeletonBinary { timeline.setStepped(frame); break; case CURVE_BEZIER: - setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2); - setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2); - setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2); - setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2); + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1); } time = time2; r = r2; @@ -644,13 +625,13 @@ public class SkeletonBinary { timeline.setStepped(frame); break; case CURVE_BEZIER: - setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr); - setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng); - setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb); - setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na); - setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2); - setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2); - setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2); + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); } time = time2; r = nr; @@ -703,8 +684,8 @@ public class SkeletonBinary { timeline.setStepped(frame); break; case CURVE_BEZIER: - setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2); - setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2); + setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, 1); } time = time2; mix = mix2; @@ -729,10 +710,10 @@ public class SkeletonBinary { timeline.setStepped(frame); break; case CURVE_BEZIER: - setBezier(input, timeline, bezier++, frame, 0, time, time2, rotateMix, rotateMix2); - setBezier(input, timeline, bezier++, frame, 1, time, time2, translateMix, translateMix2); - setBezier(input, timeline, bezier++, frame, 2, time, time2, scaleMix, scaleMix2); - setBezier(input, timeline, bezier++, frame, 3, time, time2, shearMix, shearMix2); + setBezier(input, timeline, bezier++, frame, 0, time, time2, rotateMix, rotateMix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, translateMix, translateMix2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, scaleMix, scaleMix2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, shearMix, shearMix2, 1); } time = time2; rotateMix = rotateMix2; @@ -812,7 +793,7 @@ public class SkeletonBinary { timeline.setStepped(frame); break; case CURVE_BEZIER: - setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1); + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); } time = time2; } @@ -891,7 +872,7 @@ public class SkeletonBinary { timeline.setStepped(frame); break; case CURVE_BEZIER: - setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2); + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, 1); } time = time2; value = value2; @@ -910,8 +891,8 @@ public class SkeletonBinary { timeline.setStepped(frame); break; case CURVE_BEZIER: - setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1); - setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2); + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); } time = time2; value1 = nvalue1; @@ -921,9 +902,9 @@ public class SkeletonBinary { } void setBezier (SkeletonInput input, CurveTimeline timeline, int bezier, int frame, int value, float time1, float time2, - float value1, float value2) throws IOException { - timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat(), input.readFloat(), - input.readFloat(), time2, value2); + float value1, float value2, float scale) throws IOException { + timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), + input.readFloat() * scale, time2, value2); } static class Vertices { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index 2ad62d83e..8f6e34111 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -64,7 +64,6 @@ import com.esotericsoftware.spine.BoneData.TransformMode; import com.esotericsoftware.spine.PathConstraintData.PositionMode; import com.esotericsoftware.spine.PathConstraintData.RotateMode; import com.esotericsoftware.spine.PathConstraintData.SpacingMode; -import com.esotericsoftware.spine.attachments.AtlasAttachmentLoader; import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.AttachmentLoader; import com.esotericsoftware.spine.attachments.AttachmentType; @@ -77,35 +76,19 @@ import com.esotericsoftware.spine.attachments.RegionAttachment; import com.esotericsoftware.spine.attachments.VertexAttachment; /** Loads skeleton data in the Spine JSON format. + *
+ * JSON is human readable but the binary format is much smaller on disk and faster to load. See {@link SkeletonBinary}. *
* See Spine JSON format and
* JSON and binary data in the Spine
* Runtimes Guide. */
-public class SkeletonJson {
- private final AttachmentLoader attachmentLoader;
- private float scale = 1;
- private final Array
- * See Scaling in the Spine Runtimes Guide. */
- public float getScale () {
- return scale;
- }
-
- public void setScale (float scale) {
- if (scale == 0) throw new IllegalArgumentException("scale cannot be 0.");
- this.scale = scale;
+ super(atlas);
}
protected JsonValue parse (FileHandle file) {
@@ -128,8 +111,6 @@ public class SkeletonJson {
if (skeletonMap != null) {
skeletonData.hash = skeletonMap.getString("hash", null);
skeletonData.version = skeletonMap.getString("spine", null);
- if ("3.8.75".equals(skeletonData.version))
- throw new RuntimeException("Unsupported skeleton data, please export with a newer version of Spine.");
skeletonData.x = skeletonMap.getFloat("x", 0);
skeletonData.y = skeletonMap.getFloat("y", 0);
skeletonData.width = skeletonMap.getFloat("width", 0);
@@ -491,7 +472,7 @@ public class SkeletonJson {
for (int i = 0, n = vertices.length; i < n;) {
int boneCount = (int)vertices[i++];
bones.add(boneCount);
- for (int nn = i + boneCount * 4; i < nn; i += 4) {
+ for (int nn = i + (boneCount << 2); i < nn; i += 4) {
bones.add((int)vertices[i]);
weights.add(vertices[i + 1] * scale);
weights.add(vertices[i + 2] * scale);
@@ -544,10 +525,10 @@ public class SkeletonJson {
float na = Integer.parseInt(color.substring(6, 8), 16) / 255f;
JsonValue curve = keyMap.get("curve");
if (curve != null) {
- bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, r, nr);
- bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, g, ng);
- bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, b, nb);
- bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, a, na);
+ bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, r, nr, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, g, ng, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, b, nb, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, a, na, 1);
}
time = time2;
r = nr;
@@ -589,13 +570,13 @@ public class SkeletonJson {
float nb2 = Integer.parseInt(color.substring(12, 14), 16) / 255f;
JsonValue curve = keyMap.get("curve");
if (curve != null) {
- bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, r, nr);
- bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, g, ng);
- bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, b, nb);
- bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, a, na);
- bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, r2, nr2);
- bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, g2, ng2);
- bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, b2, nb2);
+ bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, r, nr, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, g, ng, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, b, nb, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, a, na, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, r2, nr2, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, g2, ng2, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, b2, nb2, 1);
}
time = time2;
r = nr;
@@ -660,8 +641,8 @@ public class SkeletonJson {
float mix2 = nextMap.getFloat("mix", 1), softness2 = nextMap.getFloat("softness", 0) * scale;
JsonValue curve = keyMap.get("curve");
if (curve != null) {
- bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2);
- bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2);
+ bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, 1);
}
time = time2;
mix = mix2;
@@ -693,10 +674,10 @@ public class SkeletonJson {
float scaleMix2 = nextMap.getFloat("scaleMix", 1), shearMix2 = nextMap.getFloat("shearMix", 1);
JsonValue curve = keyMap.get("curve");
if (curve != null) {
- bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, rotateMix, rotateMix2);
- bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, translateMix, translateMix2);
- bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, scaleMix, scaleMix2);
- bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, shearMix, shearMix2);
+ bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, rotateMix, rotateMix2, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, translateMix, translateMix2, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, scaleMix, scaleMix2, 1);
+ bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, shearMix, shearMix2, 1);
}
time = time2;
rotateMix = rotateMix2;
@@ -777,7 +758,7 @@ public class SkeletonJson {
}
float time2 = nextMap.getFloat("time", 0);
JsonValue curve = keyMap.get("curve");
- if (curve != null) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1);
+ if (curve != null) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);
time = time2;
keyMap = nextMap;
}
@@ -853,16 +834,16 @@ public class SkeletonJson {
}
private Timeline readTimeline (JsonValue keyMap, CurveTimeline1 timeline, float defaultValue, float scale) {
- float time = keyMap.getFloat("time", 0), value = keyMap.getFloat("value", defaultValue);
+ float time = keyMap.getFloat("time", 0), value = keyMap.getFloat("value", defaultValue) * scale;
int bezier = 0;
for (int frame = 0;; frame++) {
timeline.setFrame(frame, time, value);
JsonValue nextMap = keyMap.next;
if (nextMap == null) break;
float time2 = nextMap.getFloat("time", 0);
- float value2 = nextMap.getFloat("value", defaultValue);
+ float value2 = nextMap.getFloat("value", defaultValue) * scale;
JsonValue curve = keyMap.get("curve");
- if (curve != null) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value, value2);
+ if (curve != null) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value, value2, scale);
time = time2;
value = value2;
keyMap = nextMap;
@@ -874,18 +855,18 @@ public class SkeletonJson {
private Timeline readTimeline (JsonValue keyMap, CurveTimeline2 timeline, String name1, String name2, float defaultValue,
float scale) {
float time = keyMap.getFloat("time", 0);
- float value1 = keyMap.getFloat(name1, defaultValue), value2 = keyMap.getFloat(name2, defaultValue);
+ float value1 = keyMap.getFloat(name1, defaultValue) * scale, value2 = keyMap.getFloat(name2, defaultValue) * scale;
int bezier = 0;
for (int frame = 0;; frame++) {
timeline.setFrame(frame, time, value1, value2);
JsonValue nextMap = keyMap.next;
if (nextMap == null) break;
float time2 = nextMap.getFloat("time", 0);
- float nvalue1 = nextMap.getFloat(name1, defaultValue), nvalue2 = nextMap.getFloat(name2, defaultValue);
+ float nvalue1 = nextMap.getFloat(name1, defaultValue) * scale, nvalue2 = nextMap.getFloat(name2, defaultValue) * scale;
JsonValue curve = keyMap.get("curve");
if (curve != null) {
- bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1);
- bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2);
+ bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale);
+ bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale);
}
time = time2;
value1 = nvalue1;
@@ -897,18 +878,18 @@ public class SkeletonJson {
}
int readCurve (JsonValue curve, CurveTimeline timeline, int bezier, int frame, int value, float time1, float time2,
- float value1, float value2) {
+ float value1, float value2, float scale) {
if (curve.isString()) {
if (value != 0) timeline.setStepped(frame);
} else {
- curve = curve.get(value * 4);
+ curve = curve.get(value << 2);
float cx1 = curve.asFloat();
curve = curve.next;
- float cy1 = curve.asFloat();
+ float cy1 = curve.asFloat() * scale;
curve = curve.next;
float cx2 = curve.asFloat();
curve = curve.next;
- float cy2 = curve.asFloat();
+ float cy2 = curve.asFloat() * scale;
setBezier(timeline, frame, value, bezier++, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
}
return bezier;
diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonLoader.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonLoader.java
new file mode 100644
index 000000000..d8538cdf0
--- /dev/null
+++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonLoader.java
@@ -0,0 +1,46 @@
+
+package com.esotericsoftware.spine;
+
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.utils.Array;
+
+import com.esotericsoftware.spine.SkeletonJson.LinkedMesh;
+import com.esotericsoftware.spine.attachments.AtlasAttachmentLoader;
+import com.esotericsoftware.spine.attachments.AttachmentLoader;
+
+/** Base class for loading skeleton data from a file. */
+abstract public class SkeletonLoader {
+ final AttachmentLoader attachmentLoader;
+ float scale = 1;
+ final Array
+ * See Loading skeleton data in the
+ * Spine Runtimes Guide. */
+ public SkeletonLoader (AttachmentLoader attachmentLoader) {
+ if (attachmentLoader == null) throw new IllegalArgumentException("attachmentLoader cannot be null.");
+ this.attachmentLoader = attachmentLoader;
+ }
+
+ /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at
+ * runtime than were used in Spine.
+ *
+ * See Scaling in the Spine Runtimes Guide. */
+ public float getScale () {
+ return scale;
+ }
+
+ public void setScale (float scale) {
+ if (scale == 0) throw new IllegalArgumentException("scale cannot be 0.");
+ this.scale = scale;
+ }
+
+ abstract public SkeletonData readSkeletonData (FileHandle file);
+}
diff --git a/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java b/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java
index 8099b0c12..5d70cd4de 100644
--- a/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java
+++ b/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java
@@ -94,9 +94,10 @@ public class SkeletonViewer extends ApplicationAdapter {
static final float checkModifiedInterval = 0.250f;
static final float reloadDelay = 1;
static float uiScale = 1;
+ static String[] startSuffixes = {"", "-pro", "-ess"};
static String[] dataSuffixes = {".json", ".skel"};
- static String[] atlasSuffixes = {".atlas", "-pro.atlas", "-ess.atlas"};
- static String[] extraSuffixes = {"", ".txt", ".bytes"};
+ static String[] endSuffixes = {"", ".txt", ".bytes"};
+ static String[] atlasSuffixes = {".atlas", "-pma.atlas"};
static String[] args;
static final String version = ""; // Replaced by build.
@@ -146,12 +147,14 @@ public class SkeletonViewer extends ApplicationAdapter {
FileHandle atlasFile (FileHandle skeletonFile) {
String baseName = skeletonFile.name();
- for (String extraSuffix : extraSuffixes) {
- for (String dataSuffix : dataSuffixes) {
- String suffix = dataSuffix + extraSuffix;
- if (baseName.endsWith(suffix)) {
- FileHandle file = atlasFile(skeletonFile, baseName.substring(0, baseName.length() - suffix.length()));
- if (file != null) return file;
+ for (String startSuffix : startSuffixes) {
+ for (String endSuffix : endSuffixes) {
+ for (String dataSuffix : dataSuffixes) {
+ String suffix = startSuffix + dataSuffix + endSuffix;
+ if (baseName.endsWith(suffix)) {
+ FileHandle file = atlasFile(skeletonFile, baseName.substring(0, baseName.length() - suffix.length()));
+ if (file != null) return file;
+ }
}
}
}
@@ -159,10 +162,12 @@ public class SkeletonViewer extends ApplicationAdapter {
}
private FileHandle atlasFile (FileHandle skeletonFile, String baseName) {
- for (String extraSuffix : extraSuffixes) {
- for (String suffix : atlasSuffixes) {
- FileHandle file = skeletonFile.sibling(baseName + suffix + extraSuffix);
- if (file.exists()) return file;
+ for (String startSuffix : startSuffixes) {
+ for (String endSuffix : endSuffixes) {
+ for (String suffix : atlasSuffixes) {
+ FileHandle file = skeletonFile.sibling(baseName + startSuffix + suffix + endSuffix);
+ if (file.exists()) return file;
+ }
}
}
return null;
@@ -238,6 +243,7 @@ public class SkeletonViewer extends ApplicationAdapter {
state = new AnimationState(new AnimationStateData(skeletonData));
state.addListener(new AnimationStateAdapter() {
+
public void event (TrackEntry entry, Event event) {
ui.toast(event.getData().getName());
}
@@ -254,6 +260,7 @@ public class SkeletonViewer extends ApplicationAdapter {
ui.window.getTitleLabel().setText(skeletonFile.name());
{
+
Array