From 29322c5c51bb1a58615149ddf3750780fc8d3fd3 Mon Sep 17 00:00:00 2001 From: badlogic Date: Thu, 6 Jun 2019 14:13:23 +0200 Subject: [PATCH] [cpp] Ported skin bones/constraints changes. See #1346. --- spine-cpp/spine-cpp/include/spine/Bone.h | 5 + spine-cpp/spine-cpp/include/spine/BoneData.h | 4 + .../spine/{Constraint.h => ConstraintData.h} | 23 +++-- spine-cpp/spine-cpp/include/spine/Debug.h | 1 + .../spine-cpp/include/spine/IkConstraint.h | 9 +- .../include/spine/IkConstraintData.h | 11 +-- spine-cpp/spine-cpp/include/spine/Json.h | 2 + .../spine-cpp/include/spine/PathConstraint.h | 10 +- .../include/spine/PathConstraintData.h | 10 +- .../spine-cpp/include/spine/SkeletonBinary.h | 4 +- .../spine-cpp/include/spine/SkeletonData.h | 1 + spine-cpp/spine-cpp/include/spine/Skin.h | 7 ++ .../include/spine/TransformConstraint.h | 9 +- .../include/spine/TransformConstraintData.h | 7 +- spine-cpp/spine-cpp/include/spine/Updatable.h | 4 + spine-cpp/spine-cpp/include/spine/spine.h | 2 +- .../spine-cpp/src/spine/AnimationState.cpp | 1 + .../src/spine/AttachmentTimeline.cpp | 3 + spine-cpp/spine-cpp/src/spine/Bone.cpp | 11 ++- spine-cpp/spine-cpp/src/spine/BoneData.cpp | 11 ++- .../spine-cpp/src/spine/ColorTimeline.cpp | 2 + .../{Constraint.cpp => ConstraintData.cpp} | 28 +++++- .../spine-cpp/src/spine/DeformTimeline.cpp | 2 + .../spine-cpp/src/spine/IkConstraint.cpp | 16 +++- .../spine-cpp/src/spine/IkConstraintData.cpp | 15 +-- .../src/spine/IkConstraintTimeline.cpp | 2 + spine-cpp/spine-cpp/src/spine/Json.cpp | 12 +++ .../spine-cpp/src/spine/PathConstraint.cpp | 15 ++- .../src/spine/PathConstraintData.cpp | 16 +--- .../src/spine/PathConstraintMixTimeline.cpp | 2 + .../spine/PathConstraintPositionTimeline.cpp | 2 + .../spine/PathConstraintSpacingTimeline.cpp | 2 + .../spine-cpp/src/spine/RegionAttachment.cpp | 2 +- .../spine-cpp/src/spine/RotateTimeline.cpp | 1 + .../spine-cpp/src/spine/ScaleTimeline.cpp | 2 + .../spine-cpp/src/spine/ShearTimeline.cpp | 1 + spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 31 ++++++- .../spine-cpp/src/spine/SkeletonBinary.cpp | 85 ++++++++++------- .../spine-cpp/src/spine/SkeletonData.cpp | 3 + .../spine-cpp/src/spine/SkeletonJson.cpp | 93 +++++++++++++++---- spine-cpp/spine-cpp/src/spine/Skin.cpp | 21 +++++ .../src/spine/TransformConstraint.cpp | 16 +++- .../src/spine/TransformConstraintData.cpp | 12 +-- .../src/spine/TransformConstraintTimeline.cpp | 1 + .../spine-cpp/src/spine/TranslateTimeline.cpp | 1 + .../spine-cpp/src/spine/TwoColorTimeline.cpp | 2 + spine-sfml/c/src/spine/spine-sfml.cpp | 2 +- spine-sfml/cpp/example/main.cpp | 4 +- spine-sfml/cpp/src/spine/spine-sfml.cpp | 4 +- 49 files changed, 379 insertions(+), 151 deletions(-) rename spine-cpp/spine-cpp/include/spine/{Constraint.h => ConstraintData.h} (80%) rename spine-cpp/spine-cpp/src/spine/{Constraint.cpp => ConstraintData.cpp} (78%) diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index f0026d233..869a49e78 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -223,6 +223,10 @@ public: bool isAppliedValid(); void setAppliedValid(bool valid); + bool isActive(); + + void setActive(bool inValue); + private: static bool yDown; @@ -236,6 +240,7 @@ private: float _a, _b, _worldX; float _c, _d, _worldY; bool _sorted; + bool _active; /// Computes the individual applied transform values from the world transform. This can be useful to perform processing using /// the applied transform after the world transform has been modified directly (eg, by a constraint).. diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 226ecf1bc..b800cec3f 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -106,6 +106,9 @@ public: void setTransformMode(TransformMode inValue); + bool isSkinRequired(); + void setSkinRequired(bool inValue); + private: const int _index; const String _name; @@ -113,6 +116,7 @@ private: float _length; float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; TransformMode _transformMode; + bool _skinRequired; }; } diff --git a/spine-cpp/spine-cpp/include/spine/Constraint.h b/spine-cpp/spine-cpp/include/spine/ConstraintData.h similarity index 80% rename from spine-cpp/spine-cpp/include/spine/Constraint.h rename to spine-cpp/spine-cpp/include/spine/ConstraintData.h index 29b06f644..6ceda85ee 100644 --- a/spine-cpp/spine-cpp/include/spine/Constraint.h +++ b/spine-cpp/spine-cpp/include/spine/ConstraintData.h @@ -31,21 +31,32 @@ #define Spine_Constraint_h #include +#include namespace spine { /// The interface for all constraints. -class SP_API Constraint : public Updatable { -RTTI_DECL +class SP_API ConstraintData : public SpineObject { public: - Constraint(); + ConstraintData(const String& name); - virtual ~Constraint(); + virtual ~ConstraintData(); - virtual void update() = 0; + /// The IK constraint's name, which is unique within the skeleton. + const String& getName(); /// The ordinal for the order a skeleton's constraints will be applied. - virtual int getOrder() = 0; + size_t getOrder(); + void setOrder(size_t inValue); + + /// Whether the constraint is only active for a specific skin. + bool isSkinRequired(); + void setSkinRequired(bool inValue); + +private: + const String _name; + size_t _order; + bool _skinRequired; }; } diff --git a/spine-cpp/spine-cpp/include/spine/Debug.h b/spine-cpp/spine-cpp/include/spine/Debug.h index 13c3213ec..90e221b26 100644 --- a/spine-cpp/spine-cpp/include/spine/Debug.h +++ b/spine-cpp/spine-cpp/include/spine/Debug.h @@ -55,6 +55,7 @@ public: void reportLeaks() { for (std::map::iterator it = _allocated.begin(); it != _allocated.end(); it++) { + void* addr = it->second.address; printf("\"%s:%i (%zu bytes at %p)\n", it->second.fileName, it->second.line, it->second.size, it->second.address); } printf("allocations: %zu, reallocations: %zu, frees: %zu\n", _allocations, _reallocations, _frees); diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index b872ebe92..84920c49d 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -30,7 +30,7 @@ #ifndef Spine_IkConstraint_h #define Spine_IkConstraint_h -#include +#include #include @@ -41,7 +41,7 @@ class Skeleton; class Bone; -class SP_API IkConstraint : public Constraint { +class SP_API IkConstraint : public Updatable { friend class Skeleton; friend class IkConstraintTimeline; @@ -91,6 +91,10 @@ public: void setMix(float inValue); + bool isActive(); + + void setActive(bool inValue); + private: IkConstraintData &_data; Vector _bones; @@ -99,6 +103,7 @@ private: bool _stretch; float _mix; Bone *_target; + bool _active; }; } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index 5079f21ef..05c203c04 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -33,11 +33,12 @@ #include #include #include +#include namespace spine { class BoneData; - class SP_API IkConstraintData : public SpineObject { + class SP_API IkConstraintData : public ConstraintData { friend class SkeletonBinary; friend class SkeletonJson; friend class IkConstraint; @@ -47,12 +48,6 @@ namespace spine { public: explicit IkConstraintData(const String& name); - /// The IK constraint's name, which is unique within the skeleton. - const String& getName(); - - size_t getOrder(); - void setOrder(size_t inValue); - /// The bones that are constrained by this IK Constraint. Vector& getBones(); @@ -77,8 +72,6 @@ namespace spine { void setMix(float inValue); private: - const String _name; - size_t _order; Vector _bones; BoneData* _target; int _bendDirection; diff --git a/spine-cpp/spine-cpp/include/spine/Json.h b/spine-cpp/spine-cpp/include/spine/Json.h index 97804da7a..b62fee215 100644 --- a/spine-cpp/spine-cpp/include/spine/Json.h +++ b/spine-cpp/spine-cpp/include/spine/Json.h @@ -60,6 +60,8 @@ public: static int getInt(Json *object, const char *name, int defaultValue); + static bool getBoolean(Json *object, const char *name, bool defaultValue); + /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */ static const char *getError(); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h index e5ec1d297..a791c5942 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -30,7 +30,7 @@ #ifndef Spine_PathConstraint_h #define Spine_PathConstraint_h -#include +#include #include @@ -41,7 +41,7 @@ namespace spine { class Bone; class Slot; - class SP_API PathConstraint : public Constraint { + class SP_API PathConstraint : public Updatable { friend class Skeleton; friend class PathConstraintMixTimeline; friend class PathConstraintPositionTimeline; @@ -77,6 +77,10 @@ namespace spine { void setTarget(Slot* inValue); PathConstraintData& getData(); + + bool isActive(); + + void setActive(bool inValue); private: static const float EPSILON; @@ -95,6 +99,8 @@ namespace spine { Vector _curves; Vector _lengths; Vector _segments; + + bool _active; Vector& computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index 0fa4bcf8f..0d26c24df 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -36,12 +36,13 @@ #include #include #include +#include namespace spine { class BoneData; class SlotData; - class SP_API PathConstraintData : public SpineObject { + class SP_API PathConstraintData : public ConstraintData { friend class SkeletonBinary; friend class SkeletonJson; @@ -53,11 +54,6 @@ namespace spine { public: explicit PathConstraintData(const String& name); - - const String& getName(); - - int getOrder(); - void setOrder(int inValue); Vector& getBones(); @@ -89,8 +85,6 @@ namespace spine { void setTranslateMix(float inValue); private: - const String _name; - int _order; Vector _bones; SlotData* _target; PositionMode _positionMode; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h index 5766960f4..53f92c432 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -95,6 +95,8 @@ namespace spine { void setError(const char* value1, const char* value2); char* readString(DataInput* input); + + char* readStringRef(DataInput* input, SkeletonData* skeletonData); float readFloat(DataInput* input); @@ -110,7 +112,7 @@ namespace spine { int readVarint(DataInput* input, bool optimizePositive); - Skin* readSkin(DataInput* input, const String& skinName, SkeletonData* skeletonData, bool nonessential); + Skin* readSkin(DataInput* input, bool defaultSkin, SkeletonData* skeletonData, bool nonessential); Attachment* readAttachment(DataInput* input, Skin* skin, int slotIndex, const String& attachmentName, SkeletonData* skeletonData, bool nonessential); diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/spine-cpp/spine-cpp/include/spine/SkeletonData.h index bcaf2b146..b4f626cdd 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonData.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -172,6 +172,7 @@ private: float _x, _y, _width, _height; String _version; String _hash; + Vector _strings; // Nonessential. float _fps; diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h index ce22369f5..de55f6035 100644 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -37,6 +37,8 @@ namespace spine { class Attachment; class Skeleton; +class BoneData; +class ConstraintData; /// Stores attachments by slot index and attachment name. /// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and @@ -142,9 +144,14 @@ public: AttachmentMap::Entries getAttachments(); + Vector& getBones(); + + Vector& getConstraints(); private: const String _name; AttachmentMap _attachments; + Vector _bones; + Vector _constraints; /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. void attachAll(Skeleton &skeleton, Skin &oldSkin); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index e17c4a591..cc39c0e83 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -30,7 +30,7 @@ #ifndef Spine_TransformConstraint_h #define Spine_TransformConstraint_h -#include +#include #include @@ -39,7 +39,7 @@ namespace spine { class Skeleton; class Bone; - class SP_API TransformConstraint : public Constraint { + class SP_API TransformConstraint : public Updatable { friend class Skeleton; friend class TransformConstraintTimeline; @@ -72,12 +72,17 @@ namespace spine { float getShearMix(); void setShearMix(float inValue); + + bool isActive(); + + void setActive(bool inValue); private: TransformConstraintData& _data; Vector _bones; Bone* _target; float _rotateMix, _translateMix, _scaleMix, _shearMix; + bool _active; void applyAbsoluteWorld(); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index 585ca641b..edded866e 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -33,11 +33,12 @@ #include #include #include +#include namespace spine { class BoneData; - class SP_API TransformConstraintData : public SpineObject { + class SP_API TransformConstraintData : public ConstraintData { friend class SkeletonBinary; friend class SkeletonJson; @@ -48,8 +49,6 @@ namespace spine { public: explicit TransformConstraintData(const String& name); - const String& getName(); - int getOrder(); Vector& getBones(); BoneData* getTarget(); float getRotateMix(); @@ -68,8 +67,6 @@ namespace spine { bool isLocal(); private: - const String _name; - int _order; Vector _bones; BoneData* _target; float _rotateMix, _translateMix, _scaleMix, _shearMix; diff --git a/spine-cpp/spine-cpp/include/spine/Updatable.h b/spine-cpp/spine-cpp/include/spine/Updatable.h index 21b5e9b17..12046a252 100644 --- a/spine-cpp/spine-cpp/include/spine/Updatable.h +++ b/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -43,6 +43,10 @@ public: virtual ~Updatable(); virtual void update() = 0; + + virtual bool isActive() = 0; + + virtual void setActive(bool inValue) = 0; }; } diff --git a/spine-cpp/spine-cpp/include/spine/spine.h b/spine-cpp/spine-cpp/include/spine/spine.h index f2ad93a22..528ed3737 100644 --- a/spine-cpp/spine-cpp/include/spine/spine.h +++ b/spine-cpp/spine-cpp/include/spine/spine.h @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 71a2e0773..12dc07b47 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -668,6 +668,7 @@ void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleto } Bone *bone = skeleton._bones[rotateTimeline->_boneIndex]; + if (!bone->isActive()) return; Vector& frames = rotateTimeline->_frames; float r1, r2; if (time < frames[0]) { diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp index 78d84cccc..23f27240b 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -67,6 +68,8 @@ void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, V String *attachmentName; Slot *slotP = skeleton._slots[_slotIndex]; Slot &slot = *slotP; + if (!slot._bone.isActive()) return; + if (direction == MixDirection_Out && blend == MixBlend_Setup) { attachmentName = &slot._data._attachmentName; slot.setAttachment(attachmentName->length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName)); diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 8f9118e06..53ffa45e1 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -75,7 +75,8 @@ Bone::Bone(BoneData &data, Skeleton &skeleton, Bone *parent) : Updatable(), _c(0), _d(1), _worldY(0), - _sorted(false) { + _sorted(false), + _active(false) { setToSetupPose(); } @@ -538,3 +539,11 @@ void Bone::updateAppliedTransform() { } } } + +bool Bone::isActive() { + return _active; +} + +void Bone::setActive(bool inValue) { + _active = inValue; +} diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/spine-cpp/spine-cpp/src/spine/BoneData.cpp index d70116c49..621fb2cd4 100644 --- a/spine-cpp/spine-cpp/src/spine/BoneData.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -49,7 +49,8 @@ BoneData::BoneData(int index, const String &name, BoneData *parent) : _scaleY(1), _shearX(0), _shearY(0), - _transformMode(TransformMode_Normal) { + _transformMode(TransformMode_Normal), + _skinRequired(false) { assert(index >= 0); assert(_name.length() > 0); } @@ -137,3 +138,11 @@ TransformMode BoneData::getTransformMode() { void BoneData::setTransformMode(TransformMode inValue) { _transformMode = inValue; } + +bool BoneData::isSkinRequired() { + return _skinRequired; +} + +void BoneData::setSkinRequired(bool inValue) { + _skinRequired = inValue; +} diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp index a764cf560..3ec53251c 100644 --- a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -68,6 +69,7 @@ void ColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector Slot *slotP = skeleton._slots[_slotIndex]; Slot &slot = *slotP; + if (!slot._bone.isActive()) return; if (time < _frames[0]) { switch (blend) { case MixBlend_Setup: diff --git a/spine-cpp/spine-cpp/src/spine/Constraint.cpp b/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp similarity index 78% rename from spine-cpp/spine-cpp/src/spine/Constraint.cpp rename to spine-cpp/spine-cpp/src/spine/ConstraintData.cpp index 8a71331b3..937f5f5b0 100644 --- a/spine-cpp/spine-cpp/src/spine/Constraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp @@ -31,14 +31,32 @@ #include "SpinePluginPrivatePCH.h" #endif -#include +#include using namespace spine; -RTTI_IMPL(Constraint, Updatable) - -Constraint::Constraint() { +ConstraintData::ConstraintData(const String& name): _name(name), _order(0), _skinRequired(false) { } -Constraint::~Constraint() { +ConstraintData::~ConstraintData() { +} + +const String& ConstraintData::getName() { + return _name; +} + +size_t ConstraintData::getOrder() { + return _order; +} + +void ConstraintData::setOrder(size_t inValue) { + _order = inValue; +} + +bool ConstraintData::isSkinRequired() { + return _skinRequired; +} + +void ConstraintData::setSkinRequired(bool inValue) { + _skinRequired = inValue; } diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index 3917af3df..73ebb48e5 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include using namespace spine; @@ -67,6 +68,7 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto Slot *slotP = skeleton._slots[_slotIndex]; Slot &slot = *slotP; + if (!slot._bone.isActive()) return; Attachment *slotAttachment = slot.getAttachment(); if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) { diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index 4e614125d..73fdb5354 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -41,7 +41,7 @@ using namespace spine; -RTTI_IMPL(IkConstraint, Constraint) +RTTI_IMPL(IkConstraint, Updatable) void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) { Bone *p = bone.getParent(); @@ -207,14 +207,15 @@ void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY } } -IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Constraint(), +IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatable(), _data(data), _bendDirection(data.getBendDirection()), _compress(data.getCompress()), _stretch(data.getStretch()), _mix(data.getMix()), _target(skeleton.findBone( - data.getTarget()->getName())) { + data.getTarget()->getName())), + _active(false) { _bones.ensureCapacity(_data.getBones().size()); for (size_t i = 0; i < _data.getBones().size(); i++) { BoneData *boneData = _data.getBones()[i]; @@ -294,3 +295,12 @@ bool IkConstraint::getCompress() { void IkConstraint::setCompress(bool inValue) { _compress = inValue; } + +bool IkConstraint::isActive() { + return _active; +} + +void IkConstraint::setActive(bool inValue) { + _active = inValue; +} + diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index a0f52350f..df95b28bc 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -38,8 +38,7 @@ using namespace spine; IkConstraintData::IkConstraintData(const String &name) : - _name(name), - _order(0), + ConstraintData(name), _target(NULL), _bendDirection(1), _compress(false), @@ -48,18 +47,6 @@ IkConstraintData::IkConstraintData(const String &name) : _mix(1) { } -const String &IkConstraintData::getName() { - return _name; -} - -size_t IkConstraintData::getOrder() { - return _order; -} - -void IkConstraintData::setOrder(size_t inValue) { - _order = inValue; -} - Vector &IkConstraintData::getBones() { return _bones; } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index 80575b17b..a8b14e3b3 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -69,6 +69,8 @@ void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, IkConstraint *constraintP = skeleton._ikConstraints[_ikConstraintIndex]; IkConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + if (time < _frames[0]) { switch (blend) { case MixBlend_Setup: diff --git a/spine-cpp/spine-cpp/src/spine/Json.cpp b/spine-cpp/spine-cpp/src/spine/Json.cpp index 78f84ac5d..b7721e604 100644 --- a/spine-cpp/spine-cpp/src/spine/Json.cpp +++ b/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -90,6 +90,18 @@ int Json::getInt(Json *value, const char *name, int defaultValue) { return value ? value->_valueInt : defaultValue; } +bool Json::getBoolean(spine::Json *value, const char *name, bool defaultValue) { + value = getItem(value, name); + if (value) { + if (value->_valueString) return strcmp(value->_valueString, "true") == 0; + if (value->_type == JSON_NULL) return false; + if (value->_type == JSON_NUMBER) return value->_valueFloat != 0; + return defaultValue; + } else { + return defaultValue; + } +} + const char *Json::getError() { return _error; } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index 7e87b8d64..5aad493a0 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -44,21 +44,22 @@ using namespace spine; -RTTI_IMPL(PathConstraint, Constraint) +RTTI_IMPL(PathConstraint, Updatable) const float PathConstraint::EPSILON = 0.00001f; const int PathConstraint::NONE = -1; const int PathConstraint::BEFORE = -2; const int PathConstraint::AFTER = -3; -PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : Constraint(), +PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : Updatable(), _data(data), _target(skeleton.findSlot( data.getTarget()->getName())), _position(data.getPosition()), _spacing(data.getSpacing()), _rotateMix(data.getRotateMix()), - _translateMix(data.getTranslateMix()) { + _translateMix(data.getTranslateMix()), + _active(false) { _bones.ensureCapacity(_data.getBones().size()); for (size_t i = 0; i < _data.getBones().size(); i++) { BoneData *boneData = _data.getBones()[i]; @@ -568,3 +569,11 @@ void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, fl } } } + +bool PathConstraint::isActive() { + return _active; +} + +void PathConstraint::setActive(bool inValue) { + _active = inValue; +} diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp index 72a9a714c..ea9362748 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -41,8 +41,7 @@ using namespace spine; PathConstraintData::PathConstraintData(const String &name) : - _name(name), - _order(0), + ConstraintData(name), _target(NULL), _positionMode(PositionMode_Fixed), _spacingMode(SpacingMode_Length), @@ -52,19 +51,6 @@ PathConstraintData::PathConstraintData(const String &name) : _spacing(0), _rotateMix(0), _translateMix(0) { - assert(_name.length() > 0); -} - -const String &PathConstraintData::getName() { - return _name; -} - -int PathConstraintData::getOrder() { - return _order; -} - -void PathConstraintData::setOrder(int inValue) { - _order = inValue; } Vector &PathConstraintData::getBones() { diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index fea4015f6..45f47fc8e 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -68,6 +68,8 @@ PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + if (time < _frames[0]) { switch (blend) { case MixBlend_Setup: diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index 75470ef1f..4c5388fc0 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -68,6 +68,8 @@ void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, f PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + if (time < _frames[0]) { switch (blend) { case MixBlend_Setup: diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index a611e1ed5..92da76576 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -59,6 +59,8 @@ void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, fl PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; + if (time < _frames[0]) { switch (blend) { case MixBlend_Setup: diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp index 0ae286bb6..20f5d9952 100644 --- a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -303,4 +303,4 @@ Attachment* RegionAttachment::copy() { copy->_vertexOffset.clearAndAddAll(_vertexOffset); copy->_color.set(_color); return copy; -} \ No newline at end of file +} diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index a06e43e29..8b4af88d1 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -56,6 +56,7 @@ void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto SP_UNUSED(direction); Bone *bone = skeleton.getBones()[_boneIndex]; + if (!bone->_active) return; if (time < _frames[0]) { switch (blend) { diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index 05a7e7181..6431ba748 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -55,6 +55,8 @@ void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector Bone *boneP = skeleton._bones[_boneIndex]; Bone &bone = *boneP; + if (!bone._active) return; + if (time < _frames[0]) { switch (blend) { case MixBlend_Setup: diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index 99e52ebdc..870c16d4b 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -56,6 +56,7 @@ void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector Bone *boneP = skeleton._bones[_boneIndex]; Bone &bone = *boneP; + if (!bone._active) return; if (time < _frames[0]) { switch (blend) { diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index f533449a6..636521275 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -135,7 +135,21 @@ void Skeleton::updateCache() { _updateCacheReset.clear(); for (size_t i = 0, n = _bones.size(); i < n; ++i) { - _bones[i]->_sorted = false; + Bone* bone = _bones[i]; + bone->_sorted = bone->_data.isSkinRequired(); + bone->_active = !bone->_sorted; + } + + if (_skin) { + Vector& skinBones = _skin->getBones(); + for (size_t i = 0, n = skinBones.size(); i < n; i++) { + Bone* bone = _bones[skinBones[i]->getIndex()]; + do { + bone->_sorted = false; + bone->_active = true; + bone = bone->_parent; + } while (bone); + } } size_t ikCount = _ikConstraints.size(); @@ -158,7 +172,7 @@ void Skeleton::updateCache() { for (size_t ii = 0; ii < transformCount; ++ii) { TransformConstraint *constraint = _transformConstraints[ii]; - if (constraint->getData().getOrder() == (int)i) { + if (constraint->getData().getOrder() == i) { sortTransformConstraint(constraint); i++; goto continue_outer; @@ -167,7 +181,7 @@ void Skeleton::updateCache() { for (size_t ii = 0; ii < pathCount; ++ii) { PathConstraint *constraint = _pathConstraints[ii]; - if (constraint->getData().getOrder() == (int)i) { + if (constraint->getData().getOrder() == i) { sortPathConstraint(constraint); i++; goto continue_outer; @@ -407,6 +421,7 @@ void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHe for (size_t i = 0; i < _drawOrder.size(); ++i) { Slot *slot = _drawOrder[i]; + if (!slot->_bone._active) continue; size_t verticesLength = 0; Attachment *attachment = slot->getAttachment(); @@ -536,6 +551,9 @@ void Skeleton::setScaleY(float inValue) { } void Skeleton::sortIkConstraint(IkConstraint *constraint) { + constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() || (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) return; + Bone *target = constraint->getTarget(); sortBone(target); @@ -555,6 +573,9 @@ void Skeleton::sortIkConstraint(IkConstraint *constraint) { } void Skeleton::sortPathConstraint(PathConstraint *constraint) { + constraint->_active = constraint->_target->_bone._active && (!constraint->_data.isSkinRequired() || (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) return; + Slot *slot = constraint->getTarget(); int slotIndex = slot->getData().getIndex(); Bone &slotBone = slot->getBone(); @@ -583,6 +604,9 @@ void Skeleton::sortPathConstraint(PathConstraint *constraint) { } void Skeleton::sortTransformConstraint(TransformConstraint *constraint) { + constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() || (_skin && _skin->_constraints.contains(&constraint->_data))); + if (!constraint->_active) return; + sortBone(constraint->getTarget()); Vector &constrained = constraint->getBones(); @@ -646,6 +670,7 @@ void Skeleton::sortBone(Bone *bone) { void Skeleton::sortReset(Vector &bones) { for (size_t i = 0, n = bones.size(); i < n; ++i) { Bone *bone = bones[i]; + if (!bone->_active) continue; if (bone->_sorted) sortReset(bone->getChildren()); bone->_sorted = false; } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index fcde5bb46..a70ab42d7 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -144,6 +144,10 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons 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); @@ -160,6 +164,7 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons data->_shearY = readFloat(input); data->_length = readFloat(input) * _scale; data->_transformMode = static_cast(readVarint(input, true)); + data->_skinRequired = readBoolean(input); if (nonessential) { /* Skip bone color. */ readInt(input); @@ -184,7 +189,7 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons slotData->getDarkColor().set(r / 255.0f, g / 255.0f, b / 255.0f, 1); slotData->setHasDarkColor(true); } - slotData->_attachmentName.own(readString(input)); + slotData->_attachmentName = readStringRef(input, skeletonData); slotData->_blendMode = static_cast(readVarint(input, true)); skeletonData->_slots[i] = slotData; } @@ -195,7 +200,8 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons for (int i = 0; i < ikConstraintsCount; ++i) { const char *name = readString(input); IkConstraintData *data = new(__FILE__, __LINE__) IkConstraintData(String(name, true)); - data->_order = readVarint(input, 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) { @@ -216,7 +222,8 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons for (int i = 0; i < transformConstraintsCount; ++i) { const char *name = readString(input); TransformConstraintData *data = new(__FILE__, __LINE__) TransformConstraintData(String(name, true)); - data->_order = readVarint(input, 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) { @@ -244,7 +251,8 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons for (int i = 0; i < pathConstraintsCount; ++i) { const char *name = readString(input); PathConstraintData *data = new(__FILE__, __LINE__) PathConstraintData(String(name, true)); - data->_order = readVarint(input, 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) { @@ -266,20 +274,15 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons } /* Default skin. */ - skeletonData->_defaultSkin = readSkin(input, "default", skeletonData, nonessential); - int skinsCount = readVarint(input, true); - if (skeletonData->_defaultSkin) { - ++skinsCount; - } - skeletonData->_skins.setSize(skinsCount, 0); - if (skeletonData->_defaultSkin) { - skeletonData->_skins[0] = skeletonData->_defaultSkin; + Skin* defaultSkin = readSkin(input, true, skeletonData, nonessential); + if (defaultSkin) { + skeletonData->_defaultSkin = defaultSkin; + skeletonData->_skins.add(defaultSkin); } /* Skins. */ - for (size_t i = skeletonData->_defaultSkin ? 1 : 0; i < skeletonData->_skins.size(); ++i) { - String skinName(readString(input), true); - skeletonData->_skins[i] = readSkin(input, skinName, skeletonData, nonessential); + for (size_t i = 0, n = (size_t)readVarint(input, true); i < n; ++i) { + skeletonData->_skins.add(readSkin(input, false, skeletonData, nonessential)); } /* Linked meshes. */ @@ -312,8 +315,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 = readString(input); - EventData *eventData = new(__FILE__, __LINE__) EventData(String(name, true)); + const char *name = readStringRef(input, skeletonData); + EventData *eventData = new(__FILE__, __LINE__) EventData(String(name)); eventData->_intValue = readVarint(input, false); eventData->_floatValue = readFloat(input); eventData->_stringValue.own(readString(input)); @@ -381,6 +384,11 @@ char *SkeletonBinary::readString(DataInput *input) { return string; } +char* SkeletonBinary::readStringRef(DataInput* input, SkeletonData* skeletonData) { + int index = readVarint(input, true); + return index == 0 ? nullptr : skeletonData->_strings[index - 1]; +} + float SkeletonBinary::readFloat(DataInput *input) { union { int intValue; @@ -447,14 +455,27 @@ int SkeletonBinary::readVarint(DataInput *input, bool optimizePositive) { } Skin * -SkeletonBinary::readSkin(DataInput *input, const String &skinName, SkeletonData *skeletonData, bool nonessential) { - int slotCount = readVarint(input, true); - if (slotCount == 0) return NULL; - Skin *skin = new(__FILE__, __LINE__) Skin(skinName); - for (int i = 0; i < slotCount; ++i) { +SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential) { + Skin *skin = new(__FILE__, __LINE__) Skin(defaultSkin ? "default" : readStringRef(input, skeletonData)); + + if (!defaultSkin) { + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getBones().add(skeletonData->_bones[readVarint(input, true)]); + + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getConstraints().add(skeletonData->_ikConstraints[readVarint(input, true)]); + + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getConstraints().add(skeletonData->_transformConstraints[readVarint(input, true)]); + + for (int i = 0, n = readVarint(input, true); i < n; i++) + skin->getConstraints().add(skeletonData->_pathConstraints[readVarint(input, true)]); + } + + for (int i = 0, n = readVarint(input, true); i < n; ++i) { int slotIndex = readVarint(input, true); for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { - String name(readString(input), true); + String name(readStringRef(input, skeletonData)); Attachment *attachment = readAttachment(input, skin, slotIndex, name, skeletonData, nonessential); if (attachment) skin->setAttachment(slotIndex, String(name), attachment); } @@ -464,13 +485,13 @@ SkeletonBinary::readSkin(DataInput *input, const String &skinName, SkeletonData Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, SkeletonData *skeletonData, bool nonessential) { - String name(readString(input), true); + String name(readStringRef(input, skeletonData)); if (name.isEmpty()) name = attachmentName; AttachmentType type = static_cast(readByte(input)); switch (type) { case AttachmentType_Region: { - String path(readString(input), true); + String path(readStringRef(input, skeletonData)); if (path.isEmpty()) path = name; RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path)); region->_path = path; @@ -500,7 +521,7 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo case AttachmentType_Mesh: { int vertexCount; MeshAttachment *mesh; - String path(readString(input), true); + String path(readStringRef(input, skeletonData)); if (path.isEmpty()) path = name; mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path)); @@ -524,14 +545,14 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo return mesh; } case AttachmentType_Linkedmesh: { - String path(readString(input), true); + String path(readStringRef(input, skeletonData)); if (path.isEmpty()) path = name; MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path)); mesh->_path = path; readColor(input, mesh->getColor()); - String skinName(readString(input), true); - String parent(readString(input), true); + String skinName(readStringRef(input, skeletonData)); + String parent(readStringRef(input, skeletonData)); bool inheritDeform = readBoolean(input); if (nonessential) { mesh->_width = readFloat(input) * _scale; @@ -661,7 +682,7 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S timeline->_slotIndex = slotIndex; for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { float time = readFloat(input); - String attachmentName = String(readString(input), true); + String attachmentName(readStringRef(input, skeletonData)); timeline->setFrame(frameIndex, time, attachmentName); } timelines.add(timeline); @@ -888,8 +909,8 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { int slotIndex = readVarint(input, true); for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) { - const char *attachmentName = readString(input); - Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName, true)); + const char *attachmentName = readStringRef(input, skeletonData); + Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName)); if (!baseAttachment) { ContainerUtil::cleanUpVectorOfPointers(timelines); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp index b181d2eab..0daa4c0d4 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -71,6 +71,9 @@ SkeletonData::~SkeletonData() { ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); + for (size_t i = 0; i < _strings.size(); i++) { + SpineExtension::free(_strings[i], __FILE__, __LINE__); + } } BoneData *SkeletonData::findBone(const String &boneName) { diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index d1109bba3..042ab4a0f 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -189,6 +189,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) { if (strcmp(transformMode, "noScaleOrReflection") == 0) { data->_transformMode = TransformMode_NoScaleOrReflection; } + data->_skinRequired = Json::getBoolean(boneMap, "skin", false); skeletonData->_bones[i] = data; bonesCount++; @@ -267,7 +268,8 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) { IkConstraintData *data = new(__FILE__, __LINE__) IkConstraintData( Json::getString(constraintMap, "name", 0)); - data->_order = Json::getInt(constraintMap, "order", 0); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); boneMap = Json::getItem(constraintMap, "bones"); data->_bones.ensureCapacity(boneMap->_size); @@ -311,7 +313,8 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) { TransformConstraintData *data = new(__FILE__, __LINE__) TransformConstraintData( Json::getString(constraintMap, "name", 0)); - data->_order = Json::getInt(constraintMap, "order", 0); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); boneMap = Json::getItem(constraintMap, "bones"); data->_bones.ensureCapacity(boneMap->_size); @@ -364,7 +367,8 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) { PathConstraintData *data = new(__FILE__, __LINE__) PathConstraintData( Json::getString(constraintMap, "name", 0)); - data->_order = Json::getInt(constraintMap, "order", 0); + data->setOrder(Json::getInt(constraintMap, "order", 0)); + data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false)); boneMap = Json::getItem(constraintMap, "bones"); data->_bones.ensureCapacity(boneMap->_size); @@ -438,15 +442,67 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) { Json *attachmentsMap; Json *curves; - Skin *skin = new(__FILE__, __LINE__) Skin(skinMap->_name); + Skin *skin = new(__FILE__, __LINE__) Skin(Json::getString(skinMap, "name", "")); + + Json *item = Json::getItem(skinMap, "bones"); + if (item) { + for (item = item->_child; item; item = item->_next) { + BoneData* data = skeletonData->findBone(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin bone not found: "), item->_valueString); + return NULL; + } + skin->getBones().add(data); + } + } + + item = Json::getItem(skinMap, "ik"); + if (item) { + for (item = item->_child; item; item = item->_next) { + IkConstraintData* data = skeletonData->findIkConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin IK constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "transform"); + if (item) { + for (item = item->_child; item; item = item->_next) { + TransformConstraintData* data = skeletonData->findTransformConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin transform constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } + + item = Json::getItem(skinMap, "path"); + if (item) { + for (item = item->_child; item; item = item->_next) { + PathConstraintData* data = skeletonData->findPathConstraint(item->_valueString); + if (!data) { + delete skeletonData; + setError(root, String("Skin path constraint not found: "), item->_valueString); + return NULL; + } + skin->getConstraints().add(data); + } + } skeletonData->_skins[skinsIndex++] = skin; - if (strcmp(skinMap->_name, "default") == 0) { + if (strcmp(Json::getString(skinMap, "name", ""), "default") == 0) { skeletonData->_defaultSkin = skin; } - for (attachmentsMap = skinMap->_child; attachmentsMap; attachmentsMap = attachmentsMap->_next) { - int slotIndex = skeletonData->findSlotIndex(attachmentsMap->_name); + for (attachmentsMap = Json::getItem(skinMap, "attachments")->_child; attachmentsMap; attachmentsMap = attachmentsMap->_next) { + SlotData* slot = skeletonData->findSlot(attachmentsMap->_name); Json *attachmentMap; for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { @@ -574,7 +630,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) { String(Json::getString( attachmentMap, "skin", 0)), - slotIndex, + slot->getIndex(), String(entry->_valueString), inheritDeform); _linkedMeshes.add(linkedMesh); } @@ -640,7 +696,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) { } } - skin->setAttachment(slotIndex, skinAttachmentName, attachment); + skin->setAttachment(slot->getIndex(), skinAttachmentName, attachment); } } } @@ -746,13 +802,12 @@ void SkeletonJson::readCurve(Json *frame, CurveTimeline *timeline, size_t frameI } if (curve->_type == Json::JSON_STRING && strcmp(curve->_valueString, "stepped") == 0) { timeline->setStepped(frameIndex); - } else if (curve->_type == Json::JSON_ARRAY) { - Json *child0 = curve->_child; - Json *child1 = child0->_next; - Json *child2 = child1->_next; - Json *child3 = child2->_next; - timeline->setCurve(frameIndex, child0->_valueFloat, child1->_valueFloat, child2->_valueFloat, - child3->_valueFloat); + } else { + float c1 = Json::getFloat(frame, "curve", 0); + float c2 = Json::getFloat(frame, "c2", 0); + float c3 = Json::getFloat(frame, "c3", 1); + float c4 = Json::getFloat(frame, "c4", 1); + timeline->setCurve(frameIndex, c1, c2, c3, c4); } } @@ -905,9 +960,11 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) { int isShear = strcmp(timelineMap->_name, "shear") == 0; if (isScale || isTranslate || isShear) { float timelineScale = isTranslate ? _scale : 1; + float defaultValue = 0; TranslateTimeline *timeline = 0; if (isScale) { timeline = new(__FILE__, __LINE__) ScaleTimeline(timelineMap->_size); + defaultValue = 1; } else if (isTranslate) { timeline = new(__FILE__, __LINE__) TranslateTimeline(timelineMap->_size); } else if (isShear) { @@ -917,8 +974,8 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) { for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), - Json::getFloat(valueMap, "x", 0) * timelineScale, - Json::getFloat(valueMap, "y", 0) * timelineScale); + Json::getFloat(valueMap, "x", defaultValue) * timelineScale, + Json::getFloat(valueMap, "y", defaultValue) * timelineScale); readCurve(valueMap, timeline, frameIndex); } diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index 6e3256ee3..2b5d67b0e 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -37,6 +37,7 @@ #include #include +#include #include @@ -157,6 +158,12 @@ void Skin::attachAll(Skeleton &skeleton, Skin &oldSkin) { } void Skin::addSkin(Skin* other) { + for (int i = 0; i < other->getBones().size(); i++) + if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]); + + for (int i = 0; i < other->getConstraints().size(); i++) + if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]); + AttachmentMap::Entries entries = other->getAttachments(); while(entries.hasNext()) { AttachmentMap::Entry& entry = entries.next(); @@ -165,6 +172,12 @@ void Skin::addSkin(Skin* other) { } void Skin::copySkin(Skin* other) { + for (int i = 0; i < other->getBones().size(); i++) + if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]); + + for (int i = 0; i < other->getConstraints().size(); i++) + if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]); + AttachmentMap::Entries entries = other->getAttachments(); while(entries.hasNext()) { AttachmentMap::Entry& entry = entries.next(); @@ -175,3 +188,11 @@ void Skin::copySkin(Skin* other) { } } } + +Vector& Skin::getConstraints() { + return _constraints; +} + +Vector& Skin::getBones() { + return _bones; +} diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index 70f3907fa..79a493dbb 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -41,9 +41,9 @@ using namespace spine; -RTTI_IMPL(TransformConstraint, Constraint) +RTTI_IMPL(TransformConstraint, Updatable) -TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Constraint(), +TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Updatable(), _data(data), _target(skeleton.findBone( data.getTarget()->getName())), @@ -54,7 +54,8 @@ TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton _scaleMix( data.getScaleMix()), _shearMix( - data.getShearMix()) { + data.getShearMix()), + _active(false) { _bones.ensureCapacity(_data.getBones().size()); for (size_t i = 0; i < _data.getBones().size(); ++i) { BoneData *boneData = _data.getBones()[i]; @@ -380,3 +381,12 @@ void TransformConstraint::applyRelativeLocal() { bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); } } + +bool TransformConstraint::isActive() { + return _active; +} + +void TransformConstraint::setActive(bool inValue) { + _active = inValue; +} + diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp index 404b75af2..127aa7369 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -39,8 +39,7 @@ using namespace spine; TransformConstraintData::TransformConstraintData(const String &name) : - _name(name), - _order(0), + ConstraintData(name), _target(NULL), _rotateMix(0), _translateMix(0), @@ -54,15 +53,6 @@ TransformConstraintData::TransformConstraintData(const String &name) : _offsetShearY(0), _relative(false), _local(false) { - assert(_name.length() > 0); -} - -const String &TransformConstraintData::getName() { - return _name; -} - -int TransformConstraintData::getOrder() { - return _order; } Vector &TransformConstraintData::getBones() { diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index 9dccc361b..147b4bdf5 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -71,6 +71,7 @@ void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, floa TransformConstraint *constraintP = skeleton._transformConstraints[_transformConstraintIndex]; TransformConstraint &constraint = *constraintP; + if (!constraint.isActive()) return; if (time < _frames[0]) { switch (blend) { diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index 17811c0bd..1fcfdefff 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -68,6 +68,7 @@ void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Ve Bone *boneP = skeleton._bones[_boneIndex]; Bone &bone = *boneP; + if (!bone._active) return; if (time < _frames[0]) { switch (blend) { diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 8060d8e03..799828869 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -75,6 +76,7 @@ void TwoColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vec Slot *slotP = skeleton._slots[_slotIndex]; Slot &slot = *slotP; + if (!slot._bone.isActive()) return; if (time < _frames[0]) { // Time is before first frame. diff --git a/spine-sfml/c/src/spine/spine-sfml.cpp b/spine-sfml/c/src/spine/spine-sfml.cpp index aaf31ee8a..59d3c6bdc 100644 --- a/spine-sfml/c/src/spine/spine-sfml.cpp +++ b/spine-sfml/c/src/spine/spine-sfml.cpp @@ -128,7 +128,7 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const { if (!attachment) continue; // Early out if slot is invisible - if (slot->color.a == 0) { + if (slot->color.a == 0 || !slot->bone->active) { spSkeletonClipping_clipEnd(clipper, slot); continue; } diff --git a/spine-sfml/cpp/example/main.cpp b/spine-sfml/cpp/example/main.cpp index c4ca18e69..bc710e496 100644 --- a/spine-sfml/cpp/example/main.cpp +++ b/spine-sfml/cpp/example/main.cpp @@ -473,7 +473,7 @@ int main () { SpineExtension::setInstance(&dbgExtension); testcase(goblins, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f); - /*testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f); + testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f); testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f); testcase(stretchymanStrechyIk, "data/stretchyman-stretchy-ik-pro.json", "data/stretchyman-stretchy-ik-pro.skel", "data/stretchyman-pma.atlas", 0.6f); testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f); @@ -481,7 +481,7 @@ int main () { testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine-pma.atlas", 0.5f); testcase(tank, "data/tank-pro.json", "data/tank-pro.skel", "data/tank-pma.atlas", 0.2f); testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f); - testcase(stretchyman, "data/stretchyman-pro.json", "data/stretchyman-pro.skel", "data/stretchyman-pma.atlas", 0.6f);*/ + testcase(stretchyman, "data/stretchyman-pro.json", "data/stretchyman-pro.skel", "data/stretchyman-pma.atlas", 0.6f); dbgExtension.reportLeaks(); return 0; diff --git a/spine-sfml/cpp/src/spine/spine-sfml.cpp b/spine-sfml/cpp/src/spine/spine-sfml.cpp index f3e43392b..7e759f00a 100644 --- a/spine-sfml/cpp/src/spine/spine-sfml.cpp +++ b/spine-sfml/cpp/src/spine/spine-sfml.cpp @@ -102,8 +102,8 @@ void SkeletonDrawable::draw(RenderTarget &target, RenderStates states) const { Attachment *attachment = slot.getAttachment(); if (!attachment) continue; - // Early out if the slot color is 0 - if (slot.getColor().a == 0) { + // Early out if the slot color is 0 or the bone is not active + if (slot.getColor().a == 0 || !slot.getBone().isActive()) { clipper.clipEnd(slot); continue; }