From 98b9a056f3cd3b719484895240d209a1d0d228e2 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 12 Jun 2025 03:46:51 +0200 Subject: [PATCH] [cpp] 4.3 porting WIP --- .../spine-cpp/include/spine/ConstraintData.h | 23 +- .../include/spine/IkConstraintData.h | 2 +- .../include/spine/PathConstraintData.h | 2 +- .../include/spine/PhysicsConstraintData.h | 2 +- .../spine-cpp/include/spine/SkeletonData.h | 39 ++ .../include/spine/TransformConstraint.h | 74 +--- .../include/spine/TransformConstraintData.h | 16 +- .../spine-cpp/src/spine/ConstraintData.cpp | 15 +- .../spine-cpp/src/spine/IkConstraintData.cpp | 4 +- .../src/spine/PathConstraintData.cpp | 4 +- .../src/spine/PhysicsConstraintData.cpp | 4 +- .../spine-cpp/src/spine/SkeletonData.cpp | 26 +- .../src/spine/TransformConstraint.cpp | 391 +++++------------- .../src/spine/TransformConstraintData.cpp | 46 +-- 14 files changed, 237 insertions(+), 411 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/ConstraintData.h b/spine-cpp/spine-cpp/include/spine/ConstraintData.h index e19258c14..afff1d552 100644 --- a/spine-cpp/spine-cpp/include/spine/ConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/ConstraintData.h @@ -37,26 +37,37 @@ namespace spine { class Skeleton; - /// Base class for all constraint data. + /// Base class for all constraint data types. + class SP_API ConstraintData : public SpineObject { + RTTI_DECL + public: + ConstraintData(const String &name); + virtual ~ConstraintData(); + const String &getName() const; + private: + String _name; + }; + + /// Generic base class for all constraint data. template - class SP_API ConstraintData : public PosedData

{ + class SP_API ConstraintDataGeneric : public PosedData

, public ConstraintData { friend class SkeletonBinary; friend class SkeletonJson; public: - ConstraintData(const String &name); - virtual ~ConstraintData(); + ConstraintDataGeneric(const String &name); + virtual ~ConstraintDataGeneric(); /// Creates a constraint instance. virtual T* create(Skeleton& skeleton) = 0; }; template - ConstraintData::ConstraintData(const String &name) : PosedData

(name) { + ConstraintDataGeneric::ConstraintDataGeneric(const String &name) : PosedData

(name), ConstraintData(name) { } template - ConstraintData::~ConstraintData() { + ConstraintDataGeneric::~ConstraintDataGeneric() { } } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index f64561d9e..7fd2dcf78 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -40,7 +40,7 @@ namespace spine { class BoneData; class IkConstraint; - class SP_API IkConstraintData : public ConstraintData { + class SP_API IkConstraintData : public ConstraintDataGeneric { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index ae91cd52a..b23048e09 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -73,7 +73,7 @@ namespace spine { /// Stores the setup pose for a PathConstraint. /// /// See https://esotericsoftware.com/spine-path-constraints Path constraints in the Spine User Guide. - class SP_API PathConstraintData : public ConstraintData { + class SP_API PathConstraintData : public ConstraintDataGeneric { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h b/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h index 350c89840..5a28d2059 100644 --- a/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h @@ -40,7 +40,7 @@ namespace spine { /// Stores the setup pose for a PhysicsConstraint. /// /// See https://esotericsoftware.com/spine-physics-constraints Physics constraints in the Spine User Guide. - class SP_API PhysicsConstraintData : public ConstraintData { + class SP_API PhysicsConstraintData : public ConstraintDataGeneric { friend class SkeletonBinary; friend class SkeletonJson; friend class PhysicsConstraint; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/spine-cpp/spine-cpp/include/spine/SkeletonData.h index 71afa1499..1eb10f519 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonData.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -52,7 +52,12 @@ namespace spine { class PhysicsConstraintData; + class ConstraintData; + /// Stores the setup pose and all of the stateless data for a skeleton. +/// +/// See Data objects in the Spine Runtimes +/// Guide. class SP_API SkeletonData : public SpineObject { friend class SkeletonBinary; @@ -94,6 +99,8 @@ namespace spine { /// @return May be NULL. PhysicsConstraintData *findPhysicsConstraint(const String &constraintName); + /// The skeleton's name, which by default is the name of the skeleton data file when possible, or null when a name hasn't been + /// set. const String &getName(); void setName(const String &inValue); @@ -101,6 +108,7 @@ namespace spine { /// The skeleton's bones, sorted parent first. The root bone is always the first bone. Vector &getBones(); + /// The skeleton's slots in the setup pose draw order. Vector &getSlots(); /// All skins, including the default skin. @@ -113,8 +121,10 @@ namespace spine { void setDefaultSkin(Skin *inValue); + /// The skeleton's events. Vector &getEvents(); + /// The skeleton's animations. Vector &getAnimations(); Vector &getIkConstraints(); @@ -125,22 +135,47 @@ namespace spine { Vector &getPhysicsConstraints(); + /// The skeleton's constraints. + Vector &getConstraints(); + + /// Finds a constraint by name and type. + /// @return May be NULL. + template + T *findConstraint(const String &constraintName) { + getConstraints(); // Ensure constraints array is populated + for (size_t i = 0, n = _constraints.size(); i < n; i++) { + ConstraintData *constraint = _constraints[i]; + if (constraint->getName().equals(constraintName)) { + if (constraint->rtti.isExactly(T::rtti)) { + return static_cast(constraint); + } + } + } + return NULL; + } + + /// The X coordinate of the skeleton's axis aligned bounding box in the setup pose. float getX(); void setX(float inValue); + /// The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. float getY(); void setY(float inValue); + /// The width of the skeleton's axis aligned bounding box in the setup pose. float getWidth(); void setWidth(float inValue); + /// The height of the skeleton's axis aligned bounding box in the setup pose. float getHeight(); void setHeight(float inValue); + /// Baseline scale factor for applying physics and other effects based on distance to non-scalable properties, such as angle or + /// scale. Default is 100. float getReferenceScale(); void setReferenceScale(float inValue); @@ -150,14 +185,17 @@ namespace spine { void setVersion(const String &inValue); + /// The skeleton data hash. This value will change if any of the skeleton data has changed. const String &getHash(); void setHash(const String &inValue); + /// The path to the images directory as defined in Spine, or null if nonessential data was not exported. const String &getImagesPath(); void setImagesPath(const String &inValue); + /// The path to the audio directory as defined in Spine, or null if nonessential data was not exported. const String &getAudioPath(); void setAudioPath(const String &inValue); @@ -179,6 +217,7 @@ namespace spine { Vector _transformConstraints; Vector _pathConstraints; Vector _physicsConstraints; + Vector _constraints; float _x, _y, _width, _height; float _referenceScale; String _version; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index cc8590292..165093d1f 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -30,83 +30,45 @@ #ifndef Spine_TransformConstraint_h #define Spine_TransformConstraint_h -#include - +#include +#include +#include #include namespace spine { - class TransformConstraintData; - class Skeleton; - class Bone; + class BonePose; - class SP_API TransformConstraint : public Updatable { + class SP_API TransformConstraint : public Constraint { friend class Skeleton; - friend class TransformConstraintTimeline; RTTI_DECL public: - TransformConstraint(TransformConstraintData &data, Skeleton &skeleton); + TransformConstraint(TransformConstraintData& data, Skeleton& skeleton); - virtual void update(Physics physics); + TransformConstraint copy(Skeleton& skeleton); - virtual int getOrder(); + /// Applies the constraint to the constrained bones. + void update(Skeleton& skeleton, Physics physics); - TransformConstraintData &getData(); + void sort(Skeleton& skeleton); - Vector &getBones(); + bool isSourceActive(); - Bone *getTarget(); + /// The bones that will be modified by this transform constraint. + Vector& getBones(); - void setTarget(Bone *inValue); + /// The bone whose world transform will be copied to the constrained bones. + Bone* getSource(); - float getMixRotate(); - - void setMixRotate(float inValue); - - float getMixX(); - - void setMixX(float inValue); - - float getMixY(); - - void setMixY(float inValue); - - float getMixScaleX(); - - void setMixScaleX(float inValue); - - float getMixScaleY(); - - void setMixScaleY(float inValue); - - float getMixShearY(); - - void setMixShearY(float inValue); - - bool isActive(); - - void setActive(bool inValue); - - void setToSetupPose(); + void setSource(Bone* source); private: - TransformConstraintData &_data; - Vector _bones; - Bone *_target; - float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY; - bool _active; - - void applyAbsoluteWorld(); - - void applyRelativeWorld(); - - void applyAbsoluteLocal(); - - void applyRelativeLocal(); + Vector _bones; + Bone* _source; }; } diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index 7978b3855..7f8ba468a 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -43,7 +43,6 @@ namespace spine { /// Source property for a TransformConstraint. class SP_API FromProperty : public SpineObject { public: - RTTI_DECL /// The value of this property that corresponds to ToProperty offset. float offset; @@ -61,7 +60,6 @@ namespace spine { /// Constrained property for a TransformConstraint. class SP_API ToProperty : public SpineObject { public: - RTTI_DECL /// The value of this property that corresponds to FromProperty offset. float offset; @@ -84,78 +82,66 @@ namespace spine { class SP_API FromRotate : public FromProperty { public: - RTTI_DECL float value(BonePose& source, bool local, float* offsets) override; }; class SP_API ToRotate : public ToProperty { public: - RTTI_DECL float mix(TransformConstraintPose& pose) override; void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; class SP_API FromX : public FromProperty { public: - RTTI_DECL float value(BonePose& source, bool local, float* offsets) override; }; class SP_API ToX : public ToProperty { public: - RTTI_DECL float mix(TransformConstraintPose& pose) override; void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; class SP_API FromY : public FromProperty { public: - RTTI_DECL float value(BonePose& source, bool local, float* offsets) override; }; class SP_API ToY : public ToProperty { public: - RTTI_DECL float mix(TransformConstraintPose& pose) override; void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; class SP_API FromScaleX : public FromProperty { public: - RTTI_DECL float value(BonePose& source, bool local, float* offsets) override; }; class SP_API ToScaleX : public ToProperty { public: - RTTI_DECL float mix(TransformConstraintPose& pose) override; void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; class SP_API FromScaleY : public FromProperty { public: - RTTI_DECL float value(BonePose& source, bool local, float* offsets) override; }; class SP_API ToScaleY : public ToProperty { public: - RTTI_DECL float mix(TransformConstraintPose& pose) override; void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; class SP_API FromShearY : public FromProperty { public: - RTTI_DECL float value(BonePose& source, bool local, float* offsets) override; }; class SP_API ToShearY : public ToProperty { public: - RTTI_DECL float mix(TransformConstraintPose& pose) override; void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; @@ -163,7 +149,7 @@ namespace spine { /// Stores the setup pose for a TransformConstraint. /// /// See https://esotericsoftware.com/spine-transform-constraints Transform constraints in the Spine User Guide. - class SP_API TransformConstraintData : public ConstraintData { + class SP_API TransformConstraintData : public ConstraintDataGeneric { public: static const int ROTATION = 0, X = 1, Y = 2, SCALEX = 3, SCALEY = 4, SHEARY = 5; friend class SkeletonBinary; diff --git a/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp index 9c44db0ff..64a60d202 100644 --- a/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp @@ -29,5 +29,16 @@ #include -// Template class - implementation is in the header file -using namespace spine; \ No newline at end of file +using namespace spine; + +RTTI_IMPL_NOPARENT(ConstraintData) + +ConstraintData::ConstraintData(const String &name) : _name(name) { +} + +ConstraintData::~ConstraintData() { +} + +const String &ConstraintData::getName() const { + return _name; +} \ No newline at end of file diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index 84df371f9..316bdad1e 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -33,9 +33,9 @@ using namespace spine; -RTTI_IMPL_NOPARENT(IkConstraintData) +RTTI_IMPL(IkConstraintData, ConstraintData) -IkConstraintData::IkConstraintData(const String &name) : ConstraintData(name), +IkConstraintData::IkConstraintData(const String &name) : ConstraintDataGeneric(name), _target(NULL), _uniform(false) { } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp index 14ab9014f..6df5a564a 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -34,9 +34,9 @@ using namespace spine; -RTTI_IMPL_NOPARENT(PathConstraintData) +RTTI_IMPL(PathConstraintData, ConstraintData) -PathConstraintData::PathConstraintData(const String &name) : ConstraintData(name), +PathConstraintData::PathConstraintData(const String &name) : ConstraintDataGeneric(name), _slot(NULL), _positionMode(PositionMode_Fixed), _spacingMode(SpacingMode_Length), diff --git a/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp index 128f04e78..d7403ef12 100644 --- a/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp @@ -32,9 +32,9 @@ using namespace spine; -RTTI_IMPL_NOPARENT(PhysicsConstraintData) +RTTI_IMPL(PhysicsConstraintData, ConstraintData) -PhysicsConstraintData::PhysicsConstraintData(const String &name) : ConstraintData(name), +PhysicsConstraintData::PhysicsConstraintData(const String &name) : ConstraintDataGeneric(name), _bone(NULL), _x(0), _y(0), _rotate(0), _scaleX(0), _shearX(0), _limit(0), _step(0), _inertiaGlobal(false), _strengthGlobal(false), _dampingGlobal(false), _massGlobal(false), diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp index e3b35f0ce..8e6e69866 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -52,8 +53,9 @@ SkeletonData::SkeletonData() : _name(), _referenceScale(100), _version(), _hash(), - _fps(0), - _imagesPath() { + _fps(30), + _imagesPath(), + _audioPath() { } SkeletonData::~SkeletonData() { @@ -69,6 +71,8 @@ SkeletonData::~SkeletonData() { ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); ContainerUtil::cleanUpVectorOfPointers(_physicsConstraints); + // Note: _constraints contains pointers to objects already cleaned up above, so just clear + _constraints.clear(); for (size_t i = 0; i < _strings.size(); i++) { SpineExtension::free(_strings[i], __FILE__, __LINE__); } @@ -242,3 +246,21 @@ float SkeletonData::getFps() { void SkeletonData::setFps(float inValue) { _fps = inValue; } + +Vector &SkeletonData::getConstraints() { + // Build unified constraints array by aggregating all constraint types + _constraints.clear(); + for (size_t i = 0, n = _ikConstraints.size(); i < n; i++) { + _constraints.add(static_cast(_ikConstraints[i])); + } + for (size_t i = 0, n = _transformConstraints.size(); i < n; i++) { + _constraints.add(static_cast(_transformConstraints[i])); + } + for (size_t i = 0, n = _pathConstraints.size(); i < n; i++) { + _constraints.add(static_cast(_pathConstraints[i])); + } + for (size_t i = 0, n = _physicsConstraints.size(); i < n; i++) { + _constraints.add(static_cast(_physicsConstraints[i])); + } + return _constraints; +} diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index 3fea0ac51..4fdaea4b2 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -30,321 +30,116 @@ #include #include +#include #include #include +#include #include using namespace spine; -RTTI_IMPL(TransformConstraint, Updatable) +RTTI_IMPL_NOPARENT(TransformConstraint) -TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Updatable(), - _data(data), - _target(skeleton.findBone( - data.getTarget()->getName())), - _mixRotate( - data.getMixRotate()), - _mixX(data.getMixX()), - _mixY(data.getMixY()), - _mixScaleX( - data.getMixScaleX()), - _mixScaleY( - data.getMixScaleY()), - _mixShearY( - data.getMixShearY()), - _active(false) { - _bones.ensureCapacity(_data.getBones().size()); - for (size_t i = 0; i < _data.getBones().size(); ++i) { - BoneData *boneData = _data.getBones()[i]; - _bones.add(skeleton.findBone(boneData->getName())); +TransformConstraint::TransformConstraint(TransformConstraintData& data, Skeleton& skeleton) : + Constraint(data) { + if (&skeleton == NULL) throw; + + _bones.ensureCapacity(data.getBones().size()); + for (size_t i = 0; i < data.getBones().size(); i++) { + BoneData* boneData = data.getBones()[i]; + _bones.add(&skeleton.findBone(boneData->getName())->getAppliedPose()); + } + + _source = skeleton.findBone(data.getSource()->getName()); +} + +TransformConstraint TransformConstraint::copy(Skeleton& skeleton) { + TransformConstraint copy(_data, skeleton); + copy._applied->set(*_applied); + return copy; +} + +/// Applies the constraint to the constrained bones. +void TransformConstraint::update(Skeleton& skeleton, Physics physics) { + TransformConstraintPose& p = *_applied; + if (p.getMixRotate() == 0 && p.getMixX() == 0 && p.getMixY() == 0 && p.getMixScaleX() == 0 && p.getMixScaleY() == 0 && p.getMixShearY() == 0) return; + + TransformConstraintData& data = _data; + bool localSource = data.getLocalSource(), localTarget = data.getLocalTarget(), additive = data.getAdditive(), clamp = data.getClamp(); + float* offsets = data._offsets; // Access friend field directly + BonePose& source = _source->getAppliedPose(); + if (localSource) { + source.validateLocalTransform(skeleton); + } + Vector& properties = data.getProperties(); + FromProperty** fromItems = properties.buffer(); + size_t fn = properties.size(); + int update = 1; // TODO: Add skeleton.update field + BonePose** bones = _bones.buffer(); + for (size_t i = 0, n = _bones.size(); i < n; i++) { + BonePose* bone = bones[i]; + if (localTarget) { + bone->modifyLocal(skeleton); + } else { + bone->modifyWorld(update); + } + for (size_t f = 0; f < fn; f++) { + FromProperty* from = fromItems[f]; + float value = from->value(source, localSource, offsets) - from->offset; + Vector& toProps = from->to; + ToProperty** toItems = toProps.buffer(); + for (size_t t = 0, tn = toProps.size(); t < tn; t++) { + ToProperty* to = toItems[t]; + if (to->mix(p) != 0) { + float clamped = to->offset + value * to->scale; + if (clamp) { + if (to->offset < to->max) + clamped = MathUtil::clamp(clamped, to->offset, to->max); + else + clamped = MathUtil::clamp(clamped, to->max, to->offset); + } + to->apply(p, *bone, clamped, localTarget, additive); + } + } + } } } -void TransformConstraint::update(Physics) { - if (_mixRotate == 0 && _mixX == 0 && _mixY == 0 && _mixScaleX == 0 && _mixScaleY == 0 && _mixShearY == 0) return; - - if (_data.isLocal()) { - if (_data.isRelative()) - applyRelativeLocal(); - else - applyAbsoluteLocal(); - } else { - if (_data.isRelative()) - applyRelativeWorld(); - else - applyAbsoluteWorld(); - } +void TransformConstraint::sort(Skeleton& skeleton) { + // if (!_data.getLocalSource()) skeleton.sortBone(_source); // TODO: sortBone is private, need friend access + BonePose** bones = _bones.buffer(); + size_t boneCount = _bones.size(); + bool worldTarget = !_data.getLocalTarget(); + // if (worldTarget) { + // for (size_t i = 0; i < boneCount; i++) + // skeleton.sortBone(bones[i]->_bone); // TODO: sortBone is private, need friend access + // } + // skeleton._updateCache.add(this); // TODO: _updateCache is private, need friend access + // for (size_t i = 0; i < boneCount; i++) { + // Bone* bone = bones[i]->_bone; + // skeleton.sortReset(bone->getChildren()); // TODO: sortReset is private, need friend access + // // skeleton.constrained(bone); // TODO: Add constrained() method to Skeleton class + // } + // for (size_t i = 0; i < boneCount; i++) + // bones[i]->_bone->_sorted = worldTarget; // TODO: _sorted is private, need friend access } -int TransformConstraint::getOrder() { - return (int) _data.getOrder(); +bool TransformConstraint::isSourceActive() { + return _source->isActive(); } -TransformConstraintData &TransformConstraint::getData() { - return _data; -} - -Vector &TransformConstraint::getBones() { +/// The bones that will be modified by this transform constraint. +Vector& TransformConstraint::getBones() { return _bones; } -Bone *TransformConstraint::getTarget() { - return _target; +/// The bone whose world transform will be copied to the constrained bones. +Bone* TransformConstraint::getSource() { + return _source; } -void TransformConstraint::setTarget(Bone *inValue) { - _target = inValue; -} - -float TransformConstraint::getMixRotate() { - return _mixRotate; -} - -void TransformConstraint::setMixRotate(float inValue) { - _mixRotate = inValue; -} - -float TransformConstraint::getMixX() { - return _mixX; -} - -void TransformConstraint::setMixX(float inValue) { - _mixX = inValue; -} - -float TransformConstraint::getMixY() { - return _mixY; -} - -void TransformConstraint::setMixY(float inValue) { - _mixY = inValue; -} - -void TransformConstraint::setMixScaleX(float inValue) { - _mixScaleX = inValue; -} - -float TransformConstraint::getMixScaleX() { - return _mixScaleX; -} - -float TransformConstraint::getMixScaleY() { - return _mixScaleY; -} - -void TransformConstraint::setMixScaleY(float inValue) { - _mixScaleY = inValue; -} - -float TransformConstraint::getMixShearY() { - return _mixShearY; -} - -void TransformConstraint::setMixShearY(float inValue) { - _mixShearY = inValue; -} - -void TransformConstraint::applyAbsoluteWorld() { - float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; - bool translate = mixX != 0 || mixY != 0; - Bone &target = *_target; - float ta = target._a, tb = target._b, tc = target._c, td = target._d; - float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; - float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; - - for (size_t i = 0; i < _bones.size(); ++i) { - Bone *item = _bones[i]; - Bone &bone = *item; - - if (mixRotate != 0) { - float a = bone._a, b = bone._b, c = bone._c, d = bone._d; - float r = MathUtil::atan2(tc, ta) - MathUtil::atan2(c, a) + offsetRotation; - if (r > MathUtil::Pi) - r -= MathUtil::Pi_2; - else if (r < -MathUtil::Pi) - r += MathUtil::Pi_2; - - r *= mixRotate; - float cos = MathUtil::cos(r), sin = MathUtil::sin(r); - bone._a = cos * a - sin * c; - bone._b = cos * b - sin * d; - bone._c = sin * a + cos * c; - bone._d = sin * b + cos * d; - } - - if (translate) { - float tx, ty; - target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); - bone._worldX += (tx - bone._worldX) * mixX; - bone._worldY += (ty - bone._worldY) * mixY; - } - - if (mixScaleX > 0) { - float s = MathUtil::sqrt(bone._a * bone._a + bone._c * bone._c); - if (s != 0) s = (s + (MathUtil::sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * mixScaleX) / s; - bone._a *= s; - bone._c *= s; - } - - if (mixScaleY > 0) { - float s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d); - if (s != 0) s = (s + (MathUtil::sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * mixScaleY) / s; - bone._b *= s; - bone._d *= s; - } - - if (mixShearY > 0) { - float b = bone._b, d = bone._d; - float by = MathUtil::atan2(d, b); - float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta) - (by - MathUtil::atan2(bone._c, bone._a)); - if (r > MathUtil::Pi) - r -= MathUtil::Pi_2; - else if (r < -MathUtil::Pi) - r += MathUtil::Pi_2; - - r = by + (r + offsetShearY) * mixShearY; - float s = MathUtil::sqrt(b * b + d * d); - bone._b = MathUtil::cos(r) * s; - bone._d = MathUtil::sin(r) * s; - } - - bone.updateAppliedTransform(); - } -} - -void TransformConstraint::applyRelativeWorld() { - float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; - bool translate = mixX != 0 || mixY != 0; - Bone &target = *_target; - float ta = target._a, tb = target._b, tc = target._c, td = target._d; - float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; - float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; - for (size_t i = 0; i < _bones.size(); ++i) { - Bone *item = _bones[i]; - Bone &bone = *item; - - if (mixRotate != 0) { - float a = bone._a, b = bone._b, c = bone._c, d = bone._d; - float r = MathUtil::atan2(tc, ta) + offsetRotation; - if (r > MathUtil::Pi) - r -= MathUtil::Pi_2; - else if (r < -MathUtil::Pi) - r += MathUtil::Pi_2; - - r *= mixRotate; - float cos = MathUtil::cos(r), sin = MathUtil::sin(r); - bone._a = cos * a - sin * c; - bone._b = cos * b - sin * d; - bone._c = sin * a + cos * c; - bone._d = sin * b + cos * d; - } - - if (translate) { - float tx, ty; - target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); - bone._worldX += tx * mixX; - bone._worldY += ty * mixY; - } - - if (mixScaleX != 0) { - float s = (MathUtil::sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * mixScaleX + 1; - bone._a *= s; - bone._c *= s; - } - if (mixScaleY != 0) { - float s = (MathUtil::sqrt(tb * tb + td * td) - 1 + _data._offsetScaleY) * mixScaleY + 1; - bone._b *= s; - bone._d *= s; - } - - if (mixShearY > 0) { - float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta); - if (r > MathUtil::Pi) - r -= MathUtil::Pi_2; - else if (r < -MathUtil::Pi) - r += MathUtil::Pi_2; - - float b = bone._b, d = bone._d; - r = MathUtil::atan2(d, b) + (r - MathUtil::Pi / 2 + offsetShearY) * mixShearY; - float s = MathUtil::sqrt(b * b + d * d); - bone._b = MathUtil::cos(r) * s; - bone._d = MathUtil::sin(r) * s; - } - - bone.updateAppliedTransform(); - } -} - -void TransformConstraint::applyAbsoluteLocal() { - float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; - Bone &target = *_target; - - for (size_t i = 0; i < _bones.size(); ++i) { - Bone *item = _bones[i]; - Bone &bone = *item; - - float rotation = bone._arotation; - if (mixRotate != 0) { - float r = target._arotation - rotation + _data._offsetRotation; - r -= MathUtil::ceil(r / 360 - 0.5) * 360; - rotation += r * mixRotate; - } - - float x = bone._ax, y = bone._ay; - x += (target._ax - x + _data._offsetX) * mixX; - y += (target._ay - y + _data._offsetY) * mixY; - - float scaleX = bone._ascaleX, scaleY = bone._ascaleY; - if (mixScaleX != 0 && scaleX != 0) - scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * mixScaleX) / scaleX; - if (mixScaleY != 0 && scaleY != 0) - scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * mixScaleY) / scaleY; - - float shearY = bone._ashearY; - if (mixShearY != 0) { - float r = target._ashearY - shearY + _data._offsetShearY; - r -= MathUtil::ceil(r / 360 - 0.5) * 360; - bone._shearY += r * mixShearY; - } - - bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); - } -} - -void TransformConstraint::applyRelativeLocal() { - float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY; - Bone &target = *_target; - - for (size_t i = 0; i < _bones.size(); ++i) { - Bone *item = _bones[i]; - Bone &bone = *item; - - float rotation = bone._arotation + (target._arotation + _data._offsetRotation) * mixRotate; - float x = bone._ax + (target._ax + _data._offsetX) * mixX; - float y = bone._ay + (target._ay + _data._offsetY) * mixY; - float scaleX = bone._ascaleX * (((target._ascaleX - 1 + _data._offsetScaleX) * mixScaleX) + 1); - float scaleY = bone._ascaleY * (((target._ascaleY - 1 + _data._offsetScaleY) * mixScaleY) + 1); - float shearY = bone._ashearY + (target._ashearY + _data._offsetShearY) * mixShearY; - - bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); - } -} - -bool TransformConstraint::isActive() { - return _active; -} - -void TransformConstraint::setActive(bool inValue) { - _active = inValue; -} - -void TransformConstraint::setToSetupPose() { - TransformConstraintData &data = this->_data; - this->_mixRotate = data._mixRotate; - this->_mixX = data._mixX; - this->_mixY = data._mixY; - this->_mixScaleX = data._mixScaleX; - this->_mixScaleY = data._mixScaleY; - this->_mixShearY = data._mixShearY; -} +void TransformConstraint::setSource(Bone* source) { + if (source == NULL) throw; + _source = source; +} \ No newline at end of file diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp index 86a2e13b4..5b1029772 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -36,9 +36,9 @@ using namespace spine; -RTTI_IMPL_NOPARENT(TransformConstraintData) +RTTI_IMPL(TransformConstraintData, ConstraintData) -TransformConstraintData::TransformConstraintData(const String &name) : ConstraintData(name), +TransformConstraintData::TransformConstraintData(const String &name) : ConstraintDataGeneric(name), _source(NULL), _localSource(false), _localTarget(false), @@ -149,7 +149,7 @@ Vector& TransformConstraintData::getProperties() { // Property Classes // ============================================================================ -RTTI_IMPL_NOPARENT(FromProperty) +// No RTTI for FromProperty FromProperty::FromProperty() : SpineObject(), offset(0) { } @@ -157,7 +157,7 @@ FromProperty::FromProperty() : SpineObject(), offset(0) { FromProperty::~FromProperty() { } -RTTI_IMPL_NOPARENT(ToProperty) +// No RTTI for ToProperty ToProperty::ToProperty() : offset(0), max(0), scale(1) { } @@ -165,17 +165,17 @@ ToProperty::ToProperty() : offset(0), max(0), scale(1) { ToProperty::~ToProperty() { } -RTTI_IMPL(FromRotate, FromProperty) +// No RTTI for FromRotate float FromRotate::value(BonePose& source, bool local, float* offsets) { - if (local) return source.getRotation() + offsets[ROTATION]; + if (local) return source.getRotation() + offsets[TransformConstraintData::ROTATION]; float value = MathUtil::atan2(source._c, source._a) * MathUtil::Rad_Deg - + (source._a * source._d - source._b * source._c > 0 ? offsets[ROTATION] : -offsets[ROTATION]); + + (source._a * source._d - source._b * source._c > 0 ? offsets[TransformConstraintData::ROTATION] : -offsets[TransformConstraintData::ROTATION]); if (value < 0) value += 360; return value; } -RTTI_IMPL(ToRotate, ToProperty) +// No RTTI for ToRotate float ToRotate::mix(TransformConstraintPose& pose) { return pose._mixRotate; @@ -202,13 +202,13 @@ void ToRotate::apply(TransformConstraintPose& pose, BonePose& bone, float value, } } -RTTI_IMPL(FromX, FromProperty) +// No RTTI for FromX float FromX::value(BonePose& source, bool local, float* offsets) { - return local ? source.getX() + offsets[X] : offsets[X] * source._a + offsets[Y] * source._b + source.getWorldX(); + return local ? source.getX() + offsets[TransformConstraintData::X] : offsets[TransformConstraintData::X] * source._a + offsets[TransformConstraintData::Y] * source._b + source.getWorldX(); } -RTTI_IMPL(ToX, ToProperty) +// No RTTI for ToX float ToX::mix(TransformConstraintPose& pose) { return pose._mixX; @@ -224,13 +224,13 @@ void ToX::apply(TransformConstraintPose& pose, BonePose& bone, float value, bool } } -RTTI_IMPL(FromY, FromProperty) +// No RTTI for FromY float FromY::value(BonePose& source, bool local, float* offsets) { - return local ? source.getY() + offsets[Y] : offsets[X] * source._c + offsets[Y] * source._d + source.getWorldY(); + return local ? source.getY() + offsets[TransformConstraintData::Y] : offsets[TransformConstraintData::X] * source._c + offsets[TransformConstraintData::Y] * source._d + source.getWorldY(); } -RTTI_IMPL(ToY, ToProperty) +// No RTTI for ToY float ToY::mix(TransformConstraintPose& pose) { return pose._mixY; @@ -246,13 +246,13 @@ void ToY::apply(TransformConstraintPose& pose, BonePose& bone, float value, bool } } -RTTI_IMPL(FromScaleX, FromProperty) +// No RTTI for FromScaleX float FromScaleX::value(BonePose& source, bool local, float* offsets) { - return (local ? source.getScaleX() : MathUtil::sqrt(source._a * source._a + source._c * source._c)) + offsets[SCALEX]; + return (local ? source.getScaleX() : MathUtil::sqrt(source._a * source._a + source._c * source._c)) + offsets[TransformConstraintData::SCALEX]; } -RTTI_IMPL(ToScaleX, ToProperty) +// No RTTI for ToScaleX float ToScaleX::mix(TransformConstraintPose& pose) { return pose._mixScaleX; @@ -277,13 +277,13 @@ void ToScaleX::apply(TransformConstraintPose& pose, BonePose& bone, float value, } } -RTTI_IMPL(FromScaleY, FromProperty) +// No RTTI for FromScaleY float FromScaleY::value(BonePose& source, bool local, float* offsets) { - return (local ? source.getScaleY() : MathUtil::sqrt(source._b * source._b + source._d * source._d)) + offsets[SCALEY]; + return (local ? source.getScaleY() : MathUtil::sqrt(source._b * source._b + source._d * source._d)) + offsets[TransformConstraintData::SCALEY]; } -RTTI_IMPL(ToScaleY, ToProperty) +// No RTTI for ToScaleY float ToScaleY::mix(TransformConstraintPose& pose) { return pose._mixScaleY; @@ -308,13 +308,13 @@ void ToScaleY::apply(TransformConstraintPose& pose, BonePose& bone, float value, } } -RTTI_IMPL(FromShearY, FromProperty) +// No RTTI for FromShearY float FromShearY::value(BonePose& source, bool local, float* offsets) { - return (local ? source.getShearY() : (MathUtil::atan2(source._d, source._b) - MathUtil::atan2(source._c, source._a)) * MathUtil::Rad_Deg - 90) + offsets[SHEARY]; + return (local ? source.getShearY() : (MathUtil::atan2(source._d, source._b) - MathUtil::atan2(source._c, source._a)) * MathUtil::Rad_Deg - 90) + offsets[TransformConstraintData::SHEARY]; } -RTTI_IMPL(ToShearY, ToProperty) +// No RTTI for ToShearY float ToShearY::mix(TransformConstraintPose& pose) { return pose._mixShearY;