diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h index 07f9257fd..38e8c2565 100644 --- a/spine-cpp/spine-cpp/include/spine/Animation.h +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -48,6 +48,7 @@ namespace spine { class AnimationState; + /// Stores a list of timelines to animate a skeleton's pose over time. class SP_API Animation : public SpineObject { friend class AnimationState; @@ -97,35 +98,58 @@ namespace spine { friend class TwoColorTimeline; + friend class Slider; + public: Animation(const String &name, Vector &timelines, float duration); ~Animation(); - /// Applies all the animation's timelines to the specified skeleton. - /// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection) - void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector *pEvents, float alpha, - MixBlend blend, MixDirection direction, bool appliedPose); - - const String &getName(); - + /// If the returned array or the timelines it contains are modified, setTimelines() must be called. Vector &getTimelines(); void setTimelines(Vector &timelines); + /// Returns true if this animation contains a timeline with any of the specified property IDs. bool hasTimeline(Vector &ids); + /// The duration of the animation in seconds, which is usually the highest time of all frames in the timeline. The duration is + /// used to know when it has completed and when it should loop back to the start. float getDuration(); void setDuration(float inValue); + /// Applies the animation's timelines to the specified skeleton. + /// + /// See Timeline::apply(). + /// @param skeleton The skeleton the animation is being applied to. This provides access to the bones, slots, and other skeleton + /// components the timelines may change. + /// @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at specific times rather + /// than every frame. Pass -1 the first time an animation is applied to ensure frame 0 is triggered. + /// @param time The time in seconds the skeleton is being posed for. Most timelines find the frame before and the frame after + /// this time and interpolate between the frame values. If beyond the getDuration() and loop is + /// true then the animation will repeat, else the last frame will be applied. + /// @param loop If true, the animation repeats after the getDuration(). + /// @param events If any events are fired, they are added to this list. Can be null to ignore fired events or if no timelines + /// fire events. + /// @param alpha 0 applies the current or setup values (depending on blend). 1 applies the timeline values. Between + /// 0 and 1 applies values between the current or setup values and the timeline values. By adjusting + /// alpha over time, an animation can be mixed in or out. alpha can also be useful to apply + /// animations on top of each other (layering). + /// @param blend Controls how mixing is applied when alpha < 1. + /// @param direction Indicates whether the timelines are mixing in or out. Used by timelines which perform instant transitions, + /// such as DrawOrderTimeline or AttachmentTimeline. + void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector *pEvents, float alpha, + MixBlend blend, MixDirection direction, bool appliedPose); + + /// The animation's name, which is unique across all animations in the skeleton. + const String &getName(); + /// @param target After the first and before the last entry. static int search(Vector &values, float target); static int search(Vector &values, float target, int step); - - Vector &getBones(); - private: + protected: Vector _timelines; HashMap _timelineIds; Vector _bones; diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index b42b28d04..354ecabb8 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -52,6 +52,7 @@ namespace spine { friend class PathConstraint; friend class PhysicsConstraint; friend class Skeleton; + friend class Slider; friend class RegionAttachment; friend class PointAttachment; friend class AttachmentTimeline; @@ -83,7 +84,11 @@ namespace spine { /// The immediate children of this bone. Vector& getChildren(); + static bool isYDown() { return yDown; } + static void setYDown(bool value) { yDown = value; } + private: + static bool yDown; Bone* const _parent; Vector _children; bool _sorted; diff --git a/spine-cpp/spine-cpp/include/spine/BoneLocal.h b/spine-cpp/spine-cpp/include/spine/BoneLocal.h index 15b133d78..b74014811 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneLocal.h +++ b/spine-cpp/spine-cpp/include/spine/BoneLocal.h @@ -51,6 +51,21 @@ namespace spine { friend class TranslateTimeline; friend class TranslateXTimeline; friend class TranslateYTimeline; + friend class Skeleton; + friend class FromProperty; + friend class ToProperty; + friend class FromRotate; + friend class ToRotate; + friend class FromX; + friend class ToX; + friend class FromY; + friend class ToY; + friend class FromScaleX; + friend class ToScaleX; + friend class FromScaleY; + friend class ToScaleY; + friend class FromShearY; + friend class ToShearY; protected: float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; diff --git a/spine-cpp/spine-cpp/include/spine/Constraint.h b/spine-cpp/spine-cpp/include/spine/Constraint.h index 664129a13..526ced4d8 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 { class SP_API Constraint : public Update { RTTI_DECL_NOPARENT friend class Skeleton; - + public: Constraint(); virtual ~Constraint(); @@ -54,12 +54,14 @@ namespace spine { virtual bool isSourceActive() { return true; } - + virtual void pose() = 0; + virtual void setupPose() = 0; + // Inherited from Update virtual void update(Skeleton &skeleton, Physics physics) override = 0; - + protected: bool _active; }; @@ -74,14 +76,18 @@ namespace spine { virtual ~ConstraintGeneric() { } - + virtual ConstraintData &getData() override { return PosedGeneric::getData(); } - + virtual void pose() override { PosedGeneric::pose(); } + + virtual void setupPose() override { + PosedGeneric::setupPose(); + } }; }// namespace spine diff --git a/spine-cpp/spine-cpp/include/spine/ConstraintData.h b/spine-cpp/spine-cpp/include/spine/ConstraintData.h index af775b23b..3ddfbadbc 100644 --- a/spine-cpp/spine-cpp/include/spine/ConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/ConstraintData.h @@ -32,25 +32,42 @@ #include #include +#include #include namespace spine { class Skeleton; class Constraint; - /// Base class for all constraint data types. class SP_API ConstraintData : public SpineObject { - public: RTTI_DECL_NOPARENT - ConstraintData(const String &name); - virtual ~ConstraintData(); - const String &getName() const; + friend class Skeleton; + friend class Constraint; + + public: + ConstraintData(const String &name) : SpineObject(name) {} + virtual ~ConstraintData() {} virtual Constraint* create(Skeleton& skeleton) = 0; - private: - String _name; + virtual const String &getName() const = 0; + + virtual const bool &isSkinRequired() const = 0; + }; + + /// Base class for all constraint data types. + template + class SP_API ConstraintDataGeneric: public PosedDataGeneric

, public ConstraintData { + public: + ConstraintDataGeneric(const String &name) : PosedDataGeneric

(name), ConstraintData(name) {} + virtual ~ConstraintDataGeneric() {} + + virtual Constraint* create(Skeleton& skeleton) = 0; + + // Resolve ambiguity by forwarding to PosedData's implementation + virtual const String &getName() const override { return PosedDataGeneric

::getName(); } + virtual const bool &isSkinRequired() const override { return PosedDataGeneric

::isSkinRequired(); } }; } -#endif /* Spine_ConstraintData_h */ +#endif /* Spine_ConstraintData_h */ \ No newline at end of file diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index 1ec848f6e..fefdcd008 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -49,6 +49,24 @@ namespace spine { RTTI_DECL public: + IkConstraint(IkConstraintData &data, Skeleton &skeleton); + + virtual IkConstraint* copy(Skeleton& skeleton); + + virtual void update(Skeleton& skeleton, Physics physics) override; + + virtual void sort(Skeleton& skeleton) override; + + virtual bool isSourceActive() override; + + IkConstraintData &getData(); + + Vector &getBones(); + + Bone *getTarget(); + + void setTarget(Bone *inValue); + /// 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 @@ -61,24 +79,6 @@ namespace spine { 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(Skeleton& skeleton, Physics physics) override; - - virtual void sort(Skeleton& skeleton) override; - - virtual bool isSourceActive() override; - - virtual IkConstraint* copy(Skeleton& skeleton); - - IkConstraintData &getData(); - - Vector &getBones(); - - Bone *getTarget(); - - void setTarget(Bone *inValue); - private: Vector _bones; Bone *_target; diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index 6eecedec4..5d90d7006 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -41,7 +41,7 @@ namespace spine { class BoneData; class IkConstraint; - class SP_API IkConstraintData : public ConstraintData, public PosedDataGeneric { + class SP_API IkConstraintData : public ConstraintDataGeneric { friend class SkeletonBinary; friend class SkeletonJson; @@ -56,7 +56,7 @@ namespace spine { public: explicit IkConstraintData(const String &name); - + virtual Constraint* create(Skeleton& skeleton) override; /// The bones that are constrained by this IK Constraint. diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index 85498a0d5..94fb65f52 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -48,7 +48,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, public PosedDataGeneric { + class SP_API PathConstraintData : public ConstraintDataGeneric { friend class SkeletonBinary; friend class SkeletonJson; @@ -67,7 +67,7 @@ namespace spine { public: explicit PathConstraintData(const String &name); - + virtual Constraint* create(Skeleton& skeleton) override; diff --git a/spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h b/spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h index ca20318b8..48a8ceb0f 100644 --- a/spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h @@ -66,14 +66,14 @@ namespace spine { bool isSourceActive() override; PhysicsConstraint* copy(Skeleton& skeleton); + void reset(Skeleton& skeleton); + /// Translates the physics constraint so next update() forces are applied as if the bone moved an additional amount in world space. void translate(float x, float y); /// Rotates the physics constraint so next update() forces are applied as if the bone rotated around the specified point in world space. void rotate(float x, float y, float degrees); - void reset(Skeleton& skeleton); - /// The bone constrained by this physics constraint. BonePose& getBone(); void setBone(BonePose& bone); diff --git a/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h b/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h index d53f30644..2e9386922 100644 --- a/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h @@ -41,7 +41,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, public PosedDataGeneric { + class SP_API PhysicsConstraintData : public ConstraintDataGeneric { friend class SkeletonBinary; friend class SkeletonJson; friend class PhysicsConstraint; diff --git a/spine-cpp/spine-cpp/include/spine/Posed.h b/spine-cpp/spine-cpp/include/spine/Posed.h index 9104efd72..fd4699ce4 100644 --- a/spine-cpp/spine-cpp/include/spine/Posed.h +++ b/spine-cpp/spine-cpp/include/spine/Posed.h @@ -41,11 +41,13 @@ namespace spine { virtual void setupPose() = 0; - virtual void resetConstrained() = 0; - virtual void pose() = 0; virtual void constrained() = 0; + + virtual void resetConstrained() = 0; + + virtual bool isPoseEqualToApplied() const = 0; }; template @@ -78,6 +80,7 @@ namespace spine { friend class TranslateXTimeline; friend class TranslateYTimeline; friend class InheritTimeline; + friend class Skeleton; public: PosedGeneric(D &data) : _data(data), _pose(), _constrained(), _applied(&_pose) { @@ -117,6 +120,10 @@ namespace spine { _applied = &_constrained; } + virtual bool isPoseEqualToApplied() const override { + return _applied == &_pose; + } + protected: D &_data; A _pose; ///< Stored as A type (concrete pose type) to match Java behavior diff --git a/spine-cpp/spine-cpp/include/spine/PosedData.h b/spine-cpp/spine-cpp/include/spine/PosedData.h index 62ec893b3..172a1e5a6 100644 --- a/spine-cpp/spine-cpp/include/spine/PosedData.h +++ b/spine-cpp/spine-cpp/include/spine/PosedData.h @@ -59,6 +59,7 @@ namespace spine { friend class TranslateXTimeline; friend class TranslateYTimeline; friend class InheritTimeline; + friend class Skeleton; public: PosedData(const spine::String& name); diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index e1dede9d8..7d7af7619 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -250,6 +250,8 @@ namespace spine { void setColor(Color &color); + void setColor(float r, float g, float b, float a); + float getScaleX(); void setScaleX(float inValue); diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h index 52b868a86..b955c087f 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -35,26 +35,26 @@ namespace spine { class Slot; - + class Skeleton; class ClippingAttachment; class SP_API SkeletonClipping : public SpineObject { public: SkeletonClipping(); - size_t clipStart(Slot &slot, ClippingAttachment *clip); + size_t clipStart(Skeleton &skeleton, Slot &slot, ClippingAttachment *clip); void clipEnd(Slot &slot); void clipEnd(); - void + bool clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength); - void + bool clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength, float *uvs, size_t stride); - void + bool clipTriangles(Vector &vertices, Vector &triangles, Vector &uvs, size_t stride); bool isClipping(); diff --git a/spine-cpp/spine-cpp/include/spine/SliderData.h b/spine-cpp/spine-cpp/include/spine/SliderData.h index ad53a898d..48286b3c7 100644 --- a/spine-cpp/spine-cpp/include/spine/SliderData.h +++ b/spine-cpp/spine-cpp/include/spine/SliderData.h @@ -45,7 +45,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 SliderData : public ConstraintData, public PosedDataGeneric { + class SP_API SliderData : public ConstraintDataGeneric { friend class SkeletonBinary; friend class SkeletonJson; friend class Slider; @@ -76,6 +76,9 @@ namespace spine { float getScale(); void setScale(float scale); + float getOffset(); + void setOffset(float offset); + bool getLocal(); void setLocal(bool local); @@ -85,6 +88,7 @@ namespace spine { bool _loop; BoneData* _bone; FromProperty* _property; + float _offset; float _scale; bool _local; }; diff --git a/spine-cpp/spine-cpp/include/spine/SliderPose.h b/spine-cpp/spine-cpp/include/spine/SliderPose.h index 4ed4d3221..1877fa422 100644 --- a/spine-cpp/spine-cpp/include/spine/SliderPose.h +++ b/spine-cpp/spine-cpp/include/spine/SliderPose.h @@ -34,8 +34,11 @@ #include namespace spine { + class Slider; + /// Stores a pose for a slider. class SP_API SliderPose : public Pose { + friend class Slider; private: float _time, _mix; diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h index 3cc2a50eb..34850502f 100644 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -97,7 +97,7 @@ namespace spine { /// The bone this slot belongs to. Bone &getBone(); - void setupPose(); + void setupPose() override; private: Skeleton &_skeleton; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index 4d268902b..1fe31113d 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -49,7 +49,7 @@ namespace spine { public: TransformConstraint(TransformConstraintData& data, Skeleton& skeleton); - TransformConstraint copy(Skeleton& skeleton); + virtual TransformConstraint* copy(Skeleton& skeleton); /// Applies the constraint to the constrained bones. void update(Skeleton& skeleton, Physics physics) override; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index 0d3fa8ea1..9fae5db23 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -55,7 +55,7 @@ namespace spine { virtual ~FromProperty(); /// Reads this property from the specified bone. - virtual float value(BonePose& source, bool local, float* offsets) = 0; + virtual float value(Skeleton& skeleton, BonePose& source, bool local, float* offsets) = 0; }; /// Constrained property for a TransformConstraint. @@ -78,79 +78,79 @@ namespace spine { virtual float mix(TransformConstraintPose& pose) = 0; /// Applies the value to this property. - virtual void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) = 0; + virtual void apply(Skeleton& skeleton, TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) = 0; }; class SP_API FromRotate : public FromProperty { public: - float value(BonePose& source, bool local, float* offsets) override; + float value(Skeleton &skeleton, BonePose& source, bool local, float* offsets) override; }; class SP_API ToRotate : public ToProperty { public: float mix(TransformConstraintPose& pose) override; - void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; + void apply(Skeleton &skeleton, TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; class SP_API FromX : public FromProperty { public: - float value(BonePose& source, bool local, float* offsets) override; + float value(Skeleton &skeleton, BonePose& source, bool local, float* offsets) override; }; class SP_API ToX : public ToProperty { public: float mix(TransformConstraintPose& pose) override; - void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; + void apply(Skeleton &skeleton, TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; class SP_API FromY : public FromProperty { public: - float value(BonePose& source, bool local, float* offsets) override; + float value(Skeleton &skeleton, BonePose& source, bool local, float* offsets) override; }; class SP_API ToY : public ToProperty { public: float mix(TransformConstraintPose& pose) override; - void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; + void apply(Skeleton &skeleton, TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; class SP_API FromScaleX : public FromProperty { public: - float value(BonePose& source, bool local, float* offsets) override; + float value(Skeleton &skeleton, BonePose& source, bool local, float* offsets) override; }; class SP_API ToScaleX : public ToProperty { public: float mix(TransformConstraintPose& pose) override; - void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; + void apply(Skeleton &skeleton, TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; class SP_API FromScaleY : public FromProperty { public: - float value(BonePose& source, bool local, float* offsets) override; + float value(Skeleton &skeleton, BonePose& source, bool local, float* offsets) override; }; class SP_API ToScaleY : public ToProperty { public: float mix(TransformConstraintPose& pose) override; - void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; + void apply(Skeleton &skeleton, TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; class SP_API FromShearY : public FromProperty { public: - float value(BonePose& source, bool local, float* offsets) override; + float value(Skeleton &skeleton, BonePose& source, bool local, float* offsets) override; }; class SP_API ToShearY : public ToProperty { public: float mix(TransformConstraintPose& pose) override; - void apply(TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; + void apply(Skeleton &skeleton, TransformConstraintPose& pose, BonePose& bone, float value, bool local, bool additive) override; }; /// 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, public PosedDataGeneric { + class SP_API TransformConstraintData : public ConstraintDataGeneric { public: RTTI_DECL static const int ROTATION = 0, X = 1, Y = 2, SCALEX = 3, SCALEY = 4, SHEARY = 5; @@ -163,7 +163,7 @@ namespace spine { public: explicit TransformConstraintData(const String &name); ~TransformConstraintData(); - + virtual Constraint* create(Skeleton& skeleton) override; /// The bones that will be modified by this transform constraint. diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintPose.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintPose.h index 5216ada97..796603a0c 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintPose.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintPose.h @@ -50,6 +50,7 @@ namespace spine { friend class ToScaleY; friend class FromShearY; friend class ToShearY; + friend class TransformConstraint; private: float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY; diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 1b9f6effa..c3d64eacd 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -36,6 +36,8 @@ using namespace spine; RTTI_IMPL_NOPARENT(Bone) +bool Bone::yDown = true; + Bone::Bone(BoneData &data, Bone *parent) : PosedGeneric(data), PosedActive(), _parent(parent), diff --git a/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp index 64a60d202..b8fee7229 100644 --- a/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/ConstraintData.cpp @@ -31,14 +31,4 @@ 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 +RTTI_IMPL_NOPARENT(ConstraintData) \ No newline at end of file diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index 71252d577..64a7a885b 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -41,22 +41,84 @@ using namespace spine; RTTI_IMPL(IkConstraint, Constraint) +IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : ConstraintGeneric(data), + _target(skeleton._bones[data._target->getIndex()]) { + + _bones.ensureCapacity(data._bones.size()); + for (size_t i = 0; i < data._bones.size(); i++) { + BoneData *boneData = data._bones[i]; + _bones.add(&skeleton._bones[boneData->getIndex()]->_constrained); + } +} + +IkConstraint *IkConstraint::copy(Skeleton &skeleton) { + IkConstraint *copy = new (__FILE__, __LINE__) IkConstraint(_data, skeleton); + copy->_pose.set(_pose); + return copy; +} + +void IkConstraint::update(Skeleton &skeleton, Physics physics) { + IkConstraintPose &p = _pose; + if (p._mix == 0) return; + BonePose &target = *_target->_applied; + switch (_bones.size()) { + case 1: { + apply(skeleton, *_bones[0], target._worldX, target._worldY, p._compress, p._stretch, _data._uniform, p._mix); + } break; + case 2: { + apply(skeleton, *_bones[0], *_bones[1], target._worldX, target._worldY, p._bendDirection, p._stretch, _data._uniform, + p._softness, p._mix); + } break; + } +} + +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); +} + +IkConstraintData &IkConstraint::getData() { + return _data; +} + +Vector &IkConstraint::getBones() { + return _bones; +} + +Bone *IkConstraint::getTarget() { + return _target; +} + +void IkConstraint::setTarget(Bone *target) { + _target = target; +} + +bool IkConstraint::isSourceActive() { + return _target->_active; +} + 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(); + BonePose &p = *bone._bone->_parent->_applied; 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(skeleton.getScaleX()); - ty = (targetY - bone._worldY) * MathUtil::sign(skeleton.getScaleY()); + tx = (targetX - bone._worldX) * MathUtil::sign(skeleton._scaleX); + ty = (targetY - bone._worldY) * MathUtil::sign(skeleton._scaleY); 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(); + float sa = pa / skeleton._scaleX; + float sc = pc / skeleton._scaleY; + pb = -sc * s * skeleton._scaleX; + pd = sa * s * skeleton._scaleY; rotationIK += MathUtil::atan2Deg(sc, sa); // Fall through. } @@ -88,7 +150,7 @@ void IkConstraint::apply(Skeleton &skeleton, BonePose &bone, float targetX, floa default: break; } - float b = bone._bone->getData().getLength() * bone._scaleX; + float b = bone._bone->_data.getLength() * bone._scaleX; if (b > 0.0001f) { float dd = tx * tx + ty * ty; if ((compress && dd < b * b) || (stretch && dd > b * b)) { @@ -134,7 +196,7 @@ void IkConstraint::apply(Skeleton &skeleton, BonePose &parent, BonePose &child, cwx = a * child._x + b * child._y + parent._worldX; cwy = c * child._x + d * child._y + parent._worldY; } - BonePose &pp = parent._bone->getParent()->getAppliedPose(); + BonePose &pp = *parent._bone->_parent->_applied; a = pp._a; b = pp._b; c = pp._c; @@ -142,7 +204,7 @@ void IkConstraint::apply(Skeleton &skeleton, BonePose &parent, BonePose &child, float id = a * d - b * c, x = cwx - pp._worldX, y = cwy - pp._worldY; id = MathUtil::abs(id) <= 0.0001f ? 0 : 1 / id; 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; + float l1 = MathUtil::sqrt(dx * dx + dy * dy), l2 = child._bone->_data.getLength() * csx, a1, a2; if (l1 < 0.0001f) { apply(skeleton, parent, targetX, targetY, false, stretch, false, mix); child._rotation = 0; @@ -163,7 +225,7 @@ void IkConstraint::apply(Skeleton &skeleton, BonePose &parent, BonePose &child, dd = tx * tx + ty * ty; } } -outer: + if (u) { l2 *= psx; float cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); @@ -249,65 +311,3 @@ outer_break: child._rotation += a2 * mix; } -IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : ConstraintGeneric(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(Skeleton &skeleton, Physics physics) { - IkConstraintPose &p = *_applied; - if (p._mix == 0) return; - BonePose &target = _target->getAppliedPose(); - switch (_bones.size()) { - case 1: { - apply(skeleton, *_bones[0], target._worldX, target._worldY, p._compress, p._stretch, _data._uniform, p._mix); - } break; - case 2: { - apply(skeleton, *_bones[0], *_bones[1], target._worldX, target._worldY, p._bendDirection, p._stretch, _data._uniform, - p._softness, p._mix); - } break; - } -} - - -IkConstraintData &IkConstraint::getData() { - return _data; -} - -Vector &IkConstraint::getBones() { - return _bones; -} - -Bone *IkConstraint::getTarget() { - return _target; -} - -void IkConstraint::setTarget(Bone *target) { - _target = target; -} - -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); -} - -bool IkConstraint::isSourceActive() { - return _target->_active; -} - -IkConstraint *IkConstraint::copy(Skeleton &skeleton) { - IkConstraint *copy = new IkConstraint(_data, skeleton); - copy->_pose.set(_pose); - return copy; -} diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index 889b3f9a9..9c57405e3 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -36,8 +36,7 @@ using namespace spine; RTTI_IMPL(IkConstraintData, ConstraintData) -IkConstraintData::IkConstraintData(const String &name) : ConstraintData(name), - PosedDataGeneric(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 8722684a4..ea6e230b4 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -37,8 +37,7 @@ using namespace spine; RTTI_IMPL(PathConstraintData, ConstraintData) -PathConstraintData::PathConstraintData(const String &name) : ConstraintData(name), - PosedDataGeneric(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/PhysicsConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PhysicsConstraint.cpp index 83cc9dc1e..89b97277e 100644 --- a/spine-cpp/spine-cpp/src/spine/PhysicsConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PhysicsConstraint.cpp @@ -47,35 +47,15 @@ PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData &data, Skeleton &skel _rotateOffset(0), _rotateLag(0), _rotateVelocity(0), _scaleOffset(0), _scaleLag(0), _scaleVelocity(0), _remaining(0), _lastTime(0) { - _bone = &skeleton.getBones()[(size_t) data.getBone()->getIndex()]->getAppliedPose(); + _bone = &skeleton._bones[(size_t) data._bone->getIndex()]->_constrained; } PhysicsConstraint *PhysicsConstraint::copy(Skeleton &skeleton) { PhysicsConstraint *copy = new (__FILE__, __LINE__) PhysicsConstraint(_data, skeleton); - copy->_applied->set(*_applied); + copy->_pose.set(_pose); return copy; } -void PhysicsConstraint::sort(Skeleton &skeleton) { - Bone *bone = _bone->_bone; - skeleton.sortBone(bone); - skeleton._updateCache.add(this); - skeleton.sortReset(bone->_children); - skeleton.constrained(*bone); -} - -bool PhysicsConstraint::isSourceActive() { - return _bone->_bone->isActive(); -} - -BonePose &PhysicsConstraint::getBone() { - return *_bone; -} - -void PhysicsConstraint::setBone(BonePose &bone) { - _bone = &bone; -} - void PhysicsConstraint::reset(Skeleton &skeleton) { _remaining = 0; _lastTime = skeleton.getTime(); @@ -94,14 +74,27 @@ void PhysicsConstraint::reset(Skeleton &skeleton) { _scaleVelocity = 0; } +void PhysicsConstraint::translate(float x, float y) { + _ux -= x; + _uy -= y; + _cx -= x; + _cy -= y; +} + +void PhysicsConstraint::rotate(float x, float y, float degrees) { + float r = degrees * MathUtil::Deg_Rad, cosVal = MathUtil::cos(r), sinVal = MathUtil::sin(r); + float dx = _cx - x, dy = _cy - y; + translate(dx * cosVal - dy * sinVal - dx, dx * sinVal + dy * cosVal - dy); +} + void PhysicsConstraint::update(Skeleton &skeleton, Physics physics) { - PhysicsConstraintPose &p = *_applied; - float mix = p.getMix(); + PhysicsConstraintPose &p = _pose; + float mix = p._mix; if (mix == 0) return; - bool x = _data.getX() > 0, y = _data.getY() > 0, rotateOrShearX = _data._rotate > 0 || _data._shearX > 0, scaleX = _data.getScaleX() > 0; + bool x = _data._x > 0, y = _data._y > 0, rotateOrShearX = _data._rotate > 0 || _data._shearX > 0, scaleX = _data._scaleX > 0; BonePose *bone = _bone; - float l = bone->_bone->getData().getLength(), t = _data.getStep(), z = 0; + float l = bone->_bone->_data.getLength(), t = _data._step, z = 0; switch (physics) { case Physics_None: @@ -110,9 +103,9 @@ void PhysicsConstraint::update(Skeleton &skeleton, Physics physics) { reset(skeleton); // Fall through. case Physics_Update: { - float delta = MathUtil::max(skeleton.getTime() - _lastTime, 0.0f), aa = _remaining; + float delta = MathUtil::max(skeleton._time - _lastTime, 0.0f), aa = _remaining; _remaining += delta; - _lastTime = skeleton.getTime(); + _lastTime = skeleton._time; float bx = bone->_worldX, by = bone->_worldY; if (_reset) { @@ -120,9 +113,9 @@ void PhysicsConstraint::update(Skeleton &skeleton, Physics physics) { _ux = bx; _uy = by; } else { - float a = _remaining, i = p.getInertia(), f = skeleton.getData()->getReferenceScale(), d = -1, m = 0, e = 0, qx = _data.getLimit() * delta, - qy = qx * MathUtil::abs(skeleton.getScaleY()); - qx *= MathUtil::abs(skeleton.getScaleX()); + float a = _remaining, i = p._inertia, f = skeleton._data.getReferenceScale(), d = -1, m = 0, e = 0, ax = 0, ay = 0, + qx = _data._limit * delta, qy = qx * MathUtil::abs(skeleton.getScaleY()); + qx *= MathUtil::abs(skeleton._scaleX); if (x || y) { if (x) { float u = (_ux - bx) * i; @@ -141,8 +134,9 @@ void PhysicsConstraint::update(Skeleton &skeleton, Physics physics) { d = MathUtil::pow(p._damping, 60 * t); m = t * p._massInverse; e = p._strength; - float w = f * p._wind * skeleton.getScaleX(), g = f * p._gravity * skeleton.getScaleY(), - ax = w * skeleton.getWindX() + g * skeleton.getGravityX(), ay = w * skeleton.getWindY() + g * skeleton.getGravityY(); + float w = f * p._wind, g = f * p._gravity; + ax = (w * skeleton._windX + g * skeleton._gravityX) * skeleton._scaleX; + ay = (w * skeleton._windY + g * skeleton._gravityY) * skeleton.getScaleY(); do { if (x) { _xVelocity += (ax - _xOffset * e) * m; @@ -197,10 +191,11 @@ void PhysicsConstraint::update(Skeleton &skeleton, Physics physics) { d = MathUtil::pow(p._damping, 60 * t); m = t * p._massInverse; e = p._strength; + float w = f * p._wind, g = f * p._gravity; + ax = (w * skeleton._windX + g * skeleton._gravityX) * skeleton._scaleX; + ay = (w * skeleton._windY + g * skeleton._gravityY) * skeleton.getScaleY(); } - float rs = _rotateOffset, ss = _scaleOffset, h = l / f, - ax = p._wind * skeleton.getWindX() + p._gravity * skeleton.getGravityX(), - ay = p._wind * skeleton.getWindY() + p._gravity * skeleton.getGravityY(); + float rs = _rotateOffset, ss = _scaleOffset, h = l / f; while (true) { a -= t; if (scaleX) { @@ -277,18 +272,25 @@ void PhysicsConstraint::update(Skeleton &skeleton, Physics physics) { _tx = l * bone->_a; _ty = l * bone->_c; } - // bone->modifyWorld(skeleton.getUpdate()); // TODO: Implement getUpdate method in Skeleton + bone->modifyWorld(skeleton._update); } -void PhysicsConstraint::translate(float x, float y) { - _ux -= x; - _uy -= y; - _cx -= x; - _cy -= y; +void PhysicsConstraint::sort(Skeleton &skeleton) { + Bone *bone = _bone->_bone; + skeleton.sortBone(bone); + skeleton._updateCache.add(this); + skeleton.sortReset(bone->_children); + skeleton.constrained(*bone); } -void PhysicsConstraint::rotate(float x, float y, float degrees) { - float r = degrees * MathUtil::Deg_Rad, cosVal = MathUtil::cos(r), sinVal = MathUtil::sin(r); - float dx = _cx - x, dy = _cy - y; - translate(dx * cosVal - dy * sinVal - dx, dx * sinVal + dy * cosVal - dy); +bool PhysicsConstraint::isSourceActive() { + return _bone->_bone->isActive(); +} + +BonePose &PhysicsConstraint::getBone() { + return *_bone; +} + +void PhysicsConstraint::setBone(BonePose &bone) { + _bone = &bone; } \ No newline at end of file diff --git a/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp index 1e71d3901..894f9d2bf 100644 --- a/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp @@ -36,8 +36,7 @@ using namespace spine; RTTI_IMPL(PhysicsConstraintData, ConstraintData) -PhysicsConstraintData::PhysicsConstraintData(const String &name) : ConstraintData(name), - PosedDataGeneric(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/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index 28996733a..2e86e53aa 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -57,75 +58,46 @@ using namespace spine; -Skeleton::Skeleton(SkeletonData *skeletonData) - : _data(skeletonData), _skin(NULL), _color(1, 1, 1, 1), _scaleX(1), - _scaleY(1), _x(0), _y(0), _time(0), _windX(1), _windY(0), _gravityX(0), _gravityY(1) { - _bones.ensureCapacity(_data->getBones().size()); - for (size_t i = 0; i < _data->getBones().size(); ++i) { - BoneData *data = _data->getBones()[i]; +Skeleton::Skeleton(SkeletonData &skeletonData) : _data(skeletonData), _skin(NULL), _color(1, 1, 1, 1), _x(0), _y(0), + _scaleX(1), _scaleY(1), _windX(1), _windY(0), _gravityX(0), _gravityY(1), _time(0), _update(0) { + + _bones.ensureCapacity(_data.getBones().size()); + for (size_t i = 0; i < _data.getBones().size(); ++i) { + BoneData *data = _data.getBones()[i]; Bone *bone; if (data->getParent() == NULL) { - bone = new (__FILE__, __LINE__) Bone(*data, *this, NULL); + bone = new (__FILE__, __LINE__) Bone(*data, NULL); } else { Bone *parent = _bones[data->getParent()->getIndex()]; - bone = new (__FILE__, __LINE__) Bone(*data, *this, parent); + bone = new (__FILE__, __LINE__) Bone(*data, parent); parent->getChildren().add(bone); } _bones.add(bone); } - _slots.ensureCapacity(_data->getSlots().size()); - _drawOrder.ensureCapacity(_data->getSlots().size()); - for (size_t i = 0; i < _data->getSlots().size(); ++i) { - SlotData *data = _data->getSlots()[i]; + _slots.ensureCapacity(_data.getSlots().size()); + _drawOrder.ensureCapacity(_data.getSlots().size()); + for (size_t i = 0; i < _data.getSlots().size(); ++i) { + SlotData *data = _data.getSlots()[i]; Bone *bone = _bones[data->getBoneData().getIndex()]; - Slot *slot = new (__FILE__, __LINE__) Slot(*data, *bone); + Slot *slot = new (__FILE__, __LINE__) Slot(*data, *this); _slots.add(slot); _drawOrder.add(slot); } - _ikConstraints.ensureCapacity(_data->getIkConstraints().size()); - for (size_t i = 0; i < _data->getIkConstraints().size(); ++i) { - IkConstraintData *data = _data->getIkConstraints()[i]; - - IkConstraint *constraint = - new (__FILE__, __LINE__) IkConstraint(*data, *this); - - _ikConstraints.add(constraint); - } - - _transformConstraints.ensureCapacity(_data->getTransformConstraints().size()); - for (size_t i = 0; i < _data->getTransformConstraints().size(); ++i) { - TransformConstraintData *data = _data->getTransformConstraints()[i]; - - TransformConstraint *constraint = - new (__FILE__, __LINE__) TransformConstraint(*data, *this); - - _transformConstraints.add(constraint); - } - - _pathConstraints.ensureCapacity(_data->getPathConstraints().size()); - for (size_t i = 0; i < _data->getPathConstraints().size(); ++i) { - PathConstraintData *data = _data->getPathConstraints()[i]; - - PathConstraint *constraint = - new (__FILE__, __LINE__) PathConstraint(*data, *this); - - _pathConstraints.add(constraint); - } - - _physicsConstraints.ensureCapacity(_data->getPhysicsConstraints().size()); - for (size_t i = 0; i < _data->getPhysicsConstraints().size(); ++i) { - PhysicsConstraintData *data = _data->getPhysicsConstraints()[i]; - - PhysicsConstraint *constraint = - new (__FILE__, __LINE__) PhysicsConstraint(*data, *this); - - _physicsConstraints.add(constraint); + _physics.ensureCapacity(8); + _constraints.ensureCapacity(_data.getConstraints().size()); + for (size_t i = 0; i < _data.getConstraints().size(); ++i) { + ConstraintData *constraintData = _data.getConstraints()[i]; + Constraint *constraint = constraintData->create(*this); + if (constraint->getRTTI().instanceOf(PhysicsConstraint::rtti)) { + _physics.add(static_cast(constraint)); + } + _constraints.add(constraint); } updateCache(); @@ -134,19 +106,25 @@ Skeleton::Skeleton(SkeletonData *skeletonData) Skeleton::~Skeleton() { ContainerUtil::cleanUpVectorOfPointers(_bones); ContainerUtil::cleanUpVectorOfPointers(_slots); - ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); - ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); - ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); - ContainerUtil::cleanUpVectorOfPointers(_physicsConstraints); + ContainerUtil::cleanUpVectorOfPointers(_constraints); } void Skeleton::updateCache() { _updateCache.clear(); + _resetCache.clear(); - for (size_t i = 0, n = _bones.size(); i < n; ++i) { - Bone *bone = _bones[i]; + Slot **slots = _slots.buffer(); + for (size_t i = 0, n = _slots.size(); i < n; i++) { + slots[i]->pose(); + } + + size_t boneCount = _bones.size(); + Bone **bones = _bones.buffer(); + for (size_t i = 0; i < boneCount; i++) { + Bone *bone = bones[i]; bone->_sorted = bone->_data.isSkinRequired(); bone->_active = !bone->_sorted; + bone->pose(); } if (_skin) { @@ -161,61 +139,35 @@ void Skeleton::updateCache() { } } - size_t ikCount = _ikConstraints.size(); - size_t transformCount = _transformConstraints.size(); - size_t pathCount = _pathConstraints.size(); - size_t physicsCount = _physicsConstraints.size(); - size_t constraintCount = ikCount + transformCount + pathCount + physicsCount; - - size_t i = 0; -continue_outer: - for (; i < constraintCount; ++i) { - for (size_t ii = 0; ii < ikCount; ++ii) { - IkConstraint *constraint = _ikConstraints[ii]; - if (constraint->getData().getOrder() == i) { - sortIkConstraint(constraint); - i++; - goto continue_outer; - } - } - - for (size_t ii = 0; ii < transformCount; ++ii) { - TransformConstraint *constraint = _transformConstraints[ii]; - if (constraint->getData().getOrder() == i) { - sortTransformConstraint(constraint); - i++; - goto continue_outer; - } - } - - for (size_t ii = 0; ii < pathCount; ++ii) { - PathConstraint *constraint = _pathConstraints[ii]; - if (constraint->getData().getOrder() == i) { - sortPathConstraint(constraint); - i++; - goto continue_outer; - } - } - - for (size_t ii = 0; ii < physicsCount; ++ii) { - PhysicsConstraint *constraint = _physicsConstraints[ii]; - if (constraint->getData().getOrder() == i) { - sortPhysicsConstraint(constraint); - i++; - goto continue_outer; - } - } + Constraint **constraints = _constraints.buffer(); + size_t n = _constraints.size(); + for (size_t i = 0; i < n; i++) { + constraints[i]->pose(); + } + for (size_t i = 0; i < n; i++) { + Constraint *constraint = constraints[i]; + constraint->_active = constraint->isSourceActive() && + (!constraint->getData().isSkinRequired()) || (_skin && _skin->_constraints.contains(&constraint->getData())); + if (constraint->_active) constraint->sort(*this); } - size_t n = _bones.size(); - for (i = 0; i < n; ++i) { - sortBone(_bones[i]); + for (size_t i = 0; i < boneCount; i++) { + sortBone(bones[i]); + } + + Update **updateCache = _updateCache.buffer(); + n = _updateCache.size(); + for (size_t i = 0; i < n; i++) { + if (updateCache[i]->getRTTI().instanceOf(Bone::rtti)) { + Bone *bone = (Bone*)(updateCache[i]); + updateCache[i] = bone->_applied; + } } } void Skeleton::printUpdateCache() { for (size_t i = 0; i < _updateCache.size(); i++) { - Updatable *updatable = _updateCache[i]; + Update *updatable = _updateCache[i]; if (updatable->getRTTI().isExactly(Bone::rtti)) { printf("bone %s\n", ((Bone *) updatable)->getData().getName().buffer()); } else if (updatable->getRTTI().isExactly(TransformConstraint::rtti)) { @@ -234,28 +186,58 @@ void Skeleton::printUpdateCache() { } } -void Skeleton::updateWorldTransform(Physics physics) { - for (size_t i = 0, n = _bones.size(); i < n; i++) { - Bone *bone = _bones[i]; - bone->_ax = bone->_x; - bone->_ay = bone->_y; - bone->_arotation = bone->_rotation; - bone->_ascaleX = bone->_scaleX; - bone->_ascaleY = bone->_scaleY; - bone->_ashearX = bone->_shearX; - bone->_ashearY = bone->_shearY; - } - - for (size_t i = 0, n = _updateCache.size(); i < n; ++i) { - Updatable *updatable = _updateCache[i]; - updatable->update(physics); +void Skeleton::constrained(Posed &object) { + if (object.isPoseEqualToApplied()) { + object.constrained(); + _resetCache.add(&object); } } -void Skeleton::updateWorldTransform(Physics physics, Bone *parent) { - // Apply the parent bone transform to the root bone. The root bone always - // inherits scale, rotation and reflection. - Bone *rootBone = getRootBone(); +void Skeleton::sortBone(Bone *bone) { + if (bone->_sorted || !bone->_active) return; + Bone *parent = bone->_parent; + if (parent != NULL) sortBone(parent); + bone->_sorted = true; + _updateCache.add((Update *)bone); +} + +void Skeleton::sortReset(Vector &bones) { + Bone **items = bones.buffer(); + for (size_t i = 0, n = bones.size(); i < n; i++) { + Bone *bone = items[i]; + if (bone->_active) { + if (bone->_sorted) sortReset(bone->getChildren()); + bone->_sorted = false; + } + } +} + +void Skeleton::updateWorldTransform(Physics physics) { + _update++; + + Posed **resetCache = _resetCache.buffer(); + for (size_t i = 0, n = _resetCache.size(); i < n; i++) { + resetCache[i]->resetConstrained(); + } + + Update **updateCache = _updateCache.buffer(); + for (size_t i = 0, n = _updateCache.size(); i < n; i++) { + updateCache[i]->update(*this, physics); + } +} + +void Skeleton::updateWorldTransform(Physics physics, BonePose *parent) { + if (parent == NULL) return; + + _update++; + + Posed **resetCache = _resetCache.buffer(); + for (size_t i = 0, n = _resetCache.size(); i < n; i++) { + resetCache[i]->resetConstrained(); + } + + // Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection. + BonePose *rootBone = getRootBone()->_applied; float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d; rootBone->_worldX = pa * _x + pb * _y + parent->_worldX; rootBone->_worldY = pc * _x + pd * _y + parent->_worldY; @@ -272,259 +254,211 @@ void Skeleton::updateWorldTransform(Physics physics, Bone *parent) { rootBone->_d = (pc * lb + pd * ld) * _scaleY; // Update everything except root bone. - Bone *rb = getRootBone(); + Update **updateCache = _updateCache.buffer(); for (size_t i = 0, n = _updateCache.size(); i < n; i++) { - Updatable *updatable = _updateCache[i]; - if (updatable != rb) - updatable->update(physics); + Update *updatable = updateCache[i]; + if (updatable != rootBone) updatable->update(*this, physics); } } -void Skeleton::setToSetupPose() { - setBonesToSetupPose(); - setSlotsToSetupPose(); +void Skeleton::setupPose() { + setupPoseBones(); + setupPoseSlots(); } -void Skeleton::setBonesToSetupPose() { +void Skeleton::setupPoseBones() { + Bone **bones = _bones.buffer(); for (size_t i = 0, n = _bones.size(); i < n; ++i) { - _bones[i]->setToSetupPose(); + bones[i]->setupPose(); } - for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { - _ikConstraints[i]->setToSetupPose(); - } - - for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { - _transformConstraints[i]->setToSetupPose(); - } - - for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { - _pathConstraints[i]->setToSetupPose(); - } - - for (size_t i = 0, n = _physicsConstraints.size(); i < n; ++i) { - _physicsConstraints[i]->setToSetupPose(); + Constraint **constraints = _constraints.buffer(); + for (size_t i = 0, n = _constraints.size(); i < n; ++i) { + constraints[i]->setupPose(); } } -void Skeleton::setSlotsToSetupPose() { +void Skeleton::setupPoseSlots() { + Slot **slots = _slots.buffer(); + size_t n = _slots.size(); _drawOrder.clear(); - for (size_t i = 0, n = _slots.size(); i < n; ++i) { - _drawOrder.add(_slots[i]); + _drawOrder.setSize(n, 0); + for (size_t i = 0; i < n; ++i) { + _drawOrder[i] = _slots[i]; } - for (size_t i = 0, n = _slots.size(); i < n; ++i) { - _slots[i]->setToSetupPose(); + for (size_t i = 0; i < n; ++i) { + slots[i]->setupPose(); } } +SkeletonData *Skeleton::getData() { + return &_data; +} + +Vector &Skeleton::getBones() { + return _bones; +} + +Vector &Skeleton::getUpdateCache() { + return _updateCache; +} + +Bone *Skeleton::getRootBone() { + return _bones.size() == 0 ? NULL : _bones[0]; +} + Bone *Skeleton::findBone(const String &boneName) { - return ContainerUtil::findWithDataName(_bones, boneName); + if (boneName.isEmpty()) return NULL; + Bone **bones = _bones.buffer(); + for (size_t i = 0, n = _bones.size(); i < n; i++) { + if (bones[i]->_data.getName() == boneName) return bones[i]; + } + return NULL; +} + +Vector &Skeleton::getSlots() { + return _slots; } Slot *Skeleton::findSlot(const String &slotName) { - return ContainerUtil::findWithDataName(_slots, slotName); + if (slotName.isEmpty()) return NULL; + Slot **slots = _slots.buffer(); + for (size_t i = 0, n = _slots.size(); i < n; i++) { + if (slots[i]->_data.getName() == slotName) return slots[i]; + } + return NULL; +} + +Vector &Skeleton::getDrawOrder() { + return _drawOrder; +} + +Skin *Skeleton::getSkin() { + return _skin; } void Skeleton::setSkin(const String &skinName) { - Skin *foundSkin = skinName.isEmpty() ? NULL : _data->findSkin(skinName); - setSkin(foundSkin); + Skin *skin = skinName.isEmpty() ? NULL : _data.findSkin(skinName); + if (skin == NULL) return; + setSkin(skin); } void Skeleton::setSkin(Skin *newSkin) { - if (_skin == newSkin) - return; + if (_skin == newSkin) return; if (newSkin != NULL) { if (_skin != NULL) { - Skeleton &thisRef = *this; - newSkin->attachAll(thisRef, *_skin); + newSkin->attachAll(*this, *_skin); } else { + Slot **slots = _slots.buffer(); for (size_t i = 0, n = _slots.size(); i < n; ++i) { - Slot *slotP = _slots[i]; - Slot &slot = *slotP; - const String &name = slot._data.getAttachmentName(); + Slot *slot = slots[i]; + const String &name = slot->_data.getAttachmentName(); if (name.length() > 0) { Attachment *attachment = newSkin->getAttachment(i, name); if (attachment != NULL) { - slot.setAttachment(attachment); + slot->_pose.setAttachment(attachment); } } } } } - _skin = newSkin; updateCache(); } -Attachment *Skeleton::getAttachment(const String &slotName, - const String &attachmentName) { - return getAttachment(_data->findSlot(slotName)->getIndex(), attachmentName); +Attachment *Skeleton::getAttachment(const String &slotName, const String &attachmentName) { + SlotData *slot = _data.findSlot(slotName); + if (slot == NULL) return NULL; + return getAttachment(slot->getIndex(), attachmentName); } -Attachment *Skeleton::getAttachment(int slotIndex, - const String &attachmentName) { - if (attachmentName.isEmpty()) - return NULL; - +Attachment *Skeleton::getAttachment(int slotIndex, const String &attachmentName) { + if (attachmentName.isEmpty()) return NULL; if (_skin != NULL) { Attachment *attachment = _skin->getAttachment(slotIndex, attachmentName); - if (attachment != NULL) { - return attachment; - } - } - - return _data->getDefaultSkin() != NULL - ? _data->getDefaultSkin()->getAttachment(slotIndex, attachmentName) - : NULL; -} - -void Skeleton::setAttachment(const String &slotName, - const String &attachmentName) { - assert(slotName.length() > 0); - - for (size_t i = 0, n = _slots.size(); i < n; ++i) { - Slot *slot = _slots[i]; - if (slot->_data.getName() == slotName) { - Attachment *attachment = NULL; - if (attachmentName.length() > 0) { - attachment = getAttachment((int) i, attachmentName); - - assert(attachment != NULL); - } - - slot->setAttachment(attachment); - - return; - } - } - - printf("Slot not found: %s", slotName.buffer()); - - assert(false); -} - -IkConstraint *Skeleton::findIkConstraint(const String &constraintName) { - assert(constraintName.length() > 0); - - for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { - IkConstraint *ikConstraint = _ikConstraints[i]; - if (ikConstraint->_data.getName() == constraintName) { - return ikConstraint; - } + if (attachment != NULL) return attachment; } + if (_data.getDefaultSkin() != NULL) return _data.getDefaultSkin()->getAttachment(slotIndex, attachmentName); return NULL; } -TransformConstraint * -Skeleton::findTransformConstraint(const String &constraintName) { - assert(constraintName.length() > 0); - - for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { - TransformConstraint *transformConstraint = _transformConstraints[i]; - if (transformConstraint->_data.getName() == constraintName) { - return transformConstraint; - } +void Skeleton::setAttachment(const String &slotName, const String &attachmentName) { + if (slotName.isEmpty()) return; + Slot *slot = findSlot(slotName); + if (slot == NULL) return; + Attachment *attachment = NULL; + if (!attachmentName.isEmpty()) { + attachment = getAttachment(slot->_data.getIndex(), attachmentName); + if (attachment == NULL) return; } - - return NULL; + slot->_pose.setAttachment(attachment); } -PathConstraint *Skeleton::findPathConstraint(const String &constraintName) { - assert(constraintName.length() > 0); - - for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { - PathConstraint *constraint = _pathConstraints[i]; - if (constraint->_data.getName() == constraintName) { - return constraint; - } - } - - return NULL; +Vector &Skeleton::getConstraints() { + return _constraints; } -PhysicsConstraint * -Skeleton::findPhysicsConstraint(const String &constraintName) { - assert(constraintName.length() > 0); - - for (size_t i = 0, n = _physicsConstraints.size(); i < n; ++i) { - PhysicsConstraint *constraint = _physicsConstraints[i]; - if (constraint->_data.getName() == constraintName) { - return constraint; - } - } - - return NULL; +Vector &Skeleton::getPhysicsConstraints() { + return _physics; } -void Skeleton::getBounds(float &outX, float &outY, float &outWidth, - float &outHeight, Vector &outVertexBuffer) { +void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector &outVertexBuffer) { getBounds(outX, outY, outWidth, outHeight, outVertexBuffer, NULL); } -void Skeleton::getBounds(float &outX, float &outY, float &outWidth, - float &outHeight, Vector &outVertexBuffer, SkeletonClipping *clipper) { +void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector &outVertexBuffer, SkeletonClipping *clipper) { static unsigned short quadIndices[] = {0, 1, 2, 2, 3, 0}; float minX = FLT_MAX; float minY = FLT_MAX; float maxX = -FLT_MAX; float maxY = -FLT_MAX; - for (size_t i = 0; i < _drawOrder.size(); ++i) { - Slot *slot = _drawOrder[i]; - if (!slot->_bone._active) - continue; + Slot **drawOrder = _drawOrder.buffer(); + for (size_t i = 0, n = _drawOrder.size(); i < n; ++i) { + Slot *slot = drawOrder[i]; + if (!slot->_bone._active) continue; size_t verticesLength = 0; - Attachment *attachment = slot->getAttachment(); + float *vertices = NULL; unsigned short *triangles = NULL; size_t trianglesLength = 0; + Attachment *attachment = slot->_pose.getAttachment(); - if (attachment != NULL && - attachment->getRTTI().instanceOf(RegionAttachment::rtti)) { - RegionAttachment *regionAttachment = - static_cast(attachment); - - verticesLength = 8; - if (outVertexBuffer.size() < 8) { + if (attachment != NULL) { + if (attachment->getRTTI().instanceOf(RegionAttachment::rtti)) { + RegionAttachment *regionAttachment = static_cast(attachment); + verticesLength = 8; outVertexBuffer.setSize(8, 0); - } - regionAttachment->computeWorldVertices(*slot, outVertexBuffer, 0); - triangles = quadIndices; - trianglesLength = 6; - } else if (attachment != NULL && - attachment->getRTTI().instanceOf(MeshAttachment::rtti)) { - MeshAttachment *mesh = static_cast(attachment); - - verticesLength = mesh->getWorldVerticesLength(); - if (outVertexBuffer.size() < verticesLength) { + regionAttachment->computeWorldVertices(*slot, outVertexBuffer.buffer(), 0, 2); + vertices = outVertexBuffer.buffer(); + triangles = quadIndices; + trianglesLength = 6; + } else if (attachment->getRTTI().instanceOf(MeshAttachment::rtti)) { + MeshAttachment *mesh = static_cast(attachment); + verticesLength = mesh->getWorldVerticesLength(); outVertexBuffer.setSize(verticesLength, 0); + mesh->computeWorldVertices(*this, *slot, 0, verticesLength, outVertexBuffer.buffer(), 0, 2); + vertices = outVertexBuffer.buffer(); + triangles = mesh->getTriangles().buffer(); + trianglesLength = mesh->getTriangles().size(); + } else if (attachment->getRTTI().instanceOf(ClippingAttachment::rtti) && clipper != NULL) { + clipper->clipEnd(*slot); + clipper->clipStart(*this, *slot, static_cast(attachment)); + continue; } - mesh->computeWorldVertices(*slot, 0, verticesLength, - outVertexBuffer.buffer(), 0); - triangles = mesh->getTriangles().buffer(); - trianglesLength = mesh->getTriangles().size(); - } else if (attachment != NULL && - attachment->getRTTI().instanceOf(ClippingAttachment::rtti) && clipper != NULL) { - clipper->clipStart(*slot, static_cast(attachment)); - continue; - } - - if (verticesLength > 0) { - float *vertices = outVertexBuffer.buffer(); - if (clipper != NULL && clipper->isClipping()) { - clipper->clipTriangles(outVertexBuffer.buffer(), triangles, trianglesLength); - vertices = clipper->getClippedVertices().buffer(); - verticesLength = clipper->getClippedVertices().size(); - } - for (size_t ii = 0; ii < verticesLength; ii += 2) { - float vx = vertices[ii]; - float vy = vertices[ii + 1]; - - minX = MathUtil::min(minX, vx); - minY = MathUtil::min(minY, vy); - maxX = MathUtil::max(maxX, vx); - maxY = MathUtil::max(maxY, vy); + if (vertices != NULL) { + if (clipper != NULL && clipper->isClipping() && clipper->clipTriangles(vertices, triangles, trianglesLength)) { + vertices = clipper->getClippedVertices().buffer(); + verticesLength = clipper->getClippedVertices().size(); + } + for (size_t ii = 0; ii < verticesLength; ii += 2) { + float x = vertices[ii], y = vertices[ii + 1]; + minX = MathUtil::min(minX, x); + minY = MathUtil::min(minY, y); + maxX = MathUtil::max(maxX, x); + maxY = MathUtil::max(maxY, y); + } } } if (clipper != NULL) clipper->clipEnd(*slot); @@ -537,254 +471,114 @@ void Skeleton::getBounds(float &outX, float &outY, float &outWidth, outHeight = maxY - minY; } -Bone *Skeleton::getRootBone() { return _bones.size() == 0 ? NULL : _bones[0]; } - -SkeletonData *Skeleton::getData() { return _data; } - -Vector &Skeleton::getBones() { return _bones; } - -Vector &Skeleton::getUpdateCacheList() { return _updateCache; } - -Vector &Skeleton::getSlots() { return _slots; } - -Vector &Skeleton::getDrawOrder() { return _drawOrder; } - -Vector &Skeleton::getIkConstraints() { return _ikConstraints; } - -Vector &Skeleton::getPathConstraints() { - return _pathConstraints; +Color &Skeleton::getColor() { + return _color; } -Vector &Skeleton::getTransformConstraints() { - return _transformConstraints; +void Skeleton::setColor(Color &color) { + _color.set(color.r, color.g, color.b, color.a); } -Vector &Skeleton::getPhysicsConstraints() { - return _physicsConstraints; +void Skeleton::setColor(float r, float g, float b, float a) { + _color.set(r, g, b, a); } -Skin *Skeleton::getSkin() { return _skin; } +float Skeleton::getScaleX() { + return _scaleX; +} -Color &Skeleton::getColor() { return _color; } +void Skeleton::setScaleX(float inValue) { + _scaleX = inValue; +} + +float Skeleton::getScaleY() { + return _scaleY * (Bone::isYDown() ? -1 : 1); +} + +void Skeleton::setScaleY(float inValue) { + _scaleY = inValue; +} + +void Skeleton::setScale(float scaleX, float scaleY) { + _scaleX = scaleX; + _scaleY = scaleY; +} + +float Skeleton::getX() { + return _x; +} + +void Skeleton::setX(float inValue) { + _x = inValue; +} + +float Skeleton::getY() { + return _y; +} + +void Skeleton::setY(float inValue) { + _y = inValue; +} void Skeleton::setPosition(float x, float y) { _x = x; _y = y; } -float Skeleton::getX() { return _x; } - -void Skeleton::setX(float inValue) { _x = inValue; } - -float Skeleton::getY() { return _y; } - -void Skeleton::setY(float inValue) { _y = inValue; } - -float Skeleton::getScaleX() { return _scaleX; } - -void Skeleton::setScaleX(float inValue) { _scaleX = inValue; } - -float Skeleton::getScaleY() { return _scaleY * (Bone::isYDown() ? -1 : 1); } - -void Skeleton::setScaleY(float inValue) { _scaleY = 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); - - Vector &constrained = constraint->getBones(); - Bone *parent = constrained[0]; - sortBone(parent); - - if (constrained.size() == 1) { - _updateCache.add(constraint); - sortReset(parent->_children); - } else { - Bone *child = constrained[constrained.size() - 1]; - sortBone(child); - - _updateCache.add(constraint); - - sortReset(parent->_children); - child->_sorted = true; - } +float Skeleton::getWindX() { + return _windX; } -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(); - if (_skin != NULL) - sortPathConstraintAttachment(_skin, slotIndex, slotBone); - if (_data->_defaultSkin != NULL && _data->_defaultSkin != _skin) - sortPathConstraintAttachment(_data->_defaultSkin, slotIndex, slotBone); - for (size_t ii = 0, nn = _data->_skins.size(); ii < nn; ii++) - sortPathConstraintAttachment(_data->_skins[ii], slotIndex, slotBone); - - Attachment *attachment = slot->getAttachment(); - if (attachment != NULL && - attachment->getRTTI().instanceOf(PathAttachment::rtti)) - sortPathConstraintAttachment(attachment, slotBone); - - Vector &constrained = constraint->getBones(); - size_t boneCount = constrained.size(); - for (size_t i = 0; i < boneCount; ++i) { - sortBone(constrained[i]); - } - - _updateCache.add(constraint); - - for (size_t i = 0; i < boneCount; i++) - sortReset(constrained[i]->getChildren()); - for (size_t i = 0; i < boneCount; i++) - constrained[i]->_sorted = true; +void Skeleton::setWindX(float windX) { + _windX = windX; } -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(); - size_t boneCount = constrained.size(); - if (constraint->_data.isLocal()) { - for (size_t i = 0; i < boneCount; i++) { - Bone *child = constrained[i]; - sortBone(child->getParent()); - sortBone(child); - } - } else { - for (size_t i = 0; i < boneCount; ++i) { - sortBone(constrained[i]); - } - } - - _updateCache.add(constraint); - - for (size_t i = 0; i < boneCount; ++i) - sortReset(constrained[i]->getChildren()); - for (size_t i = 0; i < boneCount; ++i) - constrained[i]->_sorted = true; +float Skeleton::getWindY() { + return _windY; } -void Skeleton::sortPhysicsConstraint(PhysicsConstraint *constraint) { - Bone *bone = constraint->getBone(); - constraint->_active = - bone->_active && - (!constraint->_data.isSkinRequired() || - (_skin && _skin->_constraints.contains(&constraint->_data))); - if (!constraint->_active) - return; - - sortBone(bone); - _updateCache.add(constraint); - sortReset(bone->getChildren()); - bone->_sorted = true; +void Skeleton::setWindY(float windY) { + _windY = windY; } -void Skeleton::sortPathConstraintAttachment(Skin *skin, size_t slotIndex, - Bone &slotBone) { - Skin::AttachmentMap::Entries attachments = skin->getAttachments(); - - while (attachments.hasNext()) { - Skin::AttachmentMap::Entry entry = attachments.next(); - if (entry._slotIndex == slotIndex) { - Attachment *value = entry._attachment; - sortPathConstraintAttachment(value, slotBone); - } - } +float Skeleton::getGravityX() { + return _gravityX; } -void Skeleton::sortPathConstraintAttachment(Attachment *attachment, - Bone &slotBone) { - if (attachment == NULL || - !attachment->getRTTI().instanceOf(PathAttachment::rtti)) - return; - Vector &pathBones = - static_cast(attachment)->getBones(); - if (pathBones.size() == 0) - sortBone(&slotBone); - else { - for (size_t i = 0, n = pathBones.size(); i < n;) { - size_t nn = pathBones[i++]; - nn += i; - while (i < nn) { - sortBone(_bones[pathBones[i++]]); - } - } - } +void Skeleton::setGravityX(float gravityX) { + _gravityX = gravityX; } -void Skeleton::sortBone(Bone *bone) { - if (bone->_sorted) - return; - Bone *parent = bone->_parent; - if (parent != NULL) - sortBone(parent); - bone->_sorted = true; - _updateCache.add(bone); +float Skeleton::getGravityY() { + return _gravityY; } -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; - } +void Skeleton::setGravityY(float gravityY) { + _gravityY = gravityY; } -float Skeleton::getTime() { return _time; } - -void Skeleton::setTime(float time) { _time = time; } - -void Skeleton::update(float delta) { _time += delta; } - void Skeleton::physicsTranslate(float x, float y) { - for (int i = 0; i < (int) _physicsConstraints.size(); i++) { - _physicsConstraints[i]->translate(x, y); + PhysicsConstraint **constraints = _physics.buffer(); + for (size_t i = 0, n = _physics.size(); i < n; i++) { + constraints[i]->translate(x, y); } } void Skeleton::physicsRotate(float x, float y, float degrees) { - for (int i = 0; i < (int) _physicsConstraints.size(); i++) { - _physicsConstraints[i]->rotate(x, y, degrees); + PhysicsConstraint **constraints = _physics.buffer(); + for (size_t i = 0, n = _physics.size(); i < n; i++) { + constraints[i]->rotate(x, y, degrees); } } -float Skeleton::getWindX() { return _windX; } +float Skeleton::getTime() { + return _time; +} -void Skeleton::setWindX(float windX) { _windX = windX; } +void Skeleton::setTime(float time) { + _time = time; +} -float Skeleton::getWindY() { return _windY; } - -void Skeleton::setWindY(float windY) { _windY = windY; } - -float Skeleton::getGravityX() { return _gravityX; } - -void Skeleton::setGravityX(float gravityX) { _gravityX = gravityX; } - -float Skeleton::getGravityY() { return _gravityY; } - -void Skeleton::setGravityY(float gravityY) { _gravityY = gravityY; } +void Skeleton::update(float delta) { + _time += delta; +} \ No newline at end of file diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp index fbe09ed01..98b25ea5b 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -41,7 +41,7 @@ SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) { _clippedUVs.ensureCapacity(128); } -size_t SkeletonClipping::clipStart(Slot &slot, ClippingAttachment *clip) { +size_t SkeletonClipping::clipStart(Skeleton &skeleton, Slot &slot, ClippingAttachment *clip) { if (_clipAttachment != NULL) { return 0; } @@ -49,8 +49,11 @@ size_t SkeletonClipping::clipStart(Slot &slot, ClippingAttachment *clip) { _clipAttachment = clip; int n = (int) clip->getWorldVerticesLength(); + if (n < 6) { + return 0; + } _clippingPolygon.setSize(n, 0); - clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2); + clip->computeWorldVertices(skeleton, slot, 0, n, _clippingPolygon.buffer(), 0, 2); makeClockwise(_clippingPolygon); _clippingPolygons = &_triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); @@ -82,7 +85,7 @@ void SkeletonClipping::clipEnd() { _clippingPolygon.clear(); } -void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, +bool SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength) { Vector &clipOutput = _clipOutput; Vector &clippedVertices = _clippedVertices; @@ -94,11 +97,11 @@ void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, clippedVertices.clear(); _clippedUVs.clear(); clippedTriangles.clear(); + bool clipped = false; int stride = 2; - size_t i = 0; -continue_outer: - for (; i < trianglesLength; i += 3) { + + for (int i = 0; i < trianglesLength; i += 3) { int vertexOffset = triangles[i] * stride; float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; @@ -113,6 +116,7 @@ continue_outer: if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) { size_t clipOutputLength = clipOutput.size(); if (clipOutputLength == 0) continue; + clipped = true; size_t clipOutputCount = clipOutputLength >> 1; clippedVertices.setSize(s + clipOutputCount * 2, 0); @@ -148,19 +152,19 @@ continue_outer: clippedTriangles[s + 1] = (unsigned short) (index + 1); clippedTriangles[s + 2] = (unsigned short) (index + 2); index += 3; - i += 3; - goto continue_outer; + break; } } } + return clipped; } -void SkeletonClipping::clipTriangles(Vector &vertices, Vector &triangles, Vector &uvs, +bool SkeletonClipping::clipTriangles(Vector &vertices, Vector &triangles, Vector &uvs, size_t stride) { - clipTriangles(vertices.buffer(), triangles.buffer(), triangles.size(), uvs.buffer(), stride); + return clipTriangles(vertices.buffer(), triangles.buffer(), triangles.size(), uvs.buffer(), stride); } -void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, +bool SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength, float *uvs, size_t stride) { Vector &clipOutput = _clipOutput; Vector &clippedVertices = _clippedVertices; @@ -172,10 +176,9 @@ void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, clippedVertices.clear(); _clippedUVs.clear(); clippedTriangles.clear(); + bool clipped = false; - size_t i = 0; -continue_outer: - for (; i < trianglesLength; i += 3) { + for (int i = 0; i < trianglesLength; i += 3) { int vertexOffset = triangles[i] * (int) stride; float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; @@ -193,6 +196,7 @@ continue_outer: if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) { size_t clipOutputLength = clipOutput.size(); if (clipOutputLength == 0) continue; + clipped = true; float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; float d = 1 / (d0 * d2 + d1 * (y1 - y3)); @@ -246,10 +250,11 @@ continue_outer: clippedTriangles[s + 2] = (unsigned short) (index + 2); index += 3; i += 3; - goto continue_outer; + break; } } } + return clipped; } bool SkeletonClipping::isClipping() { diff --git a/spine-cpp/spine-cpp/src/spine/SliderData.cpp b/spine-cpp/spine-cpp/src/spine/SliderData.cpp index 800789747..d08fc91e6 100644 --- a/spine-cpp/spine-cpp/src/spine/SliderData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SliderData.cpp @@ -35,13 +35,13 @@ using namespace spine; RTTI_IMPL(SliderData, ConstraintData) -SliderData::SliderData(const String &name) : ConstraintData(name), - PosedDataGeneric(name), +SliderData::SliderData(const String &name) : ConstraintDataGeneric(name), _animation(NULL), _additive(false), _loop(false), _bone(NULL), _property(NULL), + _offset(0.0f), _scale(0.0f), _local(false) { } @@ -98,6 +98,14 @@ void SliderData::setScale(float scale) { _scale = scale; } +float SliderData::getOffset() { + return _offset; +} + +void SliderData::setOffset(float offset) { + _offset = offset; +} + bool SliderData::getLocal() { return _local; } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index 071b00c20..f14d6ece7 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -46,33 +46,32 @@ TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton _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()); + _bones.add(&skeleton._bones[boneData->getIndex()]->_constrained); } - _source = skeleton.findBone(data.getSource()->getName()); + _source = skeleton._bones[data._source->getIndex()]; } -TransformConstraint TransformConstraint::copy(Skeleton &skeleton) { - TransformConstraint copy(_data, skeleton); - copy._applied->set(*_applied); +TransformConstraint *TransformConstraint::copy(Skeleton &skeleton) { + TransformConstraint *copy = new (__FILE__, __LINE__) TransformConstraint(_data, skeleton); + copy->_pose.set(_pose); 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; + if (p._mixRotate == 0 && p._mixX == 0 && p._mixY == 0 && p._mixScaleX == 0 && p._mixScaleY == 0 && p._mixShearY == 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(); + bool localSource = data._localSource, localTarget = data._localTarget, additive = data._additive, clamp = data._clamp; + float *offsets = data._offsets; + BonePose &source = *_source->_applied; if (localSource) { source.validateLocalTransform(skeleton); } - Vector &properties = data.getProperties(); - FromProperty **fromItems = properties.buffer(); - size_t fn = properties.size(); + FromProperty **fromItems = data._properties.buffer(); + size_t fn = data._properties.size(); int update = skeleton._update; BonePose **bones = _bones.buffer(); for (size_t i = 0, n = _bones.size(); i < n; i++) { @@ -84,7 +83,7 @@ void TransformConstraint::update(Skeleton &skeleton, Physics physics) { } for (size_t f = 0; f < fn; f++) { FromProperty *from = fromItems[f]; - float value = from->value(source, localSource, offsets) - from->offset; + float value = from->value(skeleton, source, localSource, offsets) - from->offset; Vector &toProps = from->to; ToProperty **toItems = toProps.buffer(); for (size_t t = 0, tn = toProps.size(); t < tn; t++) { @@ -97,7 +96,7 @@ void TransformConstraint::update(Skeleton &skeleton, Physics physics) { else clamped = MathUtil::clamp(clamped, to->max, to->offset); } - to->apply(p, *bone, clamped, localTarget, additive); + to->apply(skeleton, p, *bone, clamped, localTarget, additive); } } } @@ -105,10 +104,10 @@ void TransformConstraint::update(Skeleton &skeleton, Physics physics) { } void TransformConstraint::sort(Skeleton &skeleton) { - if (!_data.getLocalSource()) skeleton.sortBone(_source); + if (!_data._localSource) skeleton.sortBone(_source); BonePose **bones = _bones.buffer(); size_t boneCount = _bones.size(); - bool worldTarget = !_data.getLocalTarget(); + bool worldTarget = !_data._localTarget; if (worldTarget) { for (size_t i = 0; i < boneCount; i++) skeleton.sortBone(bones[i]->_bone); @@ -116,7 +115,7 @@ void TransformConstraint::sort(Skeleton &skeleton) { skeleton._updateCache.add(this); for (size_t i = 0; i < boneCount; i++) { Bone *bone = bones[i]->_bone; - skeleton.sortReset(bone->getChildren()); + skeleton.sortReset(bone->_children); skeleton.constrained(*bone); } for (size_t i = 0; i < boneCount; i++) @@ -124,7 +123,7 @@ void TransformConstraint::sort(Skeleton &skeleton) { } bool TransformConstraint::isSourceActive() { - return _source->isActive(); + return _source->_active; } /// The bones that will be modified by this transform constraint. diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp index 0a0c64338..327c6b24e 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -40,8 +40,7 @@ using namespace spine; RTTI_IMPL(TransformConstraintData, ConstraintData) -TransformConstraintData::TransformConstraintData(const String &name) : ConstraintData(name), - PosedDataGeneric(name), +TransformConstraintData::TransformConstraintData(const String &name) : ConstraintDataGeneric(name), _source(NULL), _localSource(false), _localTarget(false), @@ -148,53 +147,42 @@ Vector &TransformConstraintData::getProperties() { return _properties; } -// ============================================================================ -// Property Classes -// ============================================================================ - -// No RTTI for FromProperty - FromProperty::FromProperty() : SpineObject(), offset(0) { } FromProperty::~FromProperty() { } -// No RTTI for ToProperty - ToProperty::ToProperty() : offset(0), max(0), scale(1) { } ToProperty::~ToProperty() { } -// No RTTI for FromRotate - -float FromRotate::value(BonePose &source, bool local, float *offsets) { - 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[TransformConstraintData::ROTATION] : -offsets[TransformConstraintData::ROTATION]); +float FromRotate::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + if (local) return source._rotation + offsets[TransformConstraintData::ROTATION]; + float value = MathUtil::atan2(source._c / skeleton.getScaleY(), source._a / skeleton.getScaleX()) * MathUtil::Rad_Deg + + (source._a * source._d - source._b * source._c > 0 ? offsets[TransformConstraintData::ROTATION] : -offsets[TransformConstraintData::ROTATION]); if (value < 0) value += 360; return value; } -// No RTTI for ToRotate - float ToRotate::mix(TransformConstraintPose &pose) { return pose._mixRotate; } -void ToRotate::apply(TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { +void ToRotate::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { if (local) { - if (!additive) value -= bone.getRotation(); - bone.setRotation(bone.getRotation() + value * pose._mixRotate); + if (!additive) value -= bone._rotation; + bone._rotation += value * pose._mixRotate; } else { float a = bone._a, b = bone._b, c = bone._c, d = bone._d; value *= MathUtil::Deg_Rad; if (!additive) value -= MathUtil::atan2(c, a); if (value > MathUtil::Pi) - value -= MathUtil::Pi * 2; - else if (value < -MathUtil::Pi) - value += MathUtil::Pi * 2; + value -= MathUtil::Pi_2; + else if (value < -MathUtil::Pi) // + value += MathUtil::Pi_2; value *= pose._mixRotate; float cosVal = MathUtil::cos(value), sinVal = MathUtil::sin(value); bone._a = cosVal * a - sinVal * c; @@ -204,74 +192,64 @@ void ToRotate::apply(TransformConstraintPose &pose, BonePose &bone, float value, } } -// No RTTI for FromX - -float FromX::value(BonePose &source, bool local, float *offsets) { - return local ? source.getX() + offsets[TransformConstraintData::X] : offsets[TransformConstraintData::X] * source._a + offsets[TransformConstraintData::Y] * source._b + source.getWorldX(); +float FromX::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + return local ? source._x + offsets[TransformConstraintData::X] : (offsets[TransformConstraintData::X] * source._a + offsets[TransformConstraintData::Y] * source._b + source._worldX) / skeleton.getScaleX(); } -// No RTTI for ToX - float ToX::mix(TransformConstraintPose &pose) { return pose._mixX; } -void ToX::apply(TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { +void ToX::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { if (local) { - if (!additive) value -= bone.getX(); - bone.setX(bone.getX() + value * pose._mixX); + if (!additive) value -= bone._x; + bone._x += value * pose._mixX; } else { - if (!additive) value -= bone.getWorldX(); - bone.setWorldX(bone.getWorldX() + value * pose._mixX); + if (!additive) value -= bone._worldX; + bone._worldX += value * pose._mixX; } } -// No RTTI for FromY - -float FromY::value(BonePose &source, bool local, float *offsets) { - return local ? source.getY() + offsets[TransformConstraintData::Y] : offsets[TransformConstraintData::X] * source._c + offsets[TransformConstraintData::Y] * source._d + source.getWorldY(); +float FromY::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + return local ? source._y + offsets[TransformConstraintData::Y] : (offsets[TransformConstraintData::X] * source._c + offsets[TransformConstraintData::Y] * source._d + source._worldY) / skeleton.getScaleY(); } -// No RTTI for ToY - float ToY::mix(TransformConstraintPose &pose) { return pose._mixY; } -void ToY::apply(TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { +void ToY::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { if (local) { - if (!additive) value -= bone.getY(); - bone.setY(bone.getY() + value * pose._mixY); + if (!additive) value -= bone._y; + bone._y += value * pose._mixY; } else { - if (!additive) value -= bone.getWorldY(); - bone.setWorldY(bone.getWorldY() + value * pose._mixY); + if (!additive) value -= bone._worldY; + bone._worldY += value * pose._mixY; } } -// 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[TransformConstraintData::SCALEX]; +float FromScaleX::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + if (local) return source._scaleX + offsets[TransformConstraintData::SCALEX]; + float a = source._a / skeleton.getScaleX(), c = source._c / skeleton.getScaleY(); + return MathUtil::sqrt(a * a + c * c) + offsets[TransformConstraintData::SCALEX]; } -// No RTTI for ToScaleX - float ToScaleX::mix(TransformConstraintPose &pose) { return pose._mixScaleX; } -void ToScaleX::apply(TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { +void ToScaleX::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { if (local) { if (additive) - bone.setScaleX(bone.getScaleX() * (1 + ((value - 1) * pose._mixScaleX))); - else if (bone.getScaleX() != 0) - bone.setScaleX(bone.getScaleX() * (1 + (value / bone.getScaleX() - 1) * pose._mixScaleX)); + bone._scaleX *= 1 + ((value - 1) * pose._mixScaleX); + else if (bone._scaleX != 0) // + bone._scaleX = 1 + (value / bone._scaleX - 1) * pose._mixScaleX; } else { float s; if (additive) s = 1 + (value - 1) * pose._mixScaleX; else { - s = MathUtil::sqrt(bone._a * bone._a + bone._c * bone._c); + s = MathUtil::sqrt(bone._a * bone._a + bone._c * bone._c) / skeleton.getScaleX(); if (s != 0) s = 1 + (value / s - 1) * pose._mixScaleX; } bone._a *= s; @@ -279,30 +257,28 @@ void ToScaleX::apply(TransformConstraintPose &pose, BonePose &bone, float value, } } -// 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[TransformConstraintData::SCALEY]; +float FromScaleY::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + if (local) return source._scaleY + offsets[TransformConstraintData::SCALEY]; + float b = source._b / skeleton.getScaleX(), d = source._d / skeleton.getScaleY(); + return MathUtil::sqrt(b * b + d * d) + offsets[TransformConstraintData::SCALEY]; } -// No RTTI for ToScaleY - float ToScaleY::mix(TransformConstraintPose &pose) { return pose._mixScaleY; } -void ToScaleY::apply(TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { +void ToScaleY::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { if (local) { if (additive) - bone.setScaleY(bone.getScaleY() * (1 + ((value - 1) * pose._mixScaleY))); - else if (bone.getScaleY() != 0) - bone.setScaleY(bone.getScaleY() * (1 + (value / bone.getScaleY() - 1) * pose._mixScaleY)); + bone._scaleY *= 1 + ((value - 1) * pose._mixScaleY); + else if (bone._scaleY != 0) // + bone._scaleY = 1 + (value / bone._scaleY - 1) * pose._mixScaleY; } else { float s; if (additive) s = 1 + (value - 1) * pose._mixScaleY; else { - s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d); + s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d) / skeleton.getScaleY(); if (s != 0) s = 1 + (value / s - 1) * pose._mixScaleY; } bone._b *= s; @@ -310,22 +286,20 @@ void ToScaleY::apply(TransformConstraintPose &pose, BonePose &bone, float value, } } -// 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[TransformConstraintData::SHEARY]; +float FromShearY::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) { + if (local) return source._shearY + offsets[TransformConstraintData::SHEARY]; + float sx = 1 / skeleton.getScaleX(), sy = 1 / skeleton.getScaleY(); + return (MathUtil::atan2(source._d * sy, source._b * sx) - MathUtil::atan2(source._c * sy, source._a * sx)) * MathUtil::Rad_Deg - 90 + offsets[TransformConstraintData::SHEARY]; } -// No RTTI for ToShearY - float ToShearY::mix(TransformConstraintPose &pose) { return pose._mixShearY; } -void ToShearY::apply(TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { +void ToShearY::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) { if (local) { - if (!additive) value -= bone.getShearY(); - bone.setShearY(bone.getShearY() + value * pose._mixShearY); + if (!additive) value -= bone._shearY; + bone._shearY += value * pose._mixShearY; } else { float b = bone._b, d = bone._d, by = MathUtil::atan2(d, b); value = (value + 90) * MathUtil::Deg_Rad; @@ -334,9 +308,9 @@ void ToShearY::apply(TransformConstraintPose &pose, BonePose &bone, float value, else { value -= by - MathUtil::atan2(bone._c, bone._a); if (value > MathUtil::Pi) - value -= MathUtil::Pi * 2; - else if (value < -MathUtil::Pi) - value += MathUtil::Pi * 2; + value -= MathUtil::Pi_2; + else if (value < -MathUtil::Pi) // + value += MathUtil::Pi_2; } value = by + value * pose._mixShearY; float s = MathUtil::sqrt(b * b + d * d);