diff --git a/spine-cpp/spine-cpp/include/spine/BoneLocal.h b/spine-cpp/spine-cpp/include/spine/BoneLocal.h index 8fa949789..8d6a858b2 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneLocal.h +++ b/spine-cpp/spine-cpp/include/spine/BoneLocal.h @@ -38,6 +38,7 @@ namespace spine { /// Stores a bone's local pose. class SP_API BoneLocal : public Pose { + friend class IkConstraint; friend class BoneTimeline1; friend class BoneTimeline2; friend class RotateTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/BonePose.h b/spine-cpp/spine-cpp/include/spine/BonePose.h index e95981855..70d406bf7 100644 --- a/spine-cpp/spine-cpp/include/spine/BonePose.h +++ b/spine-cpp/spine-cpp/include/spine/BonePose.h @@ -39,6 +39,7 @@ namespace spine { class Skeleton; class SP_API BonePose : public BoneLocal, public Update { + friend class IkConstraint; RTTI_DECL public: diff --git a/spine-cpp/spine-cpp/include/spine/Constraint.h b/spine-cpp/spine-cpp/include/spine/Constraint.h index 69528e753..c443f17e9 100644 --- a/spine-cpp/spine-cpp/include/spine/Constraint.h +++ b/spine-cpp/spine-cpp/include/spine/Constraint.h @@ -42,7 +42,7 @@ namespace spine { RTTI_DECL public: - Constraint(D& data, P& pose, P& constrained) : PosedActive(data, pose, constrained) { + Constraint(D& data) : PosedActive(data) { } virtual ~Constraint() { diff --git a/spine-cpp/spine-cpp/include/spine/ConstraintData.h b/spine-cpp/spine-cpp/include/spine/ConstraintData.h index e69837cba..e19258c14 100644 --- a/spine-cpp/spine-cpp/include/spine/ConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/ConstraintData.h @@ -27,15 +27,14 @@ * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#ifndef Spine_Constraint_h -#define Spine_Constraint_h +#ifndef Spine_ConstraintData_h +#define Spine_ConstraintData_h #include #include #include namespace spine { - class Constraint; class Skeleton; /// Base class for all constraint data. @@ -61,4 +60,4 @@ namespace spine { } } -#endif /* Spine_Constraint_h */ +#endif /* Spine_ConstraintData_h */ diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index 077f4f0b8..2f5013987 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -30,18 +30,18 @@ #ifndef Spine_IkConstraint_h #define Spine_IkConstraint_h +#include #include - +#include +#include #include namespace spine { - class IkConstraintData; - class Skeleton; - class Bone; + class BonePose; - class SP_API IkConstraint : public Updatable { + class SP_API IkConstraint : public Constraint { friend class Skeleton; friend class IkConstraintTimeline; @@ -52,66 +52,36 @@ namespace spine { /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified /// in the world coordinate system. static void - apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha); + apply(Skeleton& skeleton, BonePose& bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float mix); /// Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as /// possible. The target is specified in the world coordinate system. /// @param child A direct descendant of the parent bone. static void - apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, - float softness, - float alpha); + apply(Skeleton& skeleton, BonePose& parent, BonePose& child, float targetX, float targetY, int bendDirection, bool stretch, bool uniform, + float softness, float mix); IkConstraint(IkConstraintData &data, Skeleton &skeleton); - virtual void update(Physics physics); + virtual void update(Skeleton& skeleton, Physics physics); - virtual int getOrder(); + virtual void sort(Skeleton& skeleton); + + virtual bool isSourceActive(); + + virtual IkConstraint* copy(Skeleton& skeleton); IkConstraintData &getData(); - Vector &getBones(); + Vector &getBones(); Bone *getTarget(); void setTarget(Bone *inValue); - int getBendDirection(); - - void setBendDirection(int inValue); - - bool getCompress(); - - void setCompress(bool inValue); - - bool getStretch(); - - void setStretch(bool inValue); - - float getMix(); - - void setMix(float inValue); - - float getSoftness(); - - void setSoftness(float inValue); - - bool isActive(); - - void setActive(bool inValue); - - void setToSetupPose(); - private: - IkConstraintData &_data; - Vector _bones; - int _bendDirection; - bool _compress; - bool _stretch; - float _mix; - float _softness; + Vector _bones; Bone *_target; - bool _active; }; } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintPose.h b/spine-cpp/spine-cpp/include/spine/IkConstraintPose.h index 213f02d98..9b075268b 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintPose.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintPose.h @@ -37,6 +37,7 @@ namespace spine { /// Stores the current pose for an IK constraint. class SP_API IkConstraintPose : public Pose { + friend class IkConstraint; RTTI_DECL public: diff --git a/spine-cpp/spine-cpp/include/spine/Posed.h b/spine-cpp/spine-cpp/include/spine/Posed.h index 47fc86b25..eb8b4784d 100644 --- a/spine-cpp/spine-cpp/include/spine/Posed.h +++ b/spine-cpp/spine-cpp/include/spine/Posed.h @@ -79,7 +79,7 @@ namespace spine { } void setupPose() { - _pose.set(*_data.getSetupPose()); + _pose.set(_data.getSetupPose()); } /// The constraint's setup pose data. diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index 84609013c..a43497883 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -30,6 +30,8 @@ #include #include +#include +#include #include #include @@ -37,92 +39,80 @@ using namespace spine; -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(); - float pa = p->_a, pb = p->_b, pc = p->_c, pd = p->_d; - float rotationIK = -bone._ashearX - bone._arotation; - float tx = 0, ty = 0; +RTTI_IMPL_NOPARENT(IkConstraint) +void IkConstraint::apply(Skeleton& skeleton, BonePose& bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float mix) { + bone.modifyLocal(skeleton); + BonePose& p = bone._bone->getParent()->getAppliedPose(); + float pa = p._a, pb = p._b, pc = p._c, pd = p._d; + float rotationIK = -bone._shearX - bone._rotation, tx, ty; switch (bone._inherit) { - case Inherit_OnlyTranslation: - tx = (targetX - bone._worldX) * MathUtil::sign(bone.getSkeleton().getScaleX()); - ty = (targetY - bone._worldY) * MathUtil::sign(bone.getSkeleton().getScaleY()); - break; - case Inherit_NoRotationOrReflection: { - float s = MathUtil::abs(pa * pd - pb * pc) / MathUtil::max(0.0001f, pa * pa + pc * pc); - float sa = pa / bone._skeleton.getScaleX(); - float sc = pc / bone._skeleton.getScaleY(); - pb = -sc * s * bone._skeleton.getScaleX(); - pd = sa * s * bone._skeleton.getScaleY(); - rotationIK += MathUtil::atan2Deg(sc, sa); + case Inherit_OnlyTranslation: + tx = (targetX - bone._worldX) * MathUtil::sign(skeleton.getScaleX()); + ty = (targetY - bone._worldY) * MathUtil::sign(skeleton.getScaleY()); + break; + case Inherit_NoRotationOrReflection: { + float s = MathUtil::abs(pa * pd - pb * pc) / MathUtil::max(0.0001f, pa * pa + pc * pc); + float sa = pa / skeleton.getScaleX(); + float sc = pc / skeleton.getScaleY(); + pb = -sc * s * skeleton.getScaleX(); + pd = sa * s * skeleton.getScaleY(); + rotationIK += MathUtil::atan2Deg(sc, sa); + // Fall through. + } + default: + float x = targetX - p._worldX, y = targetY - p._worldY; + float d = pa * pd - pb * pc; + if (MathUtil::abs(d) <= 0.0001f) { + tx = 0; + ty = 0; + } else { + tx = (x * pd - y * pb) / d - bone._x; + ty = (y * pa - x * pc) / d - bone._y; } - default: - float x = targetX - p->_worldX, y = targetY - p->_worldY; - float d = pa * pd - pb * pc; - if (MathUtil::abs(d) <= 0.0001f) { - tx = 0; - ty = 0; - } else { - tx = (x * pd - y * pb) / d - bone._ax; - ty = (y * pa - x * pc) / d - bone._ay; - } } rotationIK += MathUtil::atan2Deg(ty, tx); - if (bone._ascaleX < 0) rotationIK += 180; - if (rotationIK > 180) rotationIK -= 360; - else if (rotationIK < -180) + if (bone._scaleX < 0) rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) // rotationIK += 360; - float sx = bone._ascaleX; - float sy = bone._ascaleY; + bone._rotation += rotationIK * mix; if (compress || stretch) { switch (bone._inherit) { - case Inherit_NoScale: - case Inherit_NoScaleOrReflection: - tx = targetX - bone._worldX; - ty = targetY - bone._worldY; - default:; + case Inherit_NoScale: + case Inherit_NoScaleOrReflection: + tx = targetX - bone._worldX; + ty = targetY - bone._worldY; + break; + default: + break; } - - float b = bone._data.getLength() * sx; - if (b > 0.0001) { + float b = bone._bone->getData().getLength() * bone._scaleX; + if (b > 0.0001f) { float dd = tx * tx + ty * ty; if ((compress && dd < b * b) || (stretch && dd > b * b)) { - float s = (MathUtil::sqrt(dd) / b - 1) * alpha + 1; - sx *= s; - if (uniform) sy *= s; + float s = (MathUtil::sqrt(dd) / b - 1) * mix + 1; + bone._scaleX *= s; + if (uniform) bone._scaleY *= s; } } } - bone.updateWorldTransform(bone._ax, bone._ay, bone._arotation + rotationIK * alpha, sx, sy, bone._ashearX, - bone._ashearY); } -void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, - float softness, - float alpha) { - float a, b, c, d; - float px, py, psx, psy, sx, sy; - float cx, cy, csx, cwx, cwy; - int o1, o2, s2, u; - Bone *pp = parent.getParent(); - float tx, ty, dx, dy, dd, l1, l2, a1, a2, r, td, sd, p; - float id, x, y; +void IkConstraint::apply(Skeleton& skeleton, BonePose& parent, BonePose& child, float targetX, float targetY, int bendDir, + bool stretch, bool uniform, float softness, float mix) { if (parent._inherit != Inherit_Normal || child._inherit != Inherit_Normal) return; - px = parent._ax; - py = parent._ay; - psx = parent._ascaleX; - psy = parent._ascaleY; - sx = psx; - sy = psy; - csx = child._ascaleX; + parent.modifyLocal(skeleton); + child.modifyLocal(skeleton); + float px = parent._x, py = parent._y, psx = parent._scaleX, psy = parent._scaleY, csx = child._scaleX; + int os1, os2, s2; if (psx < 0) { psx = -psx; - o1 = 180; + os1 = 180; s2 = -1; } else { - o1 = 0; + os1 = 0; s2 = 1; } if (psy < 0) { @@ -131,185 +121,166 @@ void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY } if (csx < 0) { csx = -csx; - o2 = 180; + os2 = 180; } else - o2 = 0; - r = psx - psy; - cx = child._ax; - u = (r < 0 ? -r : r) <= 0.0001f; + os2 = 0; + float cwx, cwy, a = parent._a, b = parent._b, c = parent._c, d = parent._d; + bool u = MathUtil::abs(psx - psy) <= 0.0001f; if (!u || stretch) { - cy = 0; - cwx = parent._a * cx + parent._worldX; - cwy = parent._c * cx + parent._worldY; + child._y = 0; + cwx = a * child._x + parent._worldX; + cwy = c * child._x + parent._worldY; } else { - cy = child._ay; - cwx = parent._a * cx + parent._b * cy + parent._worldX; - cwy = parent._c * cx + parent._d * cy + parent._worldY; + cwx = a * child._x + b * child._y + parent._worldX; + cwy = c * child._x + d * child._y + parent._worldY; } - a = pp->_a; - b = pp->_b; - c = pp->_c; - d = pp->_d; - id = a * d - b * c; + BonePose& pp = parent._bone->getParent()->getAppliedPose(); + a = pp._a; + b = pp._b; + c = pp._c; + d = pp._d; + float id = a * d - b * c, x = cwx - pp._worldX, y = cwy - pp._worldY; id = MathUtil::abs(id) <= 0.0001f ? 0 : 1 / id; - x = cwx - pp->_worldX; - y = cwy - pp->_worldY; - dx = (x * d - y * b) * id - px; - dy = (y * a - x * c) * id - py; - l1 = MathUtil::sqrt(dx * dx + dy * dy); - l2 = child._data.getLength() * csx; - if (l1 < 0.0001) { - apply(parent, targetX, targetY, false, stretch, false, alpha); - child.updateWorldTransform(cx, cy, 0, child._ascaleX, child._ascaleY, child._ashearX, child._ashearY); + float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + float l1 = MathUtil::sqrt(dx * dx + dy * dy), l2 = child._bone->getData().getLength() * csx, a1, a2; + if (l1 < 0.0001f) { + apply(skeleton, parent, targetX, targetY, false, stretch, false, mix); + child._rotation = 0; return; } - x = targetX - pp->_worldX; - y = targetY - pp->_worldY; - tx = (x * d - y * b) * id - px; - ty = (y * a - x * c) * id - py; - dd = tx * tx + ty * ty; + x = targetX - pp._worldX; + y = targetY - pp._worldY; + float tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + float dd = tx * tx + ty * ty; if (softness != 0) { softness *= psx * (csx + 1) * 0.5f; - td = MathUtil::sqrt(dd); - sd = td - l1 - l2 * psx + softness; + float td = MathUtil::sqrt(dd), sd = td - l1 - l2 * psx + softness; if (sd > 0) { - p = MathUtil::min(1.0f, sd / (softness * 2)) - 1; + float p = MathUtil::min(1.0f, sd / (softness * 2)) - 1; p = (sd - softness * (1 - p * p)) / td; tx -= p * tx; ty -= p * ty; dd = tx * tx + ty * ty; } } + outer: if (u) { - float cosine; l2 *= psx; - cosine = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); - if (cosine < -1) { - cosine = -1; + float cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) { + cos = -1; a2 = MathUtil::Pi * bendDir; - } else if (cosine > 1) { - cosine = 1; + } else if (cos > 1) { + cos = 1; a2 = 0; if (stretch) { - a = (MathUtil::sqrt(dd) / (l1 + l2) - 1) * alpha + 1; - sx *= a; - if (uniform) sy *= a; + a = (MathUtil::sqrt(dd) / (l1 + l2) - 1) * mix + 1; + parent._scaleX *= a; + if (uniform) parent._scaleY *= a; } } else - a2 = MathUtil::acos(cosine) * bendDir; - a = l1 + l2 * cosine; + a2 = MathUtil::acos(cos) * bendDir; + a = l1 + l2 * cos; b = l2 * MathUtil::sin(a2); a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b); } else { a = psx * l2; b = psy * l2; - float aa = a * a, bb = b * b, ll = l1 * l1, ta = MathUtil::atan2(ty, tx); - float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa; - d = c1 * c1 - 4 * c2 * c0; + float aa = a * a, bb = b * b, ta = MathUtil::atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + float c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; if (d >= 0) { - float q = MathUtil::sqrt(d), r0, r1; + float q = MathUtil::sqrt(d); if (c1 < 0) q = -q; q = -(c1 + q) * 0.5f; - r0 = q / c2; - r1 = c0 / q; - r = MathUtil::abs(r0) < MathUtil::abs(r1) ? r0 : r1; - if (dd - r * r >= 0) { - y = MathUtil::sqrt(dd - r * r) * bendDir; + float r0 = q / c2, r1 = c / q; + float r = MathUtil::abs(r0) < MathUtil::abs(r1) ? r0 : r1; + r0 = dd - r * r; + if (r0 >= 0) { + y = MathUtil::sqrt(r0) * bendDir; a1 = ta - MathUtil::atan2(y, r); a2 = MathUtil::atan2(y / psy, (r - l1) / psx); - goto break_outer; + goto outer_break; } } - { - float minAngle = MathUtil::Pi, minX = l1 - a, minDist = minX * minX, minY = 0; - float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; - c0 = -a * l1 / (aa - bb); - if (c0 >= -1 && c0 <= 1) { - c0 = MathUtil::acos(c0); - x = a * MathUtil::cos(c0) + l1; - y = b * MathUtil::sin(c0); - d = x * x + y * y; - if (d < minDist) { - minAngle = c0; - minDist = d; - minX = x; - minY = y; - } - if (d > maxDist) { - maxAngle = c0; - maxDist = d; - maxX = x; - maxY = y; - } + float minAngle = MathUtil::Pi, minX = l1 - a, minDist = minX * minX, minY = 0; + float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = MathUtil::acos(c); + x = a * MathUtil::cos(c) + l1; + y = b * MathUtil::sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; } - if (dd <= (minDist + maxDist) * 0.5f) { - a1 = ta - MathUtil::atan2(minY * bendDir, minX); - a2 = minAngle * bendDir; - } else { - a1 = ta - MathUtil::atan2(maxY * bendDir, maxX); - a2 = maxAngle * bendDir; + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; } } + if (dd <= (minDist + maxDist) * 0.5f) { + a1 = ta - MathUtil::atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - MathUtil::atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } } -break_outer : { - float os = MathUtil::atan2(cy, cx) * s2; - a1 = (a1 - os) * MathUtil::Rad_Deg + o1 - parent._arotation; - if (a1 > 180) a1 -= 360; - else if (a1 < -180) + outer_break: + float os = MathUtil::atan2(child._y, child._x) * s2; + a1 = (a1 - os) * MathUtil::Rad_Deg + os1 - parent._rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) // a1 += 360; - parent.updateWorldTransform(px, py, parent._arotation + a1 * alpha, sx, sy, 0, 0); - a2 = ((a2 + os) * MathUtil::Rad_Deg - child._ashearX) * s2 + o2 - child._arotation; - if (a2 > 180) a2 -= 360; - else if (a2 < -180) + parent._rotation += a1 * mix; + a2 = ((a2 + os) * MathUtil::Rad_Deg - child._shearX) * s2 + os2 - child._rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) // a2 += 360; - child.updateWorldTransform(cx, cy, child._arotation + a2 * alpha, child._ascaleX, child._ascaleY, - child._ashearX, child._ashearY); -} + child._rotation += a2 * mix; } -IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatable(), - _data(data), - _bendDirection(data.getBendDirection()), - _compress(data.getCompress()), - _stretch(data.getStretch()), - _mix(data.getMix()), - _softness(data.getSoftness()), - _target(skeleton.findBone( - 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]; - _bones.add(skeleton.findBone(boneData->getName())); +IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : + Constraint(data), + _target(skeleton.findBone(data.getTarget()->getName())) { + + _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()); } } -void IkConstraint::update(Physics) { - if (_mix == 0) return; +void IkConstraint::update(Skeleton& skeleton, Physics physics) { + IkConstraintPose& p = *_applied; + if (p._mix == 0) return; + BonePose& target = _target->getAppliedPose(); switch (_bones.size()) { case 1: { - Bone *bone0 = _bones[0]; - apply(*bone0, _target->getWorldX(), _target->getWorldY(), _compress, _stretch, _data._uniform, _mix); + apply(skeleton, *_bones[0], target._worldX, target._worldY, p._compress, p._stretch, _data._uniform, p._mix); } break; case 2: { - Bone *bone0 = _bones[0]; - Bone *bone1 = _bones[1]; - apply(*bone0, *bone1, _target->getWorldX(), _target->getWorldY(), _bendDirection, _stretch, _data._uniform, - _softness, - _mix); + apply(skeleton, *_bones[0], *_bones[1], target._worldX, target._worldY, p._bendDirection, p._stretch, _data._uniform, + p._softness, p._mix); } break; } } -int IkConstraint::getOrder() { - return (int) _data.getOrder(); -} IkConstraintData &IkConstraint::getData() { return _data; } -Vector &IkConstraint::getBones() { +Vector &IkConstraint::getBones() { return _bones; } @@ -317,63 +288,27 @@ Bone *IkConstraint::getTarget() { return _target; } -void IkConstraint::setTarget(Bone *inValue) { - _target = inValue; +void IkConstraint::setTarget(Bone *target) { + _target = target; } -int IkConstraint::getBendDirection() { - return _bendDirection; +void IkConstraint::sort(Skeleton& skeleton) { + skeleton.sortBone(_target); + Bone* parent = _bones[0]->_bone; + skeleton.sortBone(parent); + skeleton.updateCache.add(this); + parent->_sorted = false; + skeleton.sortReset(parent->_children); + skeleton.constrained(parent); + if (_bones.size() > 1) skeleton.constrained(_bones[1]->_bone); } -void IkConstraint::setBendDirection(int inValue) { - _bendDirection = inValue; +bool IkConstraint::isSourceActive() { + return _target->_active; } -float IkConstraint::getMix() { - return _mix; -} - -void IkConstraint::setMix(float inValue) { - _mix = inValue; -} - -bool IkConstraint::getStretch() { - return _stretch; -} - -void IkConstraint::setStretch(bool inValue) { - _stretch = inValue; -} - -bool IkConstraint::getCompress() { - return _compress; -} - -void IkConstraint::setCompress(bool inValue) { - _compress = inValue; -} - -bool IkConstraint::isActive() { - return _active; -} - -void IkConstraint::setActive(bool inValue) { - _active = inValue; -} - -float IkConstraint::getSoftness() { - return _softness; -} - -void IkConstraint::setSoftness(float inValue) { - _softness = inValue; -} - -void IkConstraint::setToSetupPose() { - IkConstraintData &data = this->_data; - this->_mix = data._mix; - this->_softness = data._softness; - this->_bendDirection = data._bendDirection; - this->_compress = data._compress; - this->_stretch = data._stretch; +IkConstraint* IkConstraint::copy(Skeleton& skeleton) { + IkConstraint* copy = new IkConstraint(_data, skeleton); + copy->_pose.set(_pose); + return copy; }