|
@@ -53,12 +53,15 @@
|
|
|
#include <spine/EventTimeline.h>
|
|
|
#include <spine/IkConstraintData.h>
|
|
|
#include <spine/IkConstraintTimeline.h>
|
|
|
+#include <spine/InheritTimeline.h>
|
|
|
#include <spine/MeshAttachment.h>
|
|
|
#include <spine/PathAttachment.h>
|
|
|
#include <spine/PathConstraintData.h>
|
|
|
#include <spine/PathConstraintMixTimeline.h>
|
|
|
#include <spine/PathConstraintPositionTimeline.h>
|
|
|
#include <spine/PathConstraintSpacingTimeline.h>
|
|
|
+#include <spine/PhysicsConstraintData.h>
|
|
|
+#include <spine/PhysicsConstraintTimeline.h>
|
|
|
#include <spine/PointAttachment.h>
|
|
|
#include <spine/RegionAttachment.h>
|
|
|
#include <spine/RotateTimeline.h>
|
|
@@ -129,6 +132,7 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
skeletonData->_y = readFloat(input);
|
|
|
skeletonData->_width = readFloat(input);
|
|
|
skeletonData->_height = readFloat(input);
|
|
|
+ skeletonData->_referenceScale = readFloat(input) * this->_scale;
|
|
|
|
|
|
nonessential = readBoolean(input);
|
|
|
|
|
@@ -161,6 +165,8 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
data->_skinRequired = readBoolean(input);
|
|
|
if (nonessential) {
|
|
|
readColor(input, data->getColor());
|
|
|
+ data->_icon.own(readString(input));
|
|
|
+ data->_visible = readBoolean(input);
|
|
|
}
|
|
|
skeletonData->_bones[i] = data;
|
|
|
}
|
|
@@ -169,9 +175,17 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
int slotsCount = readVarint(input, true);
|
|
|
skeletonData->_slots.setSize(slotsCount, 0);
|
|
|
for (int i = 0; i < slotsCount; ++i) {
|
|
|
- const char *slotName = readString(input);
|
|
|
+ String slotName = String(readString(input), true);
|
|
|
+ String pathName = "";
|
|
|
+ if (nonessential) {
|
|
|
+ int slash = slotName.lastIndexOf('/');
|
|
|
+ if (slash != -1) {
|
|
|
+ pathName = slotName.substring(0, slash);
|
|
|
+ slotName = slotName.substring(slash + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
BoneData *boneData = skeletonData->_bones[readVarint(input, true)];
|
|
|
- SlotData *slotData = new (__FILE__, __LINE__) SlotData(i, String(slotName, true), *boneData);
|
|
|
+ SlotData *slotData = new (__FILE__, __LINE__) SlotData(i, slotName, *boneData);
|
|
|
|
|
|
readColor(input, slotData->getColor());
|
|
|
unsigned char a = readByte(input);
|
|
@@ -184,6 +198,10 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
}
|
|
|
slotData->_attachmentName = readStringRef(input, skeletonData);
|
|
|
slotData->_blendMode = static_cast<BlendMode>(readVarint(input, true));
|
|
|
+ if (nonessential) {
|
|
|
+ slotData->_visible = readBoolean(input);
|
|
|
+ slotData->_path = pathName;
|
|
|
+ }
|
|
|
skeletonData->_slots[i] = slotData;
|
|
|
}
|
|
|
|
|
@@ -194,18 +212,20 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
const char *name = readString(input);
|
|
|
IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData(String(name, true));
|
|
|
data->setOrder(readVarint(input, true));
|
|
|
- data->setSkinRequired(readBoolean(input));
|
|
|
int bonesCount = readVarint(input, true);
|
|
|
data->_bones.setSize(bonesCount, 0);
|
|
|
for (int ii = 0; ii < bonesCount; ++ii)
|
|
|
data->_bones[ii] = skeletonData->_bones[readVarint(input, true)];
|
|
|
data->_target = skeletonData->_bones[readVarint(input, true)];
|
|
|
- data->_mix = readFloat(input);
|
|
|
- data->_softness = readFloat(input) * _scale;
|
|
|
- data->_bendDirection = readSByte(input);
|
|
|
- data->_compress = readBoolean(input);
|
|
|
- data->_stretch = readBoolean(input);
|
|
|
- data->_uniform = readBoolean(input);
|
|
|
+ int flags = readByte(input);
|
|
|
+ data->_skinRequired = (flags & 1) != 0;
|
|
|
+ data->_bendDirection = (flags & 2) != 0 ? 1 : -1;
|
|
|
+ data->_compress = (flags & 4) != 0;
|
|
|
+ data->_stretch = (flags & 8) != 0;
|
|
|
+ data->_uniform = (flags & 16) != 0;
|
|
|
+ if ((flags & 32) != 0) data->_mix = (flags & 64) != 0 ? readFloat(input) : 1;
|
|
|
+ if ((flags & 128) != 0) data->_softness = readFloat(input) * _scale;
|
|
|
+
|
|
|
skeletonData->_ikConstraints[i] = data;
|
|
|
}
|
|
|
|
|
@@ -216,27 +236,30 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
const char *name = readString(input);
|
|
|
TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData(String(name, true));
|
|
|
data->setOrder(readVarint(input, true));
|
|
|
- data->setSkinRequired(readBoolean(input));
|
|
|
int bonesCount = readVarint(input, true);
|
|
|
data->_bones.setSize(bonesCount, 0);
|
|
|
for (int ii = 0; ii < bonesCount; ++ii)
|
|
|
data->_bones[ii] = skeletonData->_bones[readVarint(input, true)];
|
|
|
data->_target = skeletonData->_bones[readVarint(input, true)];
|
|
|
- data->_local = readBoolean(input);
|
|
|
- data->_relative = readBoolean(input);
|
|
|
- data->_offsetRotation = readFloat(input);
|
|
|
- data->_offsetX = readFloat(input) * _scale;
|
|
|
- data->_offsetY = readFloat(input) * _scale;
|
|
|
- data->_offsetScaleX = readFloat(input);
|
|
|
- data->_offsetScaleY = readFloat(input);
|
|
|
- data->_offsetShearY = readFloat(input);
|
|
|
- data->_mixRotate = readFloat(input);
|
|
|
- data->_mixX = readFloat(input);
|
|
|
- data->_mixY = readFloat(input);
|
|
|
- data->_mixScaleX = readFloat(input);
|
|
|
- data->_mixScaleY = readFloat(input);
|
|
|
- data->_mixShearY = readFloat(input);
|
|
|
- skeletonData->_transformConstraints[i] = data;
|
|
|
+ int flags = readByte(input);
|
|
|
+ data->_skinRequired = (flags & 1) != 0;
|
|
|
+ data->_local = (flags & 2) != 0;
|
|
|
+ data->_relative = (flags & 4) != 0;
|
|
|
+ if ((flags & 8) != 0) data->_offsetRotation = readFloat(input);
|
|
|
+ if ((flags & 16) != 0) data->_offsetX =readFloat(input) * _scale;
|
|
|
+ if ((flags & 32) != 0) data->_offsetY = readFloat(input) * _scale;
|
|
|
+ if ((flags & 64) != 0) data->_offsetScaleX = readFloat(input);
|
|
|
+ if ((flags & 128) != 0) data->_offsetScaleY = readFloat(input);
|
|
|
+ flags = readByte(input);
|
|
|
+ if ((flags & 1) != 0) data->_offsetShearY = readFloat(input);
|
|
|
+ if ((flags & 2) != 0) data->_mixRotate = readFloat(input);
|
|
|
+ if ((flags & 4) != 0) data->_mixX = readFloat(input);
|
|
|
+ if ((flags & 8) != 0) data->_mixY = readFloat(input);
|
|
|
+ if ((flags & 16) != 0) data->_mixScaleX = readFloat(input);
|
|
|
+ if ((flags & 32) != 0) data->_mixScaleY = readFloat(input);
|
|
|
+ if ((flags & 64) != 0) data->_mixShearY = readFloat(input);
|
|
|
+
|
|
|
+ skeletonData->_transformConstraints[i] = data;
|
|
|
}
|
|
|
|
|
|
/* Path constraints */
|
|
@@ -252,10 +275,11 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
for (int ii = 0; ii < bonesCount; ++ii)
|
|
|
data->_bones[ii] = skeletonData->_bones[readVarint(input, true)];
|
|
|
data->_target = skeletonData->_slots[readVarint(input, true)];
|
|
|
- data->_positionMode = static_cast<PositionMode>(readVarint(input, true));
|
|
|
- data->_spacingMode = static_cast<SpacingMode>(readVarint(input, true));
|
|
|
- data->_rotateMode = static_cast<RotateMode>(readVarint(input, true));
|
|
|
- data->_offsetRotation = readFloat(input);
|
|
|
+ int flags = readByte(input);
|
|
|
+ data->_positionMode = (PositionMode)(flags & 1);
|
|
|
+ data->_spacingMode = (SpacingMode)((flags >> 1) & 3);
|
|
|
+ data->_rotateMode = (RotateMode)((flags >> 3) & 3);
|
|
|
+ if ((flags & 128) != 0) data->_offsetRotation = readFloat(input);
|
|
|
data->_position = readFloat(input);
|
|
|
if (data->_positionMode == PositionMode_Fixed) data->_position *= _scale;
|
|
|
data->_spacing = readFloat(input);
|
|
@@ -267,6 +291,41 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
skeletonData->_pathConstraints[i] = data;
|
|
|
}
|
|
|
|
|
|
+ // Physics constraints.
|
|
|
+ int physicsConstraintsCount = readVarint(input, true);
|
|
|
+ skeletonData->_physicsConstraints.setSize(physicsConstraintsCount, 0);
|
|
|
+ for (int i = 0; i < physicsConstraintsCount; i++) {
|
|
|
+ const char *name = readString(input);
|
|
|
+ PhysicsConstraintData *data = new (__FILE__, __LINE__) PhysicsConstraintData(String(name, true));
|
|
|
+ data->_order = readVarint(input, true);
|
|
|
+ data->_bone = skeletonData->_bones[readVarint(input, true)];
|
|
|
+ int flags = readByte(input);
|
|
|
+ data->_skinRequired = (flags & 1) != 0;
|
|
|
+ if ((flags & 2) != 0) data->_x = readFloat(input);
|
|
|
+ if ((flags & 4) != 0) data->_y = readFloat(input);
|
|
|
+ if ((flags & 8) != 0) data->_rotate = readFloat(input);
|
|
|
+ if ((flags & 16) != 0) data->_scaleX = readFloat(input);
|
|
|
+ if ((flags & 32) != 0) data->_shearX = readFloat(input);
|
|
|
+ data->_limit = ((flags & 64) != 0 ? readFloat(input) : 5000) * _scale;
|
|
|
+ data->_step = 1.f / readByte(input);
|
|
|
+ data->_inertia = readFloat(input);
|
|
|
+ data->_strength = readFloat(input);
|
|
|
+ data->_damping = readFloat(input);
|
|
|
+ data->_massInverse = (flags & 128) != 0 ? readFloat(input) : 1;
|
|
|
+ data->_wind = readFloat(input);
|
|
|
+ data->_gravity = readFloat(input);
|
|
|
+ flags = readByte(input);
|
|
|
+ if ((flags & 1) != 0) data->_inertiaGlobal = true;
|
|
|
+ if ((flags & 2) != 0) data->_strengthGlobal = true;
|
|
|
+ if ((flags & 4) != 0) data->_dampingGlobal = true;
|
|
|
+ if ((flags & 8) != 0) data->_massGlobal = true;
|
|
|
+ if ((flags & 16) != 0) data->_windGlobal = true;
|
|
|
+ if ((flags & 32) != 0) data->_gravityGlobal = true;
|
|
|
+ if ((flags & 64) != 0) data->_mixGlobal = true;
|
|
|
+ data->_mix = (flags & 128) != 0 ? readFloat(input) : 1;
|
|
|
+ skeletonData->_physicsConstraints[i] = data;
|
|
|
+ }
|
|
|
+
|
|
|
/* Default skin. */
|
|
|
Skin *defaultSkin = readSkin(input, true, skeletonData, nonessential);
|
|
|
if (defaultSkin) {
|
|
@@ -289,13 +348,7 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
/* Linked meshes. */
|
|
|
for (int i = 0, n = (int) _linkedMeshes.size(); i < n; ++i) {
|
|
|
LinkedMesh *linkedMesh = _linkedMeshes[i];
|
|
|
- Skin *skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin);
|
|
|
- if (skin == NULL) {
|
|
|
- delete input;
|
|
|
- delete skeletonData;
|
|
|
- setError("Skin not found: ", linkedMesh->_skin.buffer());
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ Skin *skin = skeletonData->_skins[linkedMesh->_skinIndex];
|
|
|
Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent);
|
|
|
if (parent == NULL) {
|
|
|
delete input;
|
|
@@ -316,8 +369,8 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
int eventsCount = readVarint(input, true);
|
|
|
skeletonData->_events.setSize(eventsCount, 0);
|
|
|
for (int i = 0; i < eventsCount; ++i) {
|
|
|
- const char *name = readStringRef(input, skeletonData);
|
|
|
- EventData *eventData = new (__FILE__, __LINE__) EventData(String(name));
|
|
|
+ const char *name = readString(input);
|
|
|
+ EventData *eventData = new (__FILE__, __LINE__) EventData(String(name, true));
|
|
|
eventData->_intValue = readVarint(input, false);
|
|
|
eventData->_floatValue = readFloat(input);
|
|
|
eventData->_stringValue.own(readString(input));
|
|
@@ -452,7 +505,10 @@ Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData
|
|
|
if (slotCount == 0) return NULL;
|
|
|
skin = new (__FILE__, __LINE__) Skin("default");
|
|
|
} else {
|
|
|
- skin = new (__FILE__, __LINE__) Skin(readStringRef(input, skeletonData));
|
|
|
+ skin = new (__FILE__, __LINE__) Skin(String(readString(input), true));
|
|
|
+
|
|
|
+ if (nonessential) readColor(input, skin->getColor());
|
|
|
+
|
|
|
for (int i = 0, n = readVarint(input, true); i < n; i++) {
|
|
|
int boneIndex = readVarint(input, true);
|
|
|
if (boneIndex >= (int) skeletonData->_bones.size()) return NULL;
|
|
@@ -476,6 +532,12 @@ Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData
|
|
|
if (pathIndex >= (int) skeletonData->_pathConstraints.size()) return NULL;
|
|
|
skin->getConstraints().add(skeletonData->_pathConstraints[pathIndex]);
|
|
|
}
|
|
|
+
|
|
|
+ for (int i = 0, n = readVarint(input, true); i < n; i++) {
|
|
|
+ int physicsIndex = readVarint(input, true);
|
|
|
+ if (physicsIndex >= (int) skeletonData->_physicsConstraints.size()) return NULL;
|
|
|
+ skin->getConstraints().add(skeletonData->_physicsConstraints[physicsIndex]);
|
|
|
+ }
|
|
|
slotCount = readVarint(input, true);
|
|
|
}
|
|
|
|
|
@@ -496,7 +558,6 @@ Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData
|
|
|
}
|
|
|
|
|
|
Sequence *SkeletonBinary::readSequence(DataInput *input) {
|
|
|
- if (!readBoolean(input)) return NULL;
|
|
|
Sequence *sequence = new (__FILE__, __LINE__) Sequence(readVarint(input, true));
|
|
|
sequence->_start = readVarint(input, true);
|
|
|
sequence->_digits = readVarint(input, true);
|
|
@@ -506,24 +567,23 @@ Sequence *SkeletonBinary::readSequence(DataInput *input) {
|
|
|
|
|
|
Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName,
|
|
|
SkeletonData *skeletonData, bool nonessential) {
|
|
|
- String name(readStringRef(input, skeletonData));
|
|
|
- if (name.isEmpty()) name = attachmentName;
|
|
|
|
|
|
- AttachmentType type = static_cast<AttachmentType>(readByte(input));
|
|
|
+ int flags = readByte(input);
|
|
|
+ String name = (flags & 8) != 0 ? readStringRef(input, skeletonData) : attachmentName;
|
|
|
+ AttachmentType type = static_cast<AttachmentType>(flags & 0x7);
|
|
|
switch (type) {
|
|
|
case AttachmentType_Region: {
|
|
|
- String path(readStringRef(input, skeletonData));
|
|
|
- if (path.isEmpty()) path = name;
|
|
|
- float rotation = readFloat(input);
|
|
|
+ String path = (flags & 16) != 0 ? readStringRef(input, skeletonData) : name;
|
|
|
+ Color color(1, 1, 1, 1);
|
|
|
+ if ((flags & 32) != 0) readColor(input, color);
|
|
|
+ Sequence *sequence = (flags & 64) != 0 ? readSequence(input) : nullptr;
|
|
|
+ float rotation = (flags & 128) != 0 ? readFloat(input) : 0;
|
|
|
float x = readFloat(input) * _scale;
|
|
|
float y = readFloat(input) * _scale;
|
|
|
float scaleX = readFloat(input);
|
|
|
float scaleY = readFloat(input);
|
|
|
float width = readFloat(input) * _scale;
|
|
|
float height = readFloat(input) * _scale;
|
|
|
- Color color;
|
|
|
- readColor(input, color);
|
|
|
- Sequence *sequence = readSequence(input);
|
|
|
RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path), sequence);
|
|
|
if (!region) {
|
|
|
setError("Error reading attachment: ", name.buffer());
|
|
@@ -544,14 +604,13 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
|
|
return region;
|
|
|
}
|
|
|
case AttachmentType_Boundingbox: {
|
|
|
- int vertexCount = readVarint(input, true);
|
|
|
BoundingBoxAttachment *box = _attachmentLoader->newBoundingBoxAttachment(*skin, String(name));
|
|
|
if (!box) {
|
|
|
setError("Error reading attachment: ", name.buffer());
|
|
|
return NULL;
|
|
|
}
|
|
|
- readVertices(input, box->getVertices(), box->getBones(), vertexCount);
|
|
|
- box->setWorldVerticesLength(vertexCount << 1);
|
|
|
+ readVertices(input, box->getVertices(), box->getBones(), (flags & 16) != 0);
|
|
|
+ box->setWorldVerticesLength(box->getVertices().size());
|
|
|
if (nonessential) {
|
|
|
readColor(input, box->getColor());
|
|
|
}
|
|
@@ -559,31 +618,28 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
|
|
return box;
|
|
|
}
|
|
|
case AttachmentType_Mesh: {
|
|
|
- Color color;
|
|
|
- int vertexCount;
|
|
|
Vector<float> uvs;
|
|
|
Vector<unsigned short> triangles;
|
|
|
Vector<float> vertices;
|
|
|
Vector<int> bones;
|
|
|
int hullLength;
|
|
|
- Sequence *sequence;
|
|
|
float width = 0;
|
|
|
float height = 0;
|
|
|
Vector<unsigned short> edges;
|
|
|
|
|
|
- String path(readStringRef(input, skeletonData));
|
|
|
- if (path.isEmpty()) path = name;
|
|
|
- readColor(input, color);
|
|
|
- vertexCount = readVarint(input, true);
|
|
|
- readFloatArray(input, vertexCount << 1, 1, uvs);
|
|
|
- readShortArray(input, triangles);
|
|
|
- readVertices(input, vertices, bones, vertexCount);
|
|
|
- hullLength = readVarint(input, true) << 1;
|
|
|
- sequence = readSequence(input);
|
|
|
+ String path = (flags & 16) != 0 ? readStringRef(input, skeletonData) : name;
|
|
|
+ Color color(1, 1, 1, 1);
|
|
|
+ if ((flags & 32) != 0) readColor(input, color);
|
|
|
+ Sequence *sequence = (flags & 64) != 0 ? readSequence(input) : nullptr;
|
|
|
+ hullLength = readVarint(input, true);
|
|
|
+ int verticesLength = readVertices(input, vertices, bones, (flags & 128) != 0);
|
|
|
+ readFloatArray(input, verticesLength, 1, uvs);
|
|
|
+ readShortArray(input, triangles, (verticesLength - hullLength - 2) * 3);
|
|
|
+
|
|
|
if (nonessential) {
|
|
|
- readShortArray(input, edges);
|
|
|
- width = readFloat(input) * _scale;
|
|
|
- height = readFloat(input) * _scale;
|
|
|
+ readShortArray(input, edges, readVarint(input, true));
|
|
|
+ width = readFloat(input);
|
|
|
+ height = readFloat(input);
|
|
|
}
|
|
|
|
|
|
MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence);
|
|
@@ -595,7 +651,7 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
|
|
mesh->_color.set(color);
|
|
|
mesh->_bones.addAll(bones);
|
|
|
mesh->_vertices.addAll(vertices);
|
|
|
- mesh->setWorldVerticesLength(vertexCount << 1);
|
|
|
+ mesh->setWorldVerticesLength(verticesLength);
|
|
|
mesh->_triangles.addAll(triangles);
|
|
|
mesh->_regionUVs.addAll(uvs);
|
|
|
if (sequence == NULL) mesh->updateRegion();
|
|
@@ -610,16 +666,14 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
|
|
return mesh;
|
|
|
}
|
|
|
case AttachmentType_Linkedmesh: {
|
|
|
- String path(readStringRef(input, skeletonData));
|
|
|
- if (path.isEmpty()) path = name;
|
|
|
-
|
|
|
- Color color;
|
|
|
- float width = 0, height = 0;
|
|
|
- readColor(input, color);
|
|
|
- String skinName(readStringRef(input, skeletonData));
|
|
|
+ String path = (flags & 16) != 0 ? readStringRef(input, skeletonData) : name;
|
|
|
+ Color color(1, 1, 1, 1);
|
|
|
+ if ((flags & 32) != 0) readColor(input, color);
|
|
|
+ Sequence *sequence = (flags & 64) != 0 ? readSequence(input) : nullptr;
|
|
|
+ bool inheritTimelines = (flags & 128) != 0;
|
|
|
+ int skinIndex = readVarint(input, true);
|
|
|
String parent(readStringRef(input, skeletonData));
|
|
|
- bool inheritTimelines = readBoolean(input);
|
|
|
- Sequence *sequence = readSequence(input);
|
|
|
+ float width = 0, height = 0;
|
|
|
if (nonessential) {
|
|
|
width = readFloat(input) * _scale;
|
|
|
height = readFloat(input) * _scale;
|
|
@@ -638,7 +692,7 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
|
|
mesh->_height = height;
|
|
|
}
|
|
|
|
|
|
- LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, String(skinName), slotIndex,
|
|
|
+ LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, skinIndex, slotIndex,
|
|
|
String(parent), inheritTimelines);
|
|
|
_linkedMeshes.add(linkedMesh);
|
|
|
return mesh;
|
|
@@ -649,12 +703,11 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
|
|
setError("Error reading attachment: ", name.buffer());
|
|
|
return NULL;
|
|
|
}
|
|
|
- path->_closed = readBoolean(input);
|
|
|
- path->_constantSpeed = readBoolean(input);
|
|
|
- int vertexCount = readVarint(input, true);
|
|
|
- readVertices(input, path->getVertices(), path->getBones(), vertexCount);
|
|
|
- path->setWorldVerticesLength(vertexCount << 1);
|
|
|
- int lengthsLength = vertexCount / 3;
|
|
|
+ path->_closed = (flags & 16) != 0;
|
|
|
+ path->_constantSpeed = (flags & 32) != 0;
|
|
|
+ int verticesLength = readVertices(input, path->getVertices(), path->getBones(), (flags & 64) != 0);
|
|
|
+ path->setWorldVerticesLength(verticesLength);
|
|
|
+ int lengthsLength = verticesLength / 6;
|
|
|
path->_lengths.setSize(lengthsLength, 0);
|
|
|
for (int i = 0; i < lengthsLength; ++i) {
|
|
|
path->_lengths[i] = readFloat(input) * _scale;
|
|
@@ -683,14 +736,13 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
|
|
}
|
|
|
case AttachmentType_Clipping: {
|
|
|
int endSlotIndex = readVarint(input, true);
|
|
|
- int vertexCount = readVarint(input, true);
|
|
|
ClippingAttachment *clip = _attachmentLoader->newClippingAttachment(*skin, name);
|
|
|
if (!clip) {
|
|
|
setError("Error reading attachment: ", name.buffer());
|
|
|
return NULL;
|
|
|
}
|
|
|
- readVertices(input, clip->getVertices(), clip->getBones(), vertexCount);
|
|
|
- clip->setWorldVerticesLength(vertexCount << 1);
|
|
|
+ int verticesLength = readVertices(input, clip->getVertices(), clip->getBones(), (flags & 16) != 0);
|
|
|
+ clip->setWorldVerticesLength(verticesLength);
|
|
|
clip->_endSlot = skeletonData->_slots[endSlotIndex];
|
|
|
if (nonessential) {
|
|
|
readColor(input, clip->getColor());
|
|
@@ -702,18 +754,16 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-void SkeletonBinary::readVertices(DataInput *input, Vector<float> &vertices, Vector<int> &bones, int vertexCount) {
|
|
|
+int SkeletonBinary::readVertices(DataInput *input, Vector<float> &vertices, Vector<int> &bones, bool weighted) {
|
|
|
float scale = _scale;
|
|
|
+ int vertexCount = readVarint(input, true);
|
|
|
int verticesLength = vertexCount << 1;
|
|
|
-
|
|
|
- if (!readBoolean(input)) {
|
|
|
- readFloatArray(input, verticesLength, scale, vertices);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- vertices.ensureCapacity(verticesLength * 3 * 3);
|
|
|
- bones.ensureCapacity(verticesLength * 3);
|
|
|
-
|
|
|
+ if (!weighted) {
|
|
|
+ readFloatArray(input, verticesLength, scale, vertices);
|
|
|
+ return verticesLength;
|
|
|
+ }
|
|
|
+ vertices.ensureCapacity(verticesLength * 3 * 3);
|
|
|
+ bones.ensureCapacity(verticesLength * 3);
|
|
|
for (int i = 0; i < vertexCount; ++i) {
|
|
|
int boneCount = readVarint(input, true);
|
|
|
bones.add(boneCount);
|
|
@@ -724,6 +774,7 @@ void SkeletonBinary::readVertices(DataInput *input, Vector<float> &vertices, Vec
|
|
|
vertices.add(readFloat(input));
|
|
|
}
|
|
|
}
|
|
|
+ return verticesLength;
|
|
|
}
|
|
|
|
|
|
void SkeletonBinary::readFloatArray(DataInput *input, int n, float scale, Vector<float> &array) {
|
|
@@ -741,14 +792,10 @@ void SkeletonBinary::readFloatArray(DataInput *input, int n, float scale, Vector
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void SkeletonBinary::readShortArray(DataInput *input, Vector<unsigned short> &array) {
|
|
|
- int n = readVarint(input, true);
|
|
|
+void SkeletonBinary::readShortArray(DataInput *input, Vector<unsigned short> &array, int n) {
|
|
|
array.setSize(n, 0);
|
|
|
-
|
|
|
- int i;
|
|
|
- for (i = 0; i < n; ++i) {
|
|
|
- array[i] = readByte(input) << 8;
|
|
|
- array[i] |= readByte(input);
|
|
|
+ for (int i = 0; i < n; ++i) {
|
|
|
+ array[i] = (short)readVarint(input, true);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -762,7 +809,7 @@ void SkeletonBinary::setBezier(DataInput *input, CurveTimeline *timeline, int be
|
|
|
timeline->setBezier(bezier, frame, value, time1, value1, cx1, cy1 * scale, cx2, cy2 * scale, time2, value2);
|
|
|
}
|
|
|
|
|
|
-Timeline *SkeletonBinary::readTimeline(DataInput *input, CurveTimeline1 *timeline, float scale) {
|
|
|
+void SkeletonBinary::readTimeline(DataInput *input, Vector<Timeline*> &timelines, CurveTimeline1 *timeline, float scale) {
|
|
|
float time = readFloat(input);
|
|
|
float value = readFloat(input) * scale;
|
|
|
for (int frame = 0, bezier = 0, frameLast = (int) timeline->getFrameCount() - 1;; frame++) {
|
|
@@ -780,10 +827,10 @@ Timeline *SkeletonBinary::readTimeline(DataInput *input, CurveTimeline1 *timelin
|
|
|
time = time2;
|
|
|
value = value2;
|
|
|
}
|
|
|
- return timeline;
|
|
|
+ timelines.add(timeline);
|
|
|
}
|
|
|
|
|
|
-Timeline *SkeletonBinary::readTimeline2(DataInput *input, CurveTimeline2 *timeline, float scale) {
|
|
|
+void SkeletonBinary::readTimeline2(DataInput *input, Vector<Timeline*> &timelines, CurveTimeline2 *timeline, float scale) {
|
|
|
float time = readFloat(input);
|
|
|
float value1 = readFloat(input) * scale;
|
|
|
float value2 = readFloat(input) * scale;
|
|
@@ -805,7 +852,7 @@ Timeline *SkeletonBinary::readTimeline2(DataInput *input, CurveTimeline2 *timeli
|
|
|
value1 = nvalue1;
|
|
|
value2 = nvalue2;
|
|
|
}
|
|
|
- return timeline;
|
|
|
+ timelines.add(timeline);
|
|
|
}
|
|
|
|
|
|
Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData) {
|
|
@@ -1039,50 +1086,59 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|
|
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
|
|
unsigned char timelineType = readByte(input);
|
|
|
int frameCount = readVarint(input, true);
|
|
|
- int bezierCount = readVarint(input, true);
|
|
|
- Timeline *timeline = NULL;
|
|
|
+ if (timelineType == BONE_INHERIT) {
|
|
|
+ InheritTimeline *timeline = new (__FILE__, __LINE__) InheritTimeline(frameCount, boneIndex);
|
|
|
+ for (int frame = 0; frame < frameCount; frame++) {
|
|
|
+ float time = readFloat(input);
|
|
|
+ Inherit inherit = (Inherit)readByte(input);
|
|
|
+ timeline->setFrame(frame, time, inherit);
|
|
|
+ }
|
|
|
+ timelines.add(timeline);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int bezierCount = readVarint(input, true);
|
|
|
switch (timelineType) {
|
|
|
case BONE_ROTATE:
|
|
|
- timeline = readTimeline(input,
|
|
|
+ readTimeline(input, timelines,
|
|
|
new (__FILE__, __LINE__) RotateTimeline(frameCount, bezierCount, boneIndex),
|
|
|
1);
|
|
|
break;
|
|
|
case BONE_TRANSLATE:
|
|
|
- timeline = readTimeline2(input, new (__FILE__, __LINE__) TranslateTimeline(frameCount, bezierCount, boneIndex), scale);
|
|
|
+ readTimeline2(input, timelines,new (__FILE__, __LINE__) TranslateTimeline(frameCount, bezierCount, boneIndex), scale);
|
|
|
break;
|
|
|
case BONE_TRANSLATEX:
|
|
|
- timeline = readTimeline(input, new (__FILE__, __LINE__) TranslateXTimeline(frameCount, bezierCount, boneIndex), scale);
|
|
|
+ readTimeline(input, timelines, new (__FILE__, __LINE__) TranslateXTimeline(frameCount, bezierCount, boneIndex), scale);
|
|
|
break;
|
|
|
case BONE_TRANSLATEY:
|
|
|
- timeline = readTimeline(input, new (__FILE__, __LINE__) TranslateYTimeline(frameCount, bezierCount, boneIndex), scale);
|
|
|
+ readTimeline(input, timelines, new (__FILE__, __LINE__) TranslateYTimeline(frameCount, bezierCount, boneIndex), scale);
|
|
|
break;
|
|
|
case BONE_SCALE:
|
|
|
- timeline = readTimeline2(input,
|
|
|
+ readTimeline2(input, timelines,
|
|
|
new (__FILE__, __LINE__) ScaleTimeline(frameCount, bezierCount, boneIndex),
|
|
|
1);
|
|
|
break;
|
|
|
case BONE_SCALEX:
|
|
|
- timeline = readTimeline(input,
|
|
|
+ readTimeline(input, timelines,
|
|
|
new (__FILE__, __LINE__) ScaleXTimeline(frameCount, bezierCount, boneIndex),
|
|
|
1);
|
|
|
break;
|
|
|
case BONE_SCALEY:
|
|
|
- timeline = readTimeline(input,
|
|
|
+ readTimeline(input, timelines,
|
|
|
new (__FILE__, __LINE__) ScaleYTimeline(frameCount, bezierCount, boneIndex),
|
|
|
1);
|
|
|
break;
|
|
|
case BONE_SHEAR:
|
|
|
- timeline = readTimeline2(input,
|
|
|
+ readTimeline2(input, timelines,
|
|
|
new (__FILE__, __LINE__) ShearTimeline(frameCount, bezierCount, boneIndex),
|
|
|
1);
|
|
|
break;
|
|
|
case BONE_SHEARX:
|
|
|
- timeline = readTimeline(input,
|
|
|
+ readTimeline(input, timelines,
|
|
|
new (__FILE__, __LINE__) ShearXTimeline(frameCount, bezierCount, boneIndex),
|
|
|
1);
|
|
|
break;
|
|
|
case BONE_SHEARY:
|
|
|
- timeline = readTimeline(input,
|
|
|
+ readTimeline(input, timelines,
|
|
|
new (__FILE__, __LINE__) ShearYTimeline(frameCount, bezierCount, boneIndex),
|
|
|
1);
|
|
|
break;
|
|
@@ -1092,7 +1148,6 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|
|
return NULL;
|
|
|
}
|
|
|
}
|
|
|
- timelines.add(timeline);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1103,25 +1158,20 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|
|
int frameLast = frameCount - 1;
|
|
|
int bezierCount = readVarint(input, true);
|
|
|
IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(frameCount, bezierCount, index);
|
|
|
- float time = readFloat(input);
|
|
|
- float mix = readFloat(input);
|
|
|
- float softness = readFloat(input) * scale;
|
|
|
- for (int frame = 0, bezier = 0;; frame++) {
|
|
|
- int bendDirection = readSByte(input);
|
|
|
- bool compress = readBoolean(input);
|
|
|
- bool stretch = readBoolean(input);
|
|
|
- timeline->setFrame(frame, time, mix, softness, bendDirection, compress, stretch);
|
|
|
+ int flags = readByte(input);
|
|
|
+ float time = readFloat(input), mix = (flags & 1) != 0 ? ((flags & 2) != 0 ? readFloat(input) : 1) : 0;
|
|
|
+ float softness = (flags & 4) != 0 ? readFloat(input) * scale : 0;
|
|
|
+ for (int frame = 0, bezier = 0;; frame++) {
|
|
|
+ timeline->setFrame(frame, time, mix, softness, (flags & 8) != 0 ? 1 : -1, (flags & 16) != 0, (flags & 32) != 0);
|
|
|
if (frame == frameLast) break;
|
|
|
- float time2 = readFloat(input);
|
|
|
- float mix2 = readFloat(input);
|
|
|
- float softness2 = readFloat(input) * scale;
|
|
|
- switch (readSByte(input)) {
|
|
|
- case CURVE_STEPPED:
|
|
|
- timeline->setStepped(frame);
|
|
|
- break;
|
|
|
- case CURVE_BEZIER:
|
|
|
- setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1);
|
|
|
- setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale);
|
|
|
+ flags = readByte(input);
|
|
|
+ float time2 = readFloat(input), mix2 = (flags & 1) != 0 ? ((flags & 2) != 0 ? readFloat(input) : 1) : 0;
|
|
|
+ float softness2 = (flags & 4) != 0 ? readFloat(input) * scale : 0;
|
|
|
+ if ((flags & 64) != 0)
|
|
|
+ timeline->setStepped(frame);
|
|
|
+ else if ((flags & 128) != 0) {
|
|
|
+ setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1);
|
|
|
+ setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale);
|
|
|
}
|
|
|
time = time2;
|
|
|
mix = mix2;
|
|
@@ -1182,26 +1232,24 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|
|
int index = readVarint(input, true);
|
|
|
PathConstraintData *data = skeletonData->_pathConstraints[index];
|
|
|
for (int ii = 0, nn = readVarint(input, true); ii < nn; ii++) {
|
|
|
- int type = readSByte(input);
|
|
|
+ int type = readByte(input);
|
|
|
int frameCount = readVarint(input, true);
|
|
|
int bezierCount = readVarint(input, true);
|
|
|
- switch (type) {
|
|
|
+ switch (type) {
|
|
|
case PATH_POSITION: {
|
|
|
- timelines
|
|
|
- .add(readTimeline(input, new PathConstraintPositionTimeline(frameCount, bezierCount, index),
|
|
|
- data->_positionMode == PositionMode_Fixed ? scale : 1));
|
|
|
+ readTimeline(input, timelines, new PathConstraintPositionTimeline(frameCount, bezierCount, index),
|
|
|
+ data->_positionMode == PositionMode_Fixed ? scale : 1);
|
|
|
break;
|
|
|
}
|
|
|
case PATH_SPACING: {
|
|
|
- timelines
|
|
|
- .add(readTimeline(input,
|
|
|
+ readTimeline(input, timelines,
|
|
|
new PathConstraintSpacingTimeline(frameCount,
|
|
|
bezierCount,
|
|
|
index),
|
|
|
data->_spacingMode == SpacingMode_Length ||
|
|
|
data->_spacingMode == SpacingMode_Fixed
|
|
|
? scale
|
|
|
- : 1));
|
|
|
+ : 1);
|
|
|
break;
|
|
|
}
|
|
|
case PATH_MIX:
|
|
@@ -1236,7 +1284,46 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Deform timelines.
|
|
|
+ // Physics timelines.
|
|
|
+ for (int i = 0, n = readVarint(input, true); i < n; i++) {
|
|
|
+ int index = readVarint(input, true) - 1;
|
|
|
+ for (int ii = 0, nn = readVarint(input, true); ii < nn; ii++) {
|
|
|
+ int type = readByte(input);
|
|
|
+ int frameCount = readVarint(input, true);
|
|
|
+ if (type == PHYSICS_RESET) {
|
|
|
+ PhysicsConstraintResetTimeline *timeline = new (__FILE__, __LINE__) PhysicsConstraintResetTimeline(frameCount, index);
|
|
|
+ for (int frame = 0; frame < frameCount; frame++)
|
|
|
+ timeline->setFrame(frame, readFloat(input));
|
|
|
+ timelines.add(timeline);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int bezierCount = readVarint(input, true);
|
|
|
+ switch (type) {
|
|
|
+ case PHYSICS_INERTIA:
|
|
|
+ readTimeline(input, timelines, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1);
|
|
|
+ break;
|
|
|
+ case PHYSICS_STRENGTH:
|
|
|
+ readTimeline(input, timelines, new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index), 1);
|
|
|
+ break;
|
|
|
+ case PHYSICS_DAMPING:
|
|
|
+ readTimeline(input, timelines, new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index), 1);
|
|
|
+ break;
|
|
|
+ case PHYSICS_MASS:
|
|
|
+ readTimeline(input, timelines, new PhysicsConstraintMassTimeline(frameCount, bezierCount, index), 1);
|
|
|
+ break;
|
|
|
+ case PHYSICS_WIND:
|
|
|
+ readTimeline(input, timelines, new PhysicsConstraintWindTimeline(frameCount, bezierCount, index), 1);
|
|
|
+ break;
|
|
|
+ case PHYSICS_GRAVITY:
|
|
|
+ readTimeline(input, timelines, new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index), 1);
|
|
|
+ break;
|
|
|
+ case PHYSICS_MIX:
|
|
|
+ readTimeline(input, timelines, new PhysicsConstraintMixTimeline(frameCount, bezierCount, index), 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Attachment timelines.
|
|
|
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
|
|
Skin *skin = skeletonData->_skins[readVarint(input, true)];
|
|
|
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
|
@@ -1379,10 +1466,13 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|
|
|
|
|
event->_intValue = readVarint(input, false);
|
|
|
event->_floatValue = readFloat(input);
|
|
|
- bool freeString = readBoolean(input);
|
|
|
- const char *event_stringValue = freeString ? readString(input) : eventData->_stringValue.buffer();
|
|
|
- event->_stringValue = String(event_stringValue);
|
|
|
- if (freeString) SpineExtension::free(event_stringValue, __FILE__, __LINE__);
|
|
|
+ const char *event_stringValue = readString(input);
|
|
|
+ if (event_stringValue == nullptr) {
|
|
|
+ event->_stringValue = eventData->_stringValue;
|
|
|
+ } else {
|
|
|
+ event->_stringValue = String(event_stringValue);
|
|
|
+ SpineExtension::free(event_stringValue, __FILE__, __LINE__);
|
|
|
+ }
|
|
|
|
|
|
if (!eventData->_audioPath.isEmpty()) {
|
|
|
event->_volume = readFloat(input);
|