diff --git a/spine-cpp/spine-cpp/include/spine/ConstraintData.h b/spine-cpp/spine-cpp/include/spine/ConstraintData.h index c35a7e672..3ed15f32b 100644 --- a/spine-cpp/spine-cpp/include/spine/ConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/ConstraintData.h @@ -37,6 +37,8 @@ namespace spine { /// The interface for all constraints. class SP_API ConstraintData : public SpineObject { + friend class SkeletonBinary; + RTTI_DECL public: diff --git a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h index 053aa90c1..59bd460ca 100644 --- a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h +++ b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h @@ -42,12 +42,16 @@ namespace spine { friend class SkeletonJson; public: - LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, + LinkedMesh(MeshAttachment *mesh, const int skinIndex, size_t slotIndex, const String &parent, bool inheritTimeline); + LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, + bool inheritTimeline); + private: MeshAttachment *_mesh; - String _skin; + int _skinIndex; + String _skin; size_t _slotIndex; String _parent; bool _inheritTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h index 2f1fff497..7415dc1a2 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -75,6 +75,7 @@ namespace spine { static const int BONE_SHEAR = 7; static const int BONE_SHEARX = 8; static const int BONE_SHEARY = 9; + static const int BONE_INHERIT = 10; static const int SLOT_ATTACHMENT = 0; static const int SLOT_RGBA = 1; @@ -90,6 +91,15 @@ namespace spine { static const int PATH_SPACING = 1; static const int PATH_MIX = 2; + static const int PHYSICS_INERTIA = 0; + static const int PHYSICS_STRENGTH = 1; + static const int PHYSICS_DAMPING = 2; + static const int PHYSICS_MASS = 4; + static const int PHYSICS_WIND = 5; + static const int PHYSICS_GRAVITY = 6; + static const int PHYSICS_MIX = 7; + static const int PHYSICS_RESET = 8; + static const int CURVE_LINEAR = 0; static const int CURVE_STEPPED = 1; static const int CURVE_BEZIER = 2; @@ -147,11 +157,11 @@ namespace spine { Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, SkeletonData *skeletonData, bool nonessential); - void readVertices(DataInput *input, Vector &vertices, Vector &bones, int vertexCount); + int readVertices(DataInput *input, Vector &vertices, Vector &bones, bool weighted); void readFloatArray(DataInput *input, int n, float scale, Vector &array); - void readShortArray(DataInput *input, Vector &array); + void readShortArray(DataInput *input, Vector &array, int n); Animation *readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData); @@ -159,9 +169,9 @@ namespace spine { setBezier(DataInput *input, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, float value1, float value2, float scale); - Timeline *readTimeline(DataInput *input, CurveTimeline1 *timeline, float scale); + void readTimeline(DataInput *input, Vector &timelines, CurveTimeline1 *timeline, float scale); - Timeline *readTimeline2(DataInput *input, CurveTimeline2 *timeline, float scale); + void readTimeline2(DataInput *input, Vector &timelines, CurveTimeline2 *timeline, float scale); }; } diff --git a/spine-cpp/spine-cpp/include/spine/SpineString.h b/spine-cpp/spine-cpp/include/spine/SpineString.h index f60cd9209..d2e13a702 100644 --- a/spine-cpp/spine-cpp/include/spine/SpineString.h +++ b/spine-cpp/spine-cpp/include/spine/SpineString.h @@ -195,7 +195,7 @@ namespace spine { } String substring(int startIndex, int length) const { - if (startIndex < 0 || startIndex >= _length || length < 0 || startIndex + length > _length) { + if (startIndex < 0 || startIndex >= (int)_length || length < 0 || startIndex + length > (int)_length) { return String(); } char* subStr = SpineExtension::calloc(length + 1, __FILE__, __LINE__); @@ -205,7 +205,7 @@ namespace spine { } String substring(int startIndex) const { - if (startIndex < 0 || startIndex >= _length) { + if (startIndex < 0 || startIndex >= (int)_length) { return String(); } int length = _length - startIndex; diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index 645838834..7aff7dc75 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -45,7 +45,7 @@ void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress float rotationIK = -bone._ashearX - bone._arotation; float tx = 0, ty = 0; - switch (bone._data.getInherit()) { + switch (bone._inherit) { case Inherit_OnlyTranslation: tx = (targetX - bone._worldX) * MathUtil::sign(bone.getSkeleton().getScaleX()); ty = (targetY - bone._worldY) * MathUtil::sign(bone.getSkeleton().getScaleY()); @@ -77,7 +77,7 @@ void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress float sx = bone._ascaleX; float sy = bone._ascaleY; if (compress || stretch) { - switch (bone._data.getInherit()) { + switch (bone._inherit) { case Inherit_NoScale: case Inherit_NoScaleOrReflection: tx = targetX - bone._worldX; @@ -109,7 +109,8 @@ void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY Bone *pp = parent.getParent(); float tx, ty, dx, dy, dd, l1, l2, a1, a2, r, td, sd, p; float id, x, y; - px = parent._ax; + if (parent._inherit != Inherit_Normal || child._inherit != Inherit_Normal) return; + px = parent._ax; py = parent._ay; psx = parent._ascaleX; psy = parent._ascaleY; diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index 090e098a2..00b870a03 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -37,11 +37,11 @@ RTTI_IMPL(IkConstraintData, ConstraintData) IkConstraintData::IkConstraintData(const String &name) : ConstraintData(name), _target(NULL), - _bendDirection(1), + _bendDirection(0), _compress(false), _stretch(false), _uniform(false), - _mix(1), + _mix(0), _softness(0) { } diff --git a/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp b/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp index a67e9173d..1d716ee08 100644 --- a/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp +++ b/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp @@ -33,10 +33,20 @@ using namespace spine; -LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, - bool inheritTimeline) : _mesh(mesh), - _skin(skin), - _slotIndex(slotIndex), - _parent(parent), - _inheritTimeline(inheritTimeline) { +LinkedMesh::LinkedMesh(MeshAttachment *mesh, const int skinIndex, size_t slotIndex, const String &parent, + bool inheritTimeline) : _mesh(mesh), + _skinIndex(skinIndex), + _skin(""), + _slotIndex(slotIndex), + _parent(parent), + _inheritTimeline(inheritTimeline) { +} + +LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, + bool inheritTimeline) : _mesh(mesh), + _skinIndex(-1), + _skin(skin), + _slotIndex(slotIndex), + _parent(parent), + _inheritTimeline(inheritTimeline) { } diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index e6c38c096..df7f0e071 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -136,6 +136,7 @@ Skeleton::~Skeleton() { ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); + ContainerUtil::cleanUpVectorOfPointers(_physicsConstraints); } void Skeleton::updateCache() { @@ -195,7 +196,7 @@ continue_outer: } } - for (size_t ii = 0; ii < pathCount; ++ii) { + for (size_t ii = 0; ii < physicsCount; ++ii) { PhysicsConstraint *constraint = _physicsConstraints[ii]; if (constraint->getData().getOrder() == i) { sortPhysicsConstraint(constraint); @@ -222,7 +223,9 @@ void Skeleton::printUpdateCache() { printf("ik constraint %s\n", ((IkConstraint *) updatable)->getData().getName().buffer()); } else if (updatable->getRTTI().isExactly(PathConstraint::rtti)) { printf("path constraint %s\n", ((PathConstraint *) updatable)->getData().getName().buffer()); - } + } else if (updatable->getRTTI().isExactly(PhysicsConstraint::rtti)) { + printf("physics constraint %s\n", ((PhysicsConstraint *) updatable)->getData().getName().buffer()); + } } } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index 9db71116a..af29d00eb 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -53,12 +53,15 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -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(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(readVarint(input, true)); - data->_spacingMode = static_cast(readVarint(input, true)); - data->_rotateMode = static_cast(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(readByte(input)); + int flags = readByte(input); + String name = (flags & 8) != 0 ? readStringRef(input, skeletonData) : attachmentName; + AttachmentType type = static_cast(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 uvs; Vector triangles; Vector vertices; Vector bones; int hullLength; - Sequence *sequence; float width = 0; float height = 0; Vector 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 &vertices, Vector &bones, int vertexCount) { +int SkeletonBinary::readVertices(DataInput *input, Vector &vertices, Vector &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 &vertices, Vec vertices.add(readFloat(input)); } } + return verticesLength; } void SkeletonBinary::readFloatArray(DataInput *input, int n, float scale, Vector &array) { @@ -741,14 +792,10 @@ void SkeletonBinary::readFloatArray(DataInput *input, int n, float scale, Vector } } -void SkeletonBinary::readShortArray(DataInput *input, Vector &array) { - int n = readVarint(input, true); +void SkeletonBinary::readShortArray(DataInput *input, Vector &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 &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 &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); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index 64bad8377..1cbf17e10 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -133,7 +134,7 @@ SkeletonData *SkeletonJson::readSkeletonDataFile(const String &path) { SkeletonData *SkeletonJson::readSkeletonData(const char *json) { int i, ii; SkeletonData *skeletonData; - Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events; + Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *physics, *slots, *skins, *animations, *events; _error = ""; _linkedMeshes.clear(); @@ -455,6 +456,54 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) { } } + /* Physics constraints */ + physics = Json::getItem(root, "physics"); + if (physics) { + Json *constraintMap; + skeletonData->_physicsConstraints.ensureCapacity(physics->_size); + skeletonData->_physicsConstraints.setSize(physics->_size, 0); + for (constraintMap = physics->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { + const char *name; + + PhysicsConstraintData *data = new (__FILE__, __LINE__) PhysicsConstraintData( + Json::getString(constraintMap, "name", 0)); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); + + name = Json::getString(constraintMap, "bone", 0); + data->_bone = skeletonData->findBone(name); + if (!data->_bone) { + delete skeletonData; + setError(root, "Physics bone not found: ", name); + return NULL; + } + + data->_x = Json::getFloat(constraintMap, "x", 0); + data->_y = Json::getFloat(constraintMap, "y", 0); + data->_rotate = Json::getFloat(constraintMap, "rotate", 0); + data->_scaleX = Json::getFloat(constraintMap, "scaleX", 0); + data->_shearX = Json::getFloat(constraintMap, "shearX", 0); + data->_limit = Json::getFloat(constraintMap, "limit", 5000) * _scale; + data->_step = 1.0f / Json::getInt(constraintMap, "fps", 60); + data->_inertia = Json::getFloat(constraintMap, "inertia", 1); + data->_strength = Json::getFloat(constraintMap, "strength", 100); + data->_damping = Json::getFloat(constraintMap, "damping", 1); + data->_massInverse = 1 / Json::getFloat(constraintMap, "mass", 1); + data->_wind = Json::getFloat(constraintMap, "wind", 0); + data->_gravity = Json::getFloat(constraintMap, "gravity", 0); + data->_mix = Json::getFloat(constraintMap, "mix", 1); + data->_inertiaGlobal = Json::getBoolean(constraintMap, "inertiaGlobal", false); + data->_strengthGlobal = Json::getBoolean(constraintMap, "strengthGlobal", false); + data->_dampingGlobal = Json::getBoolean(constraintMap, "dampingGlobal", false); + data->_massGlobal = Json::getBoolean(constraintMap, "massGlobal", false); + data->_windGlobal = Json::getBoolean(constraintMap, "windGlobal", false); + data->_gravityGlobal = Json::getBoolean(constraintMap, "gravityGlobal", false); + data->_mixGlobal = Json::getBoolean(constraintMap, "mixGlobal", false); + + skeletonData->_physicsConstraints[i] = data; + } + } + /* Skins. */ skins = Json::getItem(root, "skins"); if (skins) { @@ -520,6 +569,19 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) { } } + item = Json::getItem(skinMap, "physics"); + if (item) { + for (item = item->_child; item; item = item->_next) { + PhysicsConstraintData *data = skeletonData->findPhysicsConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin physics constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + skeletonData->_skins[skinsIndex++] = skin; if (strcmp(Json::getString(skinMap, "name", ""), "default") == 0) { skeletonData->_defaultSkin = skin; diff --git a/spine-sfml/cpp/example/main.cpp b/spine-sfml/cpp/example/main.cpp index 71112ba32..f54643c2f 100644 --- a/spine-sfml/cpp/example/main.cpp +++ b/spine-sfml/cpp/example/main.cpp @@ -611,6 +611,40 @@ void mixAndMatch(SkeletonData *skeletonData, Atlas *atlas) { } } +void celestialCircus(SkeletonData *skeletonData, Atlas *atlas) { + SP_UNUSED(atlas); + + SkeletonDrawable drawable(skeletonData); + drawable.timeScale = 1; + drawable.setUsePremultipliedAlpha(true); + + Skeleton *skeleton = drawable.skeleton; + skeleton->setPosition(320, 480); + skeleton->updateWorldTransform(Physics_Update); + + drawable.state->setAnimation(0, "swing", true); + + sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - celestial circus"); + window.setFramerateLimit(60); + sf::Event event; + sf::Clock deltaClock; + + while (window.isOpen()) { + while (window.pollEvent(event)) { + if (event.type == sf::Event::Closed) window.close(); + } + + float delta = deltaClock.getElapsedTime().asSeconds(); + deltaClock.restart(); + + drawable.update(delta); + + window.clear(); + window.draw(drawable); + window.display(); + } +} + /** * Used for debugging purposes during runtime development */ @@ -636,11 +670,11 @@ DebugExtension dbgExtension(SpineExtension::getInstance()); int main() { SpineExtension::setInstance(&dbgExtension); + testcase(ikDemo, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f); + testcase(celestialCircus, "data/celestial-circus-pro.json", "data/celestial-circus-pro.skel", "data/celestial-circus-pma.atlas", 0.2f); testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine-pma.atlas", 0.5f); testcase(dragon, "data/dragon-ess.json", "data/dragon-ess.skel", "data/dragon-pma.atlas", 0.6f); - testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine-pma.atlas", 0.5f); testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f); - testcase(ikDemo, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f); testcase(mixAndMatch, "data/mix-and-match-pro.json", "data/mix-and-match-pro.skel", "data/mix-and-match-pma.atlas", 0.5f); testcase(coin, "data/coin-pro.json", "data/coin-pro.skel", "data/coin-pma.atlas", 0.5f); testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f); diff --git a/spine-sfml/cpp/src/spine/spine-sfml.cpp b/spine-sfml/cpp/src/spine/spine-sfml.cpp index edeaf89c9..2dddbd239 100644 --- a/spine-sfml/cpp/src/spine/spine-sfml.cpp +++ b/spine-sfml/cpp/src/spine/spine-sfml.cpp @@ -79,6 +79,7 @@ namespace spine { void SkeletonDrawable::update(float deltaTime, Physics physics) { state->update(deltaTime * timeScale); state->apply(*skeleton); + skeleton->update(deltaTime * timeScale); skeleton->updateWorldTransform(physics); }