From e7c4a3eef0495e41fac722d1b80fd9b72c33e835 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 7 Jul 2025 19:15:16 +0200 Subject: [PATCH] [cpp] 4.3 porting WIP --- spine-cpp/spine-cpp/include/spine/BoneLocal.h | 1 + spine-cpp/spine-cpp/include/spine/Color.h | 18 + .../include/spine/IkConstraintPose.h | 1 + .../include/spine/PathConstraintPose.h | 1 + .../include/spine/PhysicsConstraintPose.h | 1 + .../spine-cpp/include/spine/SkeletonBinary.h | 158 +++- .../spine-cpp/include/spine/SliderPose.h | 2 + spine-cpp/spine-cpp/include/spine/SlotPose.h | 1 + .../include/spine/TransformConstraintData.h | 12 +- .../include/spine/TransformConstraintPose.h | 1 + spine-cpp/spine-cpp/include/spine/Vector.h | 3 +- .../spine-cpp/src/spine/SkeletonBinary.cpp | 813 +++++++++--------- .../src/spine/TransformConstraintData.cpp | 6 +- 13 files changed, 585 insertions(+), 433 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/BoneLocal.h b/spine-cpp/spine-cpp/include/spine/BoneLocal.h index 20b821abc..7116262fc 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneLocal.h +++ b/spine-cpp/spine-cpp/include/spine/BoneLocal.h @@ -53,6 +53,7 @@ namespace spine { friend class TranslateXTimeline; friend class TranslateYTimeline; friend class SkeletonJson; + friend class SkeletonBinary; friend class Skeleton; friend class FromProperty; friend class ToProperty; diff --git a/spine-cpp/spine-cpp/include/spine/Color.h b/spine-cpp/spine-cpp/include/spine/Color.h index 119bc78d1..cf1eceef2 100644 --- a/spine-cpp/spine-cpp/include/spine/Color.h +++ b/spine-cpp/spine-cpp/include/spine/Color.h @@ -130,6 +130,24 @@ namespace spine { return strtoul(digits, NULL, 16) / 255.0f; } + // Convert packed RGBA8888 integer to Color + static void rgba8888ToColor(Color& color, int value) { + unsigned int rgba = (unsigned int)value; + color.r = ((rgba & 0xff000000) >> 24) / 255.0f; + color.g = ((rgba & 0x00ff0000) >> 16) / 255.0f; + color.b = ((rgba & 0x0000ff00) >> 8) / 255.0f; + color.a = (rgba & 0x000000ff) / 255.0f; + } + + // Convert packed RGB888 integer to Color (no alpha) + static void rgb888ToColor(Color& color, int value) { + unsigned int rgb = (unsigned int)value; + color.r = ((rgb & 0xff0000) >> 16) / 255.0f; + color.g = ((rgb & 0x00ff00) >> 8) / 255.0f; + color.b = (rgb & 0x0000ff) / 255.0f; + color.a = 1.0f; + } + float r, g, b, a; }; } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintPose.h b/spine-cpp/spine-cpp/include/spine/IkConstraintPose.h index 6b3483903..72e0b88e8 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintPose.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintPose.h @@ -40,6 +40,7 @@ namespace spine { friend class IkConstraint; friend class IkConstraintTimeline; friend class SkeletonJson; + friend class SkeletonBinary; public: IkConstraintPose(); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPose.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPose.h index 340bdb6b9..9b1bd6cc3 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPose.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPose.h @@ -41,6 +41,7 @@ namespace spine { friend class PathConstraintSpacingTimeline; friend class PathConstraintMixTimeline; friend class SkeletonJson; + friend class SkeletonBinary; private: float _position; diff --git a/spine-cpp/spine-cpp/include/spine/PhysicsConstraintPose.h b/spine-cpp/spine-cpp/include/spine/PhysicsConstraintPose.h index 5887fa8f2..ffed19d46 100644 --- a/spine-cpp/spine-cpp/include/spine/PhysicsConstraintPose.h +++ b/spine-cpp/spine-cpp/include/spine/PhysicsConstraintPose.h @@ -39,6 +39,7 @@ namespace spine { friend class PhysicsConstraint; friend class PhysicsConstraintTimeline; friend class SkeletonJson; + friend class SkeletonBinary; private: float _inertia; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h index cd74070f0..60189a0cc 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -75,7 +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 BONE_INHERIT = 10; static const int SLOT_ATTACHMENT = 0; static const int SLOT_RGBA = 1; @@ -84,6 +84,12 @@ namespace spine { static const int SLOT_RGB2 = 4; static const int SLOT_ALPHA = 5; + static const int CONSTRAINT_IK = 0; + static const int CONSTRAINT_PATH = 1; + static const int CONSTRAINT_TRANSFORM = 2; + static const int CONSTRAINT_PHYSICS = 3; + static const int CONSTRAINT_SLIDER = 4; + static const int ATTACHMENT_DEFORM = 0; static const int ATTACHMENT_SEQUENCE = 1; @@ -91,20 +97,23 @@ 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 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 SLIDER_TIME = 0; + static const int SLIDER_MIX = 1; static const int CURVE_LINEAR = 0; static const int CURVE_STEPPED = 1; static const int CURVE_BEZIER = 2; - explicit SkeletonBinary(Atlas *atlasArray); + explicit SkeletonBinary(Atlas *atlas); explicit SkeletonBinary(AttachmentLoader *attachmentLoader, bool ownsLoader = false); @@ -122,6 +131,95 @@ namespace spine { struct DataInput : public SpineObject { const unsigned char *cursor; const unsigned char *end; + SkeletonData *skeletonData; + + DataInput(SkeletonData *skeletonData, const unsigned char *data, size_t length) : cursor(data), end(data + length), skeletonData(skeletonData) {} + + inline int read() { + return readByte(); + } + + inline signed char readByte() { + return (signed char)*cursor++; + } + + inline unsigned char readUnsignedByte() { + return (unsigned char)*cursor++; + } + + inline bool readBoolean() { + return readByte() != 0; + } + + inline int readInt() { + int result = readUnsignedByte(); + result <<= 8; + result |= readUnsignedByte(); + result <<= 8; + result |= readUnsignedByte(); + result <<= 8; + result |= readUnsignedByte(); + return result; + } + + inline long long readLong() { + long long result = (unsigned long long)readInt(); + result <<= 32; + result |= (unsigned long long)readInt(); + return result; + } + + inline float readFloat() { + union { + int intValue; + float floatValue; + } intToFloat; + intToFloat.intValue = readInt(); + return intToFloat.floatValue; + } + + inline void readColor(Color &color) { + color.r = readUnsignedByte() / 255.0f; + color.g = readUnsignedByte() / 255.0f; + color.b = readUnsignedByte() / 255.0f; + color.a = readUnsignedByte() / 255.0f; + } + + inline int readInt(bool optimizePositive) { + unsigned char b = readUnsignedByte(); + int value = b & 0x7F; + if (b & 0x80) { + b = readUnsignedByte(); + value |= (b & 0x7F) << 7; + if (b & 0x80) { + b = readUnsignedByte(); + value |= (b & 0x7F) << 14; + if (b & 0x80) { + b = readUnsignedByte(); + value |= (b & 0x7F) << 21; + if (b & 0x80) value |= (readUnsignedByte() & 0x7F) << 28; + } + } + } + if (!optimizePositive) value = (((unsigned int) value >> 1) ^ -(value & 1)); + return value; + } + + char *readString() { + int length = readInt(true); + char *string; + if (length == 0) return NULL; + string = SpineExtension::alloc(length, __FILE__, __LINE__); + memcpy(string, cursor, length - 1); + cursor += length - 1; + string[length - 1] = '\0'; + return string; + } + + char *readStringRef() { + int index = readInt(true); + return index == 0 ? NULL : skeletonData->_strings[index - 1]; + } }; AttachmentLoader *_attachmentLoader; @@ -132,47 +230,29 @@ namespace spine { void setError(const char *value1, const char *value2); - char *readString(DataInput *input); + Skin *readSkin(DataInput &input, SkeletonData *skeletonData, bool defaultSkin, bool nonessential); - char *readStringRef(DataInput *input, SkeletonData *skeletonData); + Sequence *readSequence(DataInput &input); - float readFloat(DataInput *input); - - unsigned char readByte(DataInput *input); - - signed char readSByte(DataInput *input); - - bool readBoolean(DataInput *input); - - int readInt(DataInput *input); - - void readColor(DataInput *input, Color &color); - - int readVarint(DataInput *input, bool optimizePositive); - - Skin *readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential); - - Sequence *readSequence(DataInput *input); - - Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, + Attachment *readAttachment(DataInput &input, Skin *skin, int slotIndex, const String &attachmentName, SkeletonData *skeletonData, bool nonessential); - int readVertices(DataInput *input, Vector &vertices, Vector &bones, bool weighted); + int readVertices(DataInput &input, Vector &vertices, Vector &bones, bool weighted); - void readFloatArray(DataInput *input, int n, float scale, Vector &array); + void readFloatArray(DataInput &input, int n, float scale, Vector &array); - void readShortArray(DataInput *input, Vector &array, int n); + void readShortArray(DataInput &input, Vector &array, int n); - Animation *readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData); + Animation *readAnimation(DataInput &input, const String &name, SkeletonData *skeletonData); void - setBezier(DataInput *input, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, + setBezier(DataInput &input, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, float value1, float value2, float scale); - void readTimeline(DataInput *input, Vector &timelines, CurveTimeline1 *timeline, float scale); + void readTimeline(DataInput &input, Vector &timelines, CurveTimeline1 *timeline, float scale); - void readTimeline2(DataInput *input, Vector &timelines, CurveTimeline2 *timeline, float scale); + void readTimeline2(DataInput &input, Vector &timelines, CurveTimeline2 *timeline, float scale); }; -} +}// namespace spine #endif /* Spine_SkeletonBinary_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SliderPose.h b/spine-cpp/spine-cpp/include/spine/SliderPose.h index 04798574e..cd6e9e5d6 100644 --- a/spine-cpp/spine-cpp/include/spine/SliderPose.h +++ b/spine-cpp/spine-cpp/include/spine/SliderPose.h @@ -42,6 +42,8 @@ namespace spine { friend class SliderMixTimeline; friend class SliderTimeline; friend class SkeletonJson; + friend class SkeletonBinary; + private: float _time, _mix; diff --git a/spine-cpp/spine-cpp/include/spine/SlotPose.h b/spine-cpp/spine-cpp/include/spine/SlotPose.h index e8cdb3f61..520d7fe89 100644 --- a/spine-cpp/spine-cpp/include/spine/SlotPose.h +++ b/spine-cpp/spine-cpp/include/spine/SlotPose.h @@ -51,6 +51,7 @@ namespace spine { friend class RGB2Timeline; friend class PathConstraint; friend class SkeletonJson; + friend class SkeletonBinary; friend class AnimationState; protected: diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index 9fae5db23..32ae9b7c3 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -43,13 +43,14 @@ namespace spine { /// Source property for a TransformConstraint. class SP_API FromProperty : public SpineObject { + friend class SkeletonBinary; public: /// The value of this property that corresponds to ToProperty offset. - float offset; + float _offset; /// Constrained properties. - Vector to; + Vector _to; FromProperty(); virtual ~FromProperty(); @@ -60,16 +61,17 @@ namespace spine { /// Constrained property for a TransformConstraint. class SP_API ToProperty : public SpineObject { + friend class SkeletonBinary; public: /// The value of this property that corresponds to FromProperty offset. - float offset; + float _offset; /// The maximum value of this property when clamped. - float max; + float _max; /// The scale of the FromProperty value in relation to this property. - float scale; + float _scale; ToProperty(); virtual ~ToProperty(); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintPose.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintPose.h index f498d0345..ff4fff7c5 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintPose.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintPose.h @@ -53,6 +53,7 @@ namespace spine { friend class TransformConstraint; friend class TransformConstraintTimeline; friend class SkeletonJson; + friend class SkeletonBinary; private: float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY; diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index a6d11c86c..e1aa3429f 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -75,7 +75,7 @@ namespace spine { return _size; } - inline void setSize(size_t newSize, const T &defaultValue) { + inline Vector &setSize(size_t newSize, const T &defaultValue) { assert(newSize >= 0); size_t oldSize = _size; _size = newSize; @@ -97,6 +97,7 @@ namespace spine { destroy(_buffer + i); } } + return *this; } inline void ensureCapacity(size_t newCapacity = 0) { diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index e4e5f2933..c8f061edc 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -72,13 +72,16 @@ #include #include #include +#include +#include +#include #include using namespace spine; -SkeletonBinary::SkeletonBinary(Atlas *atlasArray) : _attachmentLoader( - new (__FILE__, __LINE__) AtlasAttachmentLoader(atlasArray)), - _error(), _scale(1), _ownsLoader(true) { +SkeletonBinary::SkeletonBinary(Atlas *atlas) : _attachmentLoader( + new(__FILE__, __LINE__) AtlasAttachmentLoader(atlas)), + _error(), _scale(1), _ownsLoader(true) { } SkeletonBinary::SkeletonBinary(AttachmentLoader *attachmentLoader, bool ownsLoader) : _attachmentLoader( @@ -96,319 +99,434 @@ SkeletonBinary::~SkeletonBinary() { if (_ownsLoader) delete _attachmentLoader; } -SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, const int length) { - bool nonessential; - SkeletonData *skeletonData; - - DataInput *input = new (__FILE__, __LINE__) DataInput(); - input->cursor = binary; - input->end = binary + length; - - _linkedMeshes.clear(); - - skeletonData = new (__FILE__, __LINE__) SkeletonData(); - - char buffer[16] = {0}; - int lowHash = readInt(input); - int hightHash = readInt(input); - String hashString; - snprintf(buffer, 16, "%x", hightHash); - hashString.append(buffer); - snprintf(buffer, 16, "%x", lowHash); - hashString.append(buffer); - skeletonData->_hash = hashString; - - char *skeletonDataVersion = readString(input); - skeletonData->_version.own(skeletonDataVersion); - - if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) { - char errorMsg[255]; - snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->_version.buffer(), SPINE_VERSION_STRING); - setError(errorMsg, ""); - delete input; - delete skeletonData; - return NULL; - } - - skeletonData->_x = readFloat(input); - skeletonData->_y = readFloat(input); - skeletonData->_width = readFloat(input); - skeletonData->_height = readFloat(input); - skeletonData->_referenceScale = readFloat(input) * this->_scale; - - nonessential = readBoolean(input); - - if (nonessential) { - skeletonData->_fps = readFloat(input); - skeletonData->_imagesPath.own(readString(input)); - skeletonData->_audioPath.own(readString(input)); - } - - int numStrings = readVarint(input, true); - for (int i = 0; i < numStrings; i++) - skeletonData->_strings.add(readString(input)); - - /* Bones. */ - int numBones = readVarint(input, true); - skeletonData->_bones.setSize(numBones, 0); - for (int i = 0; i < numBones; ++i) { - const char *name = readString(input); - BoneData *parent = i == 0 ? 0 : skeletonData->_bones[readVarint(input, true)]; - BoneData *data = new (__FILE__, __LINE__) BoneData(i, String(name, true), parent); - data->_rotation = readFloat(input); - data->_x = readFloat(input) * _scale; - data->_y = readFloat(input) * _scale; - data->_scaleX = readFloat(input); - data->_scaleY = readFloat(input); - data->_shearX = readFloat(input); - data->_shearY = readFloat(input); - data->_length = readFloat(input) * _scale; - data->_inherit = static_cast(readVarint(input, true)); - data->_skinRequired = readBoolean(input); - if (nonessential) { - readColor(input, data->getColor()); - data->_icon.own(readString(input)); - data->_visible = readBoolean(input); - } - skeletonData->_bones[i] = data; - } - - /* Slots. */ - int slotsCount = readVarint(input, true); - skeletonData->_slots.setSize(slotsCount, 0); - for (int i = 0; i < slotsCount; ++i) { - String slotName = String(readString(input), true); - BoneData *boneData = skeletonData->_bones[readVarint(input, true)]; - SlotData *slotData = new (__FILE__, __LINE__) SlotData(i, slotName, *boneData); - - readColor(input, slotData->getColor()); - unsigned char a = readByte(input); - unsigned char r = readByte(input); - unsigned char g = readByte(input); - unsigned char b = readByte(input); - if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) { - slotData->getDarkColor().set(r / 255.0f, g / 255.0f, b / 255.0f, 1); - slotData->setHasDarkColor(true); - } - slotData->_attachmentName = readStringRef(input, skeletonData); - slotData->_blendMode = static_cast(readVarint(input, true)); - if (nonessential) { - slotData->_visible = readBoolean(input); - } - skeletonData->_slots[i] = slotData; - } - - /* IK constraints. */ - int ikConstraintsCount = readVarint(input, true); - skeletonData->_ikConstraints.setSize(ikConstraintsCount, 0); - for (int i = 0; i < ikConstraintsCount; ++i) { - const char *name = readString(input); - IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData(String(name, true)); - data->setOrder(readVarint(input, true)); - 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)]; - 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; - } - - /* Transform constraints. */ - int transformConstraintsCount = readVarint(input, true); - skeletonData->_transformConstraints.setSize(transformConstraintsCount, 0); - for (int i = 0; i < transformConstraintsCount; ++i) { - const char *name = readString(input); - TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData(String(name, true)); - data->setOrder(readVarint(input, true)); - 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)]; - 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 */ - int pathConstraintsCount = readVarint(input, true); - skeletonData->_pathConstraints.setSize(pathConstraintsCount, 0); - for (int i = 0; i < pathConstraintsCount; ++i) { - const char *name = readString(input); - PathConstraintData *data = new (__FILE__, __LINE__) PathConstraintData(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->_slots[readVarint(input, true)]; - 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); - if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) - data->_spacing *= _scale; - data->_mixRotate = readFloat(input); - data->_mixX = readFloat(input); - data->_mixY = readFloat(input); - 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) { - skeletonData->_defaultSkin = defaultSkin; - skeletonData->_skins.add(defaultSkin); - } - - if (!this->getError().isEmpty()) { - delete input; - delete skeletonData; - return NULL; - } - - /* Skins. */ - for (size_t i = 0, n = (size_t) readVarint(input, true); i < n; ++i) { - Skin *skin = readSkin(input, false, skeletonData, nonessential); - if (skin) - skeletonData->_skins.add(skin); - else { - delete input; - delete skeletonData; - return NULL; - } - } - - /* Linked meshes. */ - for (int i = 0, n = (int) _linkedMeshes.size(); i < n; ++i) { - LinkedMesh *linkedMesh = _linkedMeshes[i]; - Skin *skin = skeletonData->_skins[linkedMesh->_skinIndex]; - Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); - if (parent == NULL) { - delete input; - delete skeletonData; - setError("Parent mesh not found: ", linkedMesh->_parent.buffer()); - return NULL; - } - linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimelines ? static_cast(parent) - : linkedMesh->_mesh; - linkedMesh->_mesh->setParentMesh(static_cast(parent)); - if (linkedMesh->_mesh->_region) linkedMesh->_mesh->updateRegion(); - _attachmentLoader->configureAttachment(linkedMesh->_mesh); - } - ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); - _linkedMeshes.clear(); - - /* Events. */ - int eventsCount = readVarint(input, true); - skeletonData->_events.setSize(eventsCount, 0); - for (int i = 0; i < eventsCount; ++i) { - 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)); - eventData->_audioPath.own(readString(input)); - if (!eventData->_audioPath.isEmpty()) { - eventData->_volume = readFloat(input); - eventData->_balance = readFloat(input); - } - skeletonData->_events[i] = eventData; - } - - /* Animations. */ - int animationsCount = readVarint(input, true); - skeletonData->_animations.setSize(animationsCount, 0); - for (int i = 0; i < animationsCount; ++i) { - String name(readString(input), true); - Animation *animation = readAnimation(name, input, skeletonData); - if (!animation) { - delete input; - delete skeletonData; - return NULL; - } - skeletonData->_animations[i] = animation; - } - - delete input; - return skeletonData; -} - SkeletonData *SkeletonBinary::readSkeletonDataFile(const String &path) { int length; - SkeletonData *skeletonData; const char *binary = SpineExtension::readFile(path.buffer(), &length); if (length == 0 || !binary) { setError("Unable to read skeleton file: ", path.buffer()); return NULL; } - skeletonData = readSkeletonData((unsigned char *) binary, length); + + SkeletonData *skeletonData = readSkeletonData((unsigned char *) binary, length); SpineExtension::free(binary, __FILE__, __LINE__); + + if (skeletonData) { + // Extract filename without extension + const char *lastSlash = strrchr(path.buffer(), '/'); + const char *lastBackslash = strrchr(path.buffer(), '\\'); + const char *filename = path.buffer(); + if (lastSlash) filename = lastSlash + 1; + if (lastBackslash && lastBackslash > filename) filename = lastBackslash + 1; + + String nameWithoutExtension(filename); + const char *lastDot = strrchr(nameWithoutExtension.buffer(), '.'); + if (lastDot) { + int length = lastDot - nameWithoutExtension.buffer(); + nameWithoutExtension = String(nameWithoutExtension.buffer(), length); + } + skeletonData->_name = nameWithoutExtension; + } + + return skeletonData; +} + +SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, const int length) { + if (binary == NULL || length == 0) { + setError("Unable to read skeleton file: ", ""); + return NULL; + } + + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + SkeletonData *skeletonData = new (__FILE__, __LINE__) SkeletonData(); + DataInput input(skeletonData, binary, length); + String version; + {// try block in Java + long long hash = input.readLong(); + if (hash == 0) { + skeletonData->_hash = ""; + } else { + char buffer[32]; + snprintf(buffer, 32, "%llx", hash); + skeletonData->_hash = String(buffer); + } + skeletonData->_version.own(input.readString()); + if (skeletonData->_version.isEmpty()) skeletonData->_version = ""; + version = skeletonData->_version; + if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) { + String errorMsg = "Skeleton version "; + errorMsg.append(skeletonData->_version); + errorMsg.append(" does not match runtime version "); + errorMsg.append(SPINE_VERSION_STRING); + setError(errorMsg.buffer(), ""); + delete skeletonData; + return NULL; + } + skeletonData->_x = input.readFloat(); + skeletonData->_y = input.readFloat(); + skeletonData->_width = input.readFloat(); + skeletonData->_height = input.readFloat(); + skeletonData->_referenceScale = input.readFloat() * this->_scale; + + bool nonessential = input.readBoolean(); + if (nonessential) { + skeletonData->_fps = input.readFloat(); + skeletonData->_imagesPath.own(input.readString()); + skeletonData->_audioPath.own(input.readString()); + } + + int n = input.readInt(true); + Vector &strings = skeletonData->_strings.setSize(n, NULL); + for (int i = 0; i < n; i++) + strings[i] = input.readString(); + + /* Bones. */ + Vector &bones = skeletonData->_bones.setSize(input.readInt(true), NULL); + for (int i = 0; i < bones.size(); ++i) { + const char *name = input.readString(); + BoneData *parent = i == 0 ? 0 : bones[input.readInt(true)]; + BoneData *data = new (__FILE__, __LINE__) BoneData(i, String(name, true), parent); + BoneLocal &setup = data->_setup; + setup._rotation = input.readFloat(); + setup._x = input.readFloat() * _scale; + setup._y = input.readFloat() * _scale; + setup._scaleX = input.readFloat(); + setup._scaleY = input.readFloat(); + setup._shearX = input.readFloat(); + setup._shearY = input.readFloat(); + setup._inherit = static_cast(input.readByte()); + data->_length = input.readFloat() * _scale; + data->_skinRequired = input.readBoolean(); + if (nonessential) { + Color::rgba8888ToColor(data->getColor(), input.readInt()); + data->_icon.own(input.readString()); + data->_visible = input.readBoolean(); + } + bones[i] = data; + } + + /* Slots. */ + Vector &slots = skeletonData->_slots.setSize(input.readInt(true), NULL); + for (int i = 0; i < slots.size(); ++i) { + String slotName = String(input.readString(), true); + BoneData *boneData = bones[input.readInt(true)]; + SlotData *data = new (__FILE__, __LINE__) SlotData(i, slotName, *boneData); + Color::rgba8888ToColor(data->_setup._color, input.readInt()); + + int darkColor = input.readInt(); + if (darkColor != -1) { + Color::rgb888ToColor(data->_setup._darkColor, darkColor); + data->_setup._hasDarkColor = true; + } + + data->_attachmentName = input.readStringRef(); + data->_blendMode = static_cast(input.readInt(true)); + if (nonessential) data->_visible = input.readBoolean(); + slots[i] = data; + } + + /* Constraints. */ + int constraintCount = input.readInt(true); + Vector &constraints = skeletonData->_constraints.setSize(constraintCount, NULL); + for (int i = 0; i < constraintCount; i++) { + String name(input.readString(), true); + int nn; + switch (input.readByte()) { + case CONSTRAINT_IK: { + IkConstraintData *data = new (__FILE__, __LINE__) IkConstraintData(name); + Vector &constraintBones = data->_bones.setSize(nn = input.readInt(true), NULL); + for (int ii = 0; ii < nn; ii++) + constraintBones[ii] = bones[input.readInt(true)]; + data->_target = bones[input.readInt(true)]; + int flags = input.read(); + data->_skinRequired = (flags & 1) != 0; + data->_uniform = (flags & 2) != 0; + IkConstraintPose &setup = data->_setup; + setup._bendDirection = (flags & 4) != 0 ? 1 : -1; + setup._compress = (flags & 8) != 0; + setup._stretch = (flags & 16) != 0; + if ((flags & 32) != 0) setup._mix = (flags & 64) != 0 ? input.readFloat() : 1; + if ((flags & 128) != 0) setup._softness = input.readFloat() * _scale; + constraints[i] = data; + break; + } + case CONSTRAINT_TRANSFORM: { + TransformConstraintData *data = new (__FILE__, __LINE__) TransformConstraintData(name); + Vector &constraintBones = data->_bones.setSize(nn = input.readInt(true), NULL); + for (int ii = 0; ii < nn; ii++) + constraintBones[ii] = bones[input.readInt(true)]; + data->_source = bones[input.readInt(true)]; + int flags = input.read(); + data->_skinRequired = (flags & 1) != 0; + data->_localSource = (flags & 2) != 0; + data->_localTarget = (flags & 4) != 0; + data->_additive = (flags & 8) != 0; + data->_clamp = (flags & 16) != 0; + Vector &froms = data->_properties.setSize(nn = flags >> 5, NULL); + for (int ii = 0, tn; ii < nn; ii++) { + float fromScale = 1; + FromProperty *from = NULL; + switch (input.readByte()) { + case 0: + from = new (__FILE__, __LINE__) FromRotate(); + break; + case 1: + fromScale = _scale; + from = new (__FILE__, __LINE__) FromX(); + break; + case 2: + fromScale = _scale; + from = new (__FILE__, __LINE__) FromY(); + break; + case 3: + from = new (__FILE__, __LINE__) FromScaleX(); + break; + case 4: + from = new (__FILE__, __LINE__) FromScaleY(); + break; + case 5: + from = new (__FILE__, __LINE__) FromShearY(); + break; + } + from->_offset = input.readFloat() * fromScale; + Vector &tos = from->_to.setSize(tn = input.readByte(), NULL); + for (int t = 0; t < tn; t++) { + float toScale = 1; + ToProperty *to = NULL; + switch (input.readByte()) { + case 0: + to = new (__FILE__, __LINE__) ToRotate(); + break; + case 1: + toScale = _scale; + to = new (__FILE__, __LINE__) ToX(); + break; + case 2: + toScale = _scale; + to = new (__FILE__, __LINE__) ToY(); + break; + case 3: + to = new (__FILE__, __LINE__) ToScaleX(); + break; + case 4: + to = new (__FILE__, __LINE__) ToScaleY(); + break; + case 5: + to = new (__FILE__, __LINE__) ToShearY(); + break; + } + to->_offset = input.readFloat() * toScale; + to->_max = input.readFloat() * toScale; + to->_scale = input.readFloat() * toScale / fromScale; + tos[t] = to; + } + froms[ii] = from; + } + flags = input.read(); + if ((flags & 1) != 0) data->_offsets[TransformConstraintData::ROTATION] = input.readFloat(); + if ((flags & 2) != 0) data->_offsets[TransformConstraintData::X] = input.readFloat() * _scale; + if ((flags & 4) != 0) data->_offsets[TransformConstraintData::Y] = input.readFloat() * _scale; + if ((flags & 8) != 0) data->_offsets[TransformConstraintData::SCALEX] = input.readFloat(); + if ((flags & 16) != 0) data->_offsets[TransformConstraintData::SCALEY] = input.readFloat(); + if ((flags & 32) != 0) data->_offsets[TransformConstraintData::SHEARY] = input.readFloat(); + flags = input.read(); + TransformConstraintPose &setup = data->_setup; + if ((flags & 1) != 0) setup._mixRotate = input.readFloat(); + if ((flags & 2) != 0) setup._mixX = input.readFloat(); + if ((flags & 4) != 0) setup._mixY = input.readFloat(); + if ((flags & 8) != 0) setup._mixScaleX = input.readFloat(); + if ((flags & 16) != 0) setup._mixScaleY = input.readFloat(); + if ((flags & 32) != 0) setup._mixShearY = input.readFloat(); + constraints[i] = data; + break; + } + case CONSTRAINT_PATH: { + PathConstraintData *data = new (__FILE__, __LINE__) PathConstraintData(name); + Vector &constraintBones = data->_bones.setSize(nn = input.readInt(true), NULL); + for (int ii = 0; ii < nn; ii++) + constraintBones[ii] = bones[input.readInt(true)]; + data->_slot = slots[input.readInt(true)]; + int flags = input.read(); + data->_skinRequired = (flags & 1) != 0; + data->_positionMode = (PositionMode) ((flags >> 1) & 2); + data->_spacingMode = (SpacingMode) ((flags >> 2) & 3); + data->_rotateMode = (RotateMode) ((flags >> 4) & 3); + if ((flags & 128) != 0) data->_offsetRotation = input.readFloat(); + PathConstraintPose &setup = data->_setup; + setup._position = input.readFloat(); + if (data->_positionMode == PositionMode_Fixed) setup._position *= _scale; + setup._spacing = input.readFloat(); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) setup._spacing *= _scale; + setup._mixRotate = input.readFloat(); + setup._mixX = input.readFloat(); + setup._mixY = input.readFloat(); + constraints[i] = data; + break; + } + case CONSTRAINT_PHYSICS: { + PhysicsConstraintData *data = new (__FILE__, __LINE__) PhysicsConstraintData(name); + data->_bone = bones[input.readInt(true)]; + int flags = input.read(); + data->_skinRequired = (flags & 1) != 0; + if ((flags & 2) != 0) data->_x = input.readFloat(); + if ((flags & 4) != 0) data->_y = input.readFloat(); + if ((flags & 8) != 0) data->_rotate = input.readFloat(); + if ((flags & 16) != 0) data->_scaleX = input.readFloat(); + if ((flags & 32) != 0) data->_shearX = input.readFloat(); + data->_limit = ((flags & 64) != 0 ? input.readFloat() : 5000) * _scale; + data->_step = 1.f / input.readUnsignedByte(); + PhysicsConstraintPose &setup = data->getSetupPose(); + setup._inertia = input.readFloat(); + setup._strength = input.readFloat(); + setup._damping = input.readFloat(); + setup._massInverse = (flags & 128) != 0 ? input.readFloat() : 1; + setup._wind = input.readFloat(); + setup._gravity = input.readFloat(); + flags = input.read(); + 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; + setup._mix = (flags & 128) != 0 ? input.readFloat() : 1; + constraints[i] = data; + break; + } + case CONSTRAINT_SLIDER: { + SliderData *data = new (__FILE__, __LINE__) SliderData(name); + int flags = input.read(); + data->_skinRequired = (flags & 1) != 0; + data->_loop = (flags & 2) != 0; + data->_additive = (flags & 4) != 0; + SliderPose &setup = data->_setup; + if ((flags & 8) != 0) setup._time = input.readFloat(); + if ((flags & 16) != 0) setup._mix = (flags & 32) != 0 ? input.readFloat() : 1; + if ((flags & 64) != 0) { + data->_local = (flags & 128) != 0; + data->_bone = bones[input.readInt(true)]; + float offset = input.readFloat(); + float propertyScale = 1; + switch (input.readByte()) { + case 0: + data->_property = new (__FILE__, __LINE__) FromRotate(); + break; + case 1: + propertyScale = _scale; + data->_property = new (__FILE__, __LINE__) FromX(); + break; + case 2: + propertyScale = _scale; + data->_property = new (__FILE__, __LINE__) FromY(); + break; + case 3: + data->_property = new (__FILE__, __LINE__) FromScaleX(); + break; + case 4: + data->_property = new (__FILE__, __LINE__) FromScaleY(); + break; + case 5: + data->_property = new (__FILE__, __LINE__) FromShearY(); + break; + default: + data->_property = NULL; + break; + } + if(data->_property) data->_property->_offset = offset * propertyScale; + data->_offset = input.readFloat(); + data->_scale = input.readFloat() / propertyScale; + } + constraints[i] = data; + break; + } + } + } + + /* Default skin. */ + Skin *defaultSkin = readSkin(input, skeletonData, true, nonessential); + if (defaultSkin) { + skeletonData->_defaultSkin = defaultSkin; + skeletonData->_skins.add(defaultSkin); + } + + if (!this->getError().isEmpty()) { + delete skeletonData; + return NULL; + } + + /* Skins. */ + { + int i = skeletonData->_skins.size(); + Vector &skins = skeletonData->_skins.setSize(n = i + input.readInt(true), NULL); + for (; i < n; i++) { + Skin *skin = readSkin(input, skeletonData, false, nonessential); + if (skin) + skins[i] = skin; + else { + delete skeletonData; + return NULL; + } + } + } + + /* Linked meshes. */ + Vector &items = _linkedMeshes; + for (int i = 0, n = items.size(); i < n; i++) { + LinkedMesh *linkedMesh = items[i]; + Skin *skin = skeletonData->_skins[linkedMesh->_skinIndex]; + Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) { + delete skeletonData; + setError("Parent mesh not found: ", linkedMesh->_parent.buffer()); + return NULL; + } + linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimelines ? static_cast(parent) + : linkedMesh->_mesh; + linkedMesh->_mesh->setParentMesh(static_cast(parent)); + if (linkedMesh->_mesh->getSequence() == NULL) linkedMesh->_mesh->updateRegion(); + _attachmentLoader->configureAttachment(linkedMesh->_mesh); + } + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + _linkedMeshes.clear(); + + /* Events. */ + int eventsCount = input.readInt(true); + Vector &events = skeletonData->_events.setSize(eventsCount, NULL); + for (int i = 0; i < eventsCount; ++i) { + EventData *eventData = new (__FILE__, __LINE__) EventData(String(input.readString(), true)); + eventData->_intValue = input.readInt(false); + eventData->_floatValue = input.readFloat(); + eventData->_stringValue.own(input.readString()); + eventData->_audioPath.own(input.readString()); + if (!eventData->_audioPath.isEmpty()) { + eventData->_volume = input.readFloat(); + eventData->_balance = input.readFloat(); + } + events[i] = eventData; + } + + /* Animations. */ + int animationsCount = input.readInt(true); + Vector &animations = skeletonData->_animations.setSize(animationsCount, NULL); + for (int i = 0; i < animationsCount; ++i) { + Animation *animation = readAnimation(input, String(input.readString(), true), skeletonData); + if (!animation) { + delete skeletonData; + return NULL; + } + skeletonData->_animations[i] = animation; + } + + for (int i = 0; i < constraintCount; i++) { + if (constraints[i]->getRTTI().instanceOf(SliderData::rtti)) { + SliderData *data = static_cast(constraints[i]); + data->setAnimation(animations[input.readInt(true)]); + } + } + } + return skeletonData; } @@ -421,82 +539,7 @@ void SkeletonBinary::setError(const char *value1, const char *value2) { _error = String(message); } -char *SkeletonBinary::readString(DataInput *input) { - int length = readVarint(input, true); - char *string; - if (length == 0) return NULL; - string = SpineExtension::alloc(length, __FILE__, __LINE__); - memcpy(string, input->cursor, length - 1); - input->cursor += length - 1; - string[length - 1] = '\0'; - return string; -} - -char *SkeletonBinary::readStringRef(DataInput *input, SkeletonData *skeletonData) { - int index = readVarint(input, true); - return index == 0 ? NULL : skeletonData->_strings[index - 1]; -} - -float SkeletonBinary::readFloat(DataInput *input) { - union { - int intValue; - float floatValue; - } intToFloat; - intToFloat.intValue = readInt(input); - return intToFloat.floatValue; -} - -unsigned char SkeletonBinary::readByte(DataInput *input) { - return *input->cursor++; -} - -signed char SkeletonBinary::readSByte(DataInput *input) { - return (signed char) readByte(input); -} - -bool SkeletonBinary::readBoolean(DataInput *input) { - return readByte(input) != 0; -} - -int SkeletonBinary::readInt(DataInput *input) { - int result = readByte(input); - result <<= 8; - result |= readByte(input); - result <<= 8; - result |= readByte(input); - result <<= 8; - result |= readByte(input); - return result; -} - -void SkeletonBinary::readColor(DataInput *input, Color &color) { - color.r = readByte(input) / 255.0f; - color.g = readByte(input) / 255.0f; - color.b = readByte(input) / 255.0f; - color.a = readByte(input) / 255.0f; -} - -int SkeletonBinary::readVarint(DataInput *input, bool optimizePositive) { - unsigned char b = readByte(input); - int value = b & 0x7F; - if (b & 0x80) { - b = readByte(input); - value |= (b & 0x7F) << 7; - if (b & 0x80) { - b = readByte(input); - value |= (b & 0x7F) << 14; - if (b & 0x80) { - b = readByte(input); - value |= (b & 0x7F) << 21; - if (b & 0x80) value |= (readByte(input) & 0x7F) << 28; - } - } - } - if (!optimizePositive) value = (((unsigned int) value >> 1) ^ -(value & 1)); - return value; -} - -Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential) { +Skin *SkeletonBinary::readSkin(DataInput *input, SkeletonData *skeletonData, bool defaultSkin, bool nonessential) { Skin *skin; int slotCount = 0; if (defaultSkin) { @@ -854,7 +897,7 @@ void SkeletonBinary::readTimeline2(DataInput *input, Vector &timelin timelines.add(timeline); } -Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData) { +Animation *SkeletonBinary::readAnimation(DataInput *input, const String &name, SkeletonData *skeletonData) { Vector timelines; float scale = _scale; int numTimelines = readVarint(input, true); diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp index 31c71f6bc..5b28b127d 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -147,13 +147,13 @@ Vector &TransformConstraintData::getProperties() { return _properties; } -FromProperty::FromProperty() : SpineObject(), offset(0) { +FromProperty::FromProperty() : SpineObject(), _offset(0) { } FromProperty::~FromProperty() { } -ToProperty::ToProperty() : offset(0), max(0), scale(1) { +ToProperty::ToProperty() : SpineObject(), _offset(0), _max(0), _scale(1) { } ToProperty::~ToProperty() { @@ -326,7 +326,7 @@ TransformConstraintData::~TransformConstraintData() { FromProperty *fromProp = _properties[i]; if (fromProp) { // Clean up the ToProperty objects in the FromProperty - ContainerUtil::cleanUpVectorOfPointers(fromProp->to); + ContainerUtil::cleanUpVectorOfPointers(fromProp->_to); delete fromProp; } }