[cpp] 4.0 port, half done.

This commit is contained in:
badlogic 2021-03-02 16:54:14 +01:00
parent 8c4d03c8be
commit 653c06a6b8
45 changed files with 1178 additions and 781 deletions

View File

@ -286,7 +286,7 @@ xcopy "$(ProjectDir)..\Resources" "$(OutDir)\Resources" /D /E /I /F /Y
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\String.h" /> <ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\String.h" />
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TextureLoader.h" /> <ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TextureLoader.h" />
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\Timeline.h" /> <ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\Timeline.h" />
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TimelineType.h" /> <ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\Property.h" />
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraint.h" /> <ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraint.h" />
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraintData.h" /> <ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraintData.h" />
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraintTimeline.h" /> <ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraintTimeline.h" />

View File

@ -491,7 +491,7 @@
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\Timeline.h"> <ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\Timeline.h">
<Filter>spine</Filter> <Filter>spine</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TimelineType.h"> <ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\Property.h">
<Filter>spine</Filter> <Filter>spine</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraint.h"> <ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraint.h">

View File

@ -36,6 +36,7 @@
#include <spine/MixDirection.h> #include <spine/MixDirection.h>
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
#include <spine/SpineString.h> #include <spine/SpineString.h>
#include <spine/Property.h>
namespace spine { namespace spine {
class Timeline; class Timeline;
@ -79,6 +80,10 @@ class SP_API Animation : public SpineObject {
friend class TranslateTimeline; friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class TwoColorTimeline; friend class TwoColorTimeline;
public: public:
@ -95,27 +100,22 @@ public:
Vector<Timeline *> &getTimelines(); Vector<Timeline *> &getTimelines();
bool hasTimeline(int id); bool hasTimeline(Vector<PropertyId> ids);
float getDuration(); float getDuration();
void setDuration(float inValue); void setDuration(float inValue);
private: private:
Vector<Timeline *> _timelines; Vector<Timeline *> _timelines;
HashMap<int, bool> _timelineIds; HashMap<PropertyId, bool> _timelineIds;
float _duration; float _duration;
String _name; String _name;
/// @param target After the first and before the last entry. /// @param target After the first and before the last entry.
static int binarySearch(Vector<float> &values, float target, int step); static int search(Vector<float> &values, float target);
/// @param target After the first and before the last entry. static int search(Vector<float> &values, float target, int step);
static int binarySearch(Vector<float> &values, float target);
static int linearSearch(Vector<float> &values, float target, int step);
}; };
} }

View File

@ -65,10 +65,18 @@ class SP_API Bone : public Updatable {
friend class ScaleTimeline; friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline; friend class ShearTimeline;
friend class TranslateTimeline; friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
RTTI_DECL RTTI_DECL
public: public:

View File

@ -46,10 +46,18 @@ class SP_API BoneData : public SpineObject {
friend class ScaleTimeline; friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline; friend class ShearTimeline;
friend class TranslateTimeline; friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
public: public:
BoneData(int index, const String &name, BoneData *parent = NULL); BoneData(int index, const String &name, BoneData *parent = NULL);

View File

@ -39,38 +39,59 @@ namespace spine {
RTTI_DECL RTTI_DECL
public: public:
explicit CurveTimeline(int frameCount); explicit CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount);
virtual ~CurveTimeline(); virtual ~CurveTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction) = 0; void setLinear(size_t frame);
virtual int getPropertyId() = 0; void setStepped(size_t frame);
size_t getFrameCount(); void setBezier (size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2, float time2, float value2);
void setLinear(size_t frameIndex); float getBezierValue(float time, size_t frame, size_t valueOffset, size_t i);
void setStepped(size_t frameIndex);
/// Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
/// cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
/// the difference between the keyframe's values.
void setCurve(size_t frameIndex, float cx1, float cy1, float cx2, float cy2);
float getCurvePercent(size_t frameIndex, float percent);
float getCurveType(size_t frameIndex);
protected: protected:
static const float LINEAR; static const int LINEAR = 0;
static const float STEPPED; static const int STEPPED = 1;
static const float BEZIER; static const int BEZIER = 2;
static const int BEZIER_SIZE; static const int BEZIER_SIZE = 18;
private:
Vector<float> _curves; // type, x, y, ... Vector<float> _curves; // type, x, y, ...
}; };
class SP_API CurveTimeline1 : public CurveTimeline {
RTTI_DECL
public:
explicit CurveTimeline1(size_t frameCount, size_t bezierCount);
virtual ~CurveTimeline1();
void setFrame(size_t frame, float time, float value);
float getCurveValue(float time);
protected:
static const int ENTRIES;
static const int VALUE;
};
class SP_API CurveTimeline2 : public CurveTimeline {
RTTI_DECL
public:
explicit CurveTimeline2(size_t frameCount, size_t bezierCount);
virtual ~CurveTimeline2();
void setFrame(size_t frame, float time, float value1, float value2);
float getCurveValue(float time);
protected:
static const int ENTRIES;
static const int VALUE1;
static const int VALUE2;
};
} }
#endif /* Spine_CurveTimeline_h */ #endif /* Spine_CurveTimeline_h */

View File

@ -65,11 +65,14 @@ namespace spine {
float getSpacing(); float getSpacing();
void setSpacing(float inValue); void setSpacing(float inValue);
float getRotateMix(); float getMixRotate();
void setRotateMix(float inValue); void setMixRotate(float inValue);
float getTranslateMix(); float getMixX();
void setTranslateMix(float inValue); void setMixX(float inValue);
float getMixY();
void setMixY(float inValue);
Vector<Bone*>& getBones(); Vector<Bone*>& getBones();
@ -91,7 +94,8 @@ namespace spine {
PathConstraintData& _data; PathConstraintData& _data;
Vector<Bone*> _bones; Vector<Bone*> _bones;
Slot* _target; Slot* _target;
float _position, _spacing, _rotateMix, _translateMix; float _position, _spacing;
float _mixRotate, _mixX, _mixY;
Vector<float> _spaces; Vector<float> _spaces;
Vector<float> _positions; Vector<float> _positions;
@ -102,7 +106,7 @@ namespace spine {
bool _active; bool _active;
Vector<float>& computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing); Vector<float>& computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents);
static void addBeforePosition(float p, Vector<float>& temp, int i, Vector<float>& output, int o); static void addBeforePosition(float p, Vector<float>& temp, int i, Vector<float>& output, int o);

View File

@ -78,11 +78,14 @@ namespace spine {
float getSpacing(); float getSpacing();
void setSpacing(float inValue); void setSpacing(float inValue);
float getRotateMix(); float getMixRotate();
void setRotateMix(float inValue); void setMixRotate(float inValue);
float getTranslateMix(); float getMixX();
void setTranslateMix(float inValue); void setMixX(float inValue);
float getMixY();
void setMixY(float inValue);
private: private:
Vector<BoneData*> _bones; Vector<BoneData*> _bones;
@ -91,7 +94,8 @@ namespace spine {
SpacingMode _spacingMode; SpacingMode _spacingMode;
RotateMode _rotateMode; RotateMode _rotateMode;
float _offsetRotation; float _offsetRotation;
float _position, _spacing, _rotateMix, _translateMix; float _position, _spacing;
float _mixRotate, _mixX, _mixY;
}; };
} }

View File

@ -27,27 +27,32 @@
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef Spine_TimelineType_h #ifndef Spine_Property_h
#define Spine_TimelineType_h #define Spine_Property_h
namespace spine { namespace spine {
enum TimelineType { typedef long long PropertyId;
TimelineType_Rotate = 0, enum Property {
TimelineType_Translate, Property_Rotate = 1 << 0,
TimelineType_Scale, Property_X = 1 << 1,
TimelineType_Shear, Property_Y = 1 << 2,
TimelineType_Attachment, Property_ScaleX = 1 << 3,
TimelineType_Color, Property_ScaleY = 1 << 4,
TimelineType_Deform, Property_ShearX = 1 << 5,
TimelineType_Event, Property_ShearY = 1 << 6,
TimelineType_DrawOrder, Property_Rgb = 1 << 7,
TimelineType_IkConstraint, Property_Alpha = 1 << 8,
TimelineType_TransformConstraint, Property_Rgb2 = 1 << 9,
TimelineType_PathConstraintPosition, Property_Attachment = 1 << 10,
TimelineType_PathConstraintSpacing, Property_Deform = 1 << 11,
TimelineType_PathConstraintMix, Property_Event = 1 << 12,
TimelineType_TwoColor Property_DrawOrder = 1 << 13,
Property_IkConstraint = 1 << 14,
Property_TransformConstraint = 1 << 15,
Property_PathConstraintPosition = 1 << 16,
Property_PathConstraintSpacing = 1 << 17,
Property_OathConstraintMix = 1 << 18
}; };
} }
#endif /* Spine_TimelineType_h */ #endif /* Spine_Property_h */

View File

@ -54,7 +54,7 @@ namespace spine {
void updateOffset(); void updateOffset();
void setUVs(float u, float v, float u2, float v2, bool rotate); void setUVs(float u, float v, float u2, float v2, float degrees);
/// Transforms the attachment's four vertices to world coordinates. /// Transforms the attachment's four vertices to world coordinates.
/// @param bone The parent bone. /// @param bone The parent bone.

View File

@ -33,7 +33,7 @@
#include <spine/CurveTimeline.h> #include <spine/CurveTimeline.h>
namespace spine { namespace spine {
class SP_API RotateTimeline : public CurveTimeline { class SP_API RotateTimeline : public CurveTimeline1 {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
friend class AnimationState; friend class AnimationState;
@ -41,29 +41,15 @@ namespace spine {
RTTI_DECL RTTI_DECL
public: public:
static const int ENTRIES = 2; explicit RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
explicit RotateTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); int getBoneIndex() { return _boneIndex; }
/// Sets the time and value of the specified keyframe.
void setFrame(int frameIndex, float time, float degrees);
int getBoneIndex();
void setBoneIndex(int inValue);
Vector<float>& getFrames();
void setBoneIndex(int inValue) { _boneIndex = inValue; }
private: private:
static const int PREV_TIME = -2;
static const int PREV_ROTATION = -1;
static const int ROTATION = 1;
int _boneIndex; int _boneIndex;
Vector<float> _frames; // time, angle, ...
}; };
} }

View File

@ -33,19 +33,65 @@
#include <spine/TranslateTimeline.h> #include <spine/TranslateTimeline.h>
namespace spine { namespace spine {
class SP_API ScaleTimeline : public TranslateTimeline { class SP_API ScaleTimeline : public CurveTimeline2 {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL RTTI_DECL
public: public:
explicit ScaleTimeline(int frameCount); explicit ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
virtual ~ScaleTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); int getBoneIndex() { return _boneIndex; }
void setBoneIndex(int inValue) { _boneIndex = inValue; }
private:
int _boneIndex;
}; };
class SP_API ScaleXTimeline : public CurveTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
virtual ~ScaleXTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
int getBoneIndex() { return _boneIndex; }
void setBoneIndex(int inValue) { _boneIndex = inValue; }
private:
int _boneIndex;
};
class SP_API ScaleYTimeline : public CurveTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
virtual ~ScaleYTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
int getBoneIndex() { return _boneIndex; }
void setBoneIndex(int inValue) { _boneIndex = inValue; }
private:
int _boneIndex;
};
} }
#endif /* Spine_ScaleTimeline_h */ #endif /* Spine_ScaleTimeline_h */

View File

@ -82,12 +82,22 @@ class SP_API Skeleton : public SpineObject {
friend class ScaleTimeline; friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline; friend class ShearTimeline;
friend class TransformConstraintTimeline; friend class TransformConstraintTimeline;
friend class RotateTimeline;
friend class TranslateTimeline; friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class TwoColorTimeline; friend class TwoColorTimeline;
public: public:
@ -104,6 +114,8 @@ public:
/// Updates the world transform for each bone and applies constraints. /// Updates the world transform for each bone and applies constraints.
void updateWorldTransform(); void updateWorldTransform();
void updateWorldTransform(Bone* parent);
/// Sets the bones, constraints, and slots to their setup pose values. /// Sets the bones, constraints, and slots to their setup pose values.
void setToSetupPose(); void setToSetupPose();
@ -217,7 +229,6 @@ private:
Vector<TransformConstraint *> _transformConstraints; Vector<TransformConstraint *> _transformConstraints;
Vector<PathConstraint *> _pathConstraints; Vector<PathConstraint *> _pathConstraints;
Vector<Updatable *> _updateCache; Vector<Updatable *> _updateCache;
Vector<Bone *> _updateCacheReset;
Skin *_skin; Skin *_skin;
Color _color; Color _color;
float _time; float _time;

View File

@ -34,7 +34,8 @@ namespace spine {
enum SpacingMode { enum SpacingMode {
SpacingMode_Length = 0, SpacingMode_Length = 0,
SpacingMode_Fixed, SpacingMode_Fixed,
SpacingMode_Percent SpacingMode_Percent,
SpacingMode_Proportional
}; };
} }

View File

@ -35,6 +35,7 @@
#include <spine/MixBlend.h> #include <spine/MixBlend.h>
#include <spine/MixDirection.h> #include <spine/MixDirection.h>
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
#include <spine/Property.h>
namespace spine { namespace spine {
class Skeleton; class Skeleton;
@ -45,7 +46,7 @@ class SP_API Timeline : public SpineObject {
RTTI_DECL RTTI_DECL
public: public:
Timeline(); Timeline(size_t frameCount, size_t frameEntries);
virtual ~Timeline(); virtual ~Timeline();
@ -63,7 +64,22 @@ public:
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend, apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
MixDirection direction) = 0; MixDirection direction) = 0;
virtual int getPropertyId() = 0; size_t getFrameEntries();
size_t getFrameCount();
Vector<float> &getFrames();
float getDuration();
virtual Vector<PropertyId> &getPropertyIds();
protected:
void setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount);
Vector<PropertyId> _propertyIds;
Vector<float> _frames;
size_t _frameEntries;
}; };
} }

View File

@ -48,8 +48,6 @@ namespace spine {
public: public:
TransformConstraint(TransformConstraintData& data, Skeleton& skeleton); TransformConstraint(TransformConstraintData& data, Skeleton& skeleton);
void apply();
virtual void update(); virtual void update();
virtual int getOrder(); virtual int getOrder();
@ -61,17 +59,23 @@ namespace spine {
Bone* getTarget(); Bone* getTarget();
void setTarget(Bone* inValue); void setTarget(Bone* inValue);
float getRotateMix(); float getMixRotate();
void setRotateMix(float inValue); void setMixRotate(float inValue);
float getTranslateMix(); float getMixX();
void setTranslateMix(float inValue); void setMixX(float inValue);
float getScaleMix(); float getMixY();
void setScaleMix(float inValue); void setMixY(float inValue);
float getShearMix(); float getMixScaleX();
void setShearMix(float inValue); void setMixScaleX(float inValue);
float getMixScaleY();
void setMixScaleY(float inValue);
float getMixShearY();
void setMixShearY(float inValue);
bool isActive(); bool isActive();
@ -81,8 +85,8 @@ namespace spine {
TransformConstraintData& _data; TransformConstraintData& _data;
Vector<Bone*> _bones; Vector<Bone*> _bones;
Bone* _target; Bone* _target;
float _rotateMix, _translateMix, _scaleMix, _shearMix; float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY;
bool _active; bool _active;
void applyAbsoluteWorld(); void applyAbsoluteWorld();

View File

@ -51,10 +51,12 @@ namespace spine {
Vector<BoneData*>& getBones(); Vector<BoneData*>& getBones();
BoneData* getTarget(); BoneData* getTarget();
float getRotateMix(); float getMixRotate();
float getTranslateMix(); float getMixX();
float getScaleMix(); float getMixY();
float getShearMix(); float getMixScaleX();
float getMixScaleY();
float getMixShearY();
float getOffsetRotation(); float getOffsetRotation();
float getOffsetX(); float getOffsetX();
@ -69,7 +71,7 @@ namespace spine {
private: private:
Vector<BoneData*> _bones; Vector<BoneData*> _bones;
BoneData* _target; BoneData* _target;
float _rotateMix, _translateMix, _scaleMix, _shearMix; float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY;
float _offsetRotation, _offsetX, _offsetY, _offsetScaleX, _offsetScaleY, _offsetShearY; float _offsetRotation, _offsetX, _offsetY, _offsetScaleX, _offsetScaleY, _offsetShearY;
bool _relative, _local; bool _relative, _local;
}; };

View File

@ -33,40 +33,69 @@
#include <spine/CurveTimeline.h> #include <spine/CurveTimeline.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
namespace spine { namespace spine {
class SP_API TranslateTimeline : public CurveTimeline { class SP_API TranslateTimeline : public CurveTimeline2 {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL RTTI_DECL
public: public:
static const int ENTRIES; explicit TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
explicit TranslateTimeline(int frameCount);
virtual ~TranslateTimeline(); virtual ~TranslateTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); int getBoneIndex() { return _boneIndex; }
/// Sets the time and value of the specified keyframe. void setBoneIndex(int inValue) { _boneIndex = inValue; }
void setFrame(int frameIndex, float time, float x, float y); private:
int _boneIndex;
protected:
static const int PREV_TIME;
static const int PREV_X;
static const int PREV_Y;
static const int X;
static const int Y;
Vector<float> _frames;
int _boneIndex;
}; };
class SP_API TranslateXTimeline : public CurveTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
virtual ~TranslateXTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
int getBoneIndex() { return _boneIndex; }
void setBoneIndex(int inValue) { _boneIndex = inValue; }
private:
int _boneIndex;
};
class SP_API TranslateYTimeline : public CurveTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
virtual ~TranslateYTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
int getBoneIndex() { return _boneIndex; }
void setBoneIndex(int inValue) { _boneIndex = inValue; }
private:
int _boneIndex;
};
} }
#endif /* Spine_TranslateTimeline_h */ #endif /* Spine_TranslateTimeline_h */

View File

@ -95,7 +95,7 @@
#include <spine/SpineString.h> #include <spine/SpineString.h>
#include <spine/TextureLoader.h> #include <spine/TextureLoader.h>
#include <spine/Timeline.h> #include <spine/Timeline.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/TransformConstraint.h> #include <spine/TransformConstraint.h>
#include <spine/TransformConstraintData.h> #include <spine/TransformConstraintData.h>
#include <spine/TransformConstraintTimeline.h> #include <spine/TransformConstraintTimeline.h>

View File

@ -48,12 +48,18 @@ Animation::Animation(const String &name, Vector<Timeline *> &timelines, float du
_duration(duration), _duration(duration),
_name(name) { _name(name) {
assert(_name.length() > 0); assert(_name.length() > 0);
for (int i = 0; i < (int)timelines.size(); i++) for (size_t i = 0; i < timelines.size(); i++) {
_timelineIds.put(timelines[i]->getPropertyId(), true); Vector<PropertyId> propertyIds = timelines[i]->getPropertyIds();
for (size_t ii = 0; ii < propertyIds.size(); ii++)
_timelineIds.put(propertyIds[ii], true);
}
} }
bool Animation::hasTimeline(int id) { bool Animation::hasTimeline(Vector<PropertyId> ids) {
return _timelineIds.containsKey(id); for (size_t i = 0; i < ids.size(); i++) {
if (_timelineIds.containsKey(ids[i])) return true;
}
return false;
} }
Animation::~Animation() { Animation::~Animation() {
@ -91,52 +97,17 @@ void Animation::setDuration(float inValue) {
_duration = inValue; _duration = inValue;
} }
int Animation::binarySearch(Vector<float> &values, float target, int step) { int Animation::search(Vector<float> &frames, float target) {
int low = 0; size_t n = (int)frames.size();
int size = (int)values.size(); for (size_t i = 1; i < n; i++) {
int high = size / step - 2; if (frames[i] > target) return i - 1;
if (high == 0) { }
return step; return n - 1;
}
int current = (int) (static_cast<uint32_t>(high) >> 1);
while (true) {
if (values[(current + 1) * step] <= target)
low = current + 1;
else
high = current;
if (low == high) return (low + 1) * step;
current = (int) (static_cast<uint32_t>(low + high) >> 1);
}
} }
int Animation::binarySearch(Vector<float> &values, float target) { int Animation::search(Vector<float> &frames, float target, int step) {
int low = 0; size_t n = frames.size();
int size = (int)values.size(); for (size_t i = step; i < n; i += step)
int high = size - 2; if (frames[i] > target) return i - step;
if (high == 0) return 1; return n - step;
int current = (int) (static_cast<uint32_t>(high) >> 1);
while (true) {
if (values[(current + 1)] <= target)
low = current + 1;
else
high = current;
if (low == high) return (low + 1);
current = (int) (static_cast<uint32_t>(low + high) >> 1);
}
}
int Animation::linearSearch(Vector<float> &values, float target, int step) {
for (int i = 0, last = (int)values.size() - step; i <= last; i += step) {
if (values[i] > target) {
return i;
}
}
return -1;
} }

View File

@ -38,7 +38,7 @@
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/Bone.h> #include <spine/Bone.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>

View File

@ -38,7 +38,7 @@
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/Bone.h> #include <spine/Bone.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>

View File

@ -39,89 +39,111 @@ using namespace spine;
RTTI_IMPL(CurveTimeline, Timeline) RTTI_IMPL(CurveTimeline, Timeline)
const float CurveTimeline::LINEAR = 0; CurveTimeline::CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount): Timeline(frameCount, frameEntries) {
const float CurveTimeline::STEPPED = 1; _curves.setSize(frameCount + bezierCount * BEZIER_SIZE, 0);
const float CurveTimeline::BEZIER = 2; _curves[frameCount - 1] = STEPPED;
const int CurveTimeline::BEZIER_SIZE = 10 * 2 - 1;
CurveTimeline::CurveTimeline(int frameCount) {
assert(frameCount > 0);
_curves.setSize((frameCount - 1) * BEZIER_SIZE, 0);
} }
CurveTimeline::~CurveTimeline() { CurveTimeline::~CurveTimeline() {
} }
size_t CurveTimeline::getFrameCount() { void CurveTimeline::setLinear(size_t frame) {
return _curves.size() / BEZIER_SIZE + 1; _curves[frame] = LINEAR;
} }
void CurveTimeline::setLinear(size_t frameIndex) { void CurveTimeline::setStepped(size_t frame) {
_curves[frameIndex * BEZIER_SIZE] = LINEAR; _curves[frame] = STEPPED;
} }
void CurveTimeline::setStepped(size_t frameIndex) { void CurveTimeline::setBezier (size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2, float time2, float value2) {
_curves[frameIndex * BEZIER_SIZE] = STEPPED; size_t i = getFrameCount() + bezier * BEZIER_SIZE;
if (value == 0) _curves[frame] = BEZIER + i;
float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03;
float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006;
float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;
float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667;
float x = time1 + dx, y = value1 + dy;
for (size_t n = i + BEZIER_SIZE; i < n; i += 2) {
_curves[i] = x;
_curves[i + 1] = y;
dx += ddx;
dy += ddy;
ddx += dddx;
ddy += dddy;
x += dx;
y += dy;
}
} }
void CurveTimeline::setCurve(size_t frameIndex, float cx1, float cy1, float cx2, float cy2) { float CurveTimeline::getBezierValue(float time, size_t frame, size_t valueOffset, size_t i) {
float tmpx = (-cx1 * 2 + cx2) * 0.03f, tmpy = (-cy1 * 2 + cy2) * 0.03f; if (_curves[i] > time) {
float dddfx = ((cx1 - cx2) * 3 + 1) * 0.006f, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006f; float x = _frames[frame], y = _frames[frame + valueOffset];
float ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y);
float dfx = cx1 * 0.3f + tmpx + dddfx * 0.16666667f, dfy = cy1 * 0.3f + tmpy + dddfy * 0.16666667f; }
size_t n = i + BEZIER_SIZE;
size_t i = frameIndex * BEZIER_SIZE; for (i += 2; i < n; i += 2) {
_curves[i++] = BEZIER; if (_curves[i] >= time) {
float x = _curves[i - 2], y = _curves[i - 1];
float x = dfx, y = dfy; return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y);
for (size_t n = i + BEZIER_SIZE - 1; i < n; i += 2) { }
_curves[i] = x; }
_curves[i + 1] = y; frame += getFrameEntries();
dfx += ddfx; float x = _curves[n - 2], y = _curves[n - 1];
dfy += ddfy; return y + (time - x) / (_frames[frame] - x) * (_frames[frame + valueOffset] - y);
ddfx += dddfx;
ddfy += dddfy;
x += dfx;
y += dfy;
}
} }
float CurveTimeline::getCurvePercent(size_t frameIndex, float percent) { RTTI_IMPL(CurveTimeline1, CurveTimeline)
percent = MathUtil::clamp(percent, 0, 1); const int CurveTimeline1::ENTRIES = 2;
size_t i = frameIndex * BEZIER_SIZE; const int CurveTimeline1::VALUE = 1;
float type = _curves[i];
if (type == LINEAR) { CurveTimeline1::CurveTimeline1(size_t frameCount, size_t bezierCount): CurveTimeline(frameCount, CurveTimeline1::ENTRIES, bezierCount) {
return percent;
}
if (type == STEPPED) {
return 0;
}
i++;
float x = 0;
for (size_t start = i, n = i + BEZIER_SIZE - 1; i < n; i += 2) {
x = _curves[i];
if (x >= percent) {
float prevX, prevY;
if (i == start) {
prevX = 0;
prevY = 0;
} else {
prevX = _curves[i - 2];
prevY = _curves[i - 1];
}
return prevY + (_curves[i + 1] - prevY) * (percent - prevX) / (x - prevX);
}
}
float y = _curves[i - 1];
return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1.
} }
float CurveTimeline::getCurveType(size_t frameIndex) { CurveTimeline1::~CurveTimeline1() {
return _curves[frameIndex * BEZIER_SIZE]; }
void CurveTimeline1::setFrame(size_t frame, float time, float value) {
frame <<= 1;
_frames[frame] = time;
_frames[frame + CurveTimeline1::VALUE] = value;
}
float CurveTimeline1::getCurveValue(float time) {
int i = _frames.size() - 2;
for (int ii = 2; ii <= i; ii += 2) {
if (_frames[ii] > time) {
i = ii - 2;
break;
}
}
int curveType = (int)_curves[i >> 1];
switch (curveType) {
case CurveTimeline::LINEAR: {
float before = _frames[i], value = _frames[i + CurveTimeline1::VALUE];
return value + (time - before) / (_frames[i + CurveTimeline1::ENTRIES] - before) *
(_frames[i + CurveTimeline1::ENTRIES + CurveTimeline1::VALUE] - value);
}
case CurveTimeline::STEPPED:
return _frames[i + CurveTimeline1::VALUE];
}
return getBezierValue(time, i, CurveTimeline1::VALUE, curveType - CurveTimeline1::BEZIER);
}
RTTI_IMPL(CurveTimeline2, CurveTimeline)
const int CurveTimeline2::ENTRIES = 3;
const int CurveTimeline2::VALUE1 = 1;
const int CurveTimeline2::VALUE2 = 2;
CurveTimeline2::CurveTimeline2(size_t frameCount, size_t bezierCount): CurveTimeline(frameCount, CurveTimeline2::ENTRIES, bezierCount) {
}
CurveTimeline2::~CurveTimeline2() {
}
void CurveTimeline2::setFrame(size_t frame, float time, float value1, float value2) {
frame *= CurveTimeline2::ENTRIES;
_frames[frame] = time;
_frames[frame + CurveTimeline2::VALUE1] = value1;
_frames[frame + CurveTimeline2::VALUE2] = value2;
} }

View File

@ -39,7 +39,7 @@
#include <spine/VertexAttachment.h> #include <spine/VertexAttachment.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/Bone.h> #include <spine/Bone.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>

View File

@ -37,7 +37,7 @@
#include <spine/Event.h> #include <spine/Event.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>

View File

@ -37,7 +37,7 @@
#include <spine/Event.h> #include <spine/Event.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>
#include <spine/EventData.h> #include <spine/EventData.h>

View File

@ -101,10 +101,6 @@ void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY
Bone *pp = parent.getParent(); Bone *pp = parent.getParent();
float tx, ty, dx, dy, dd, l1, l2, a1, a2, r, td, sd, p; float tx, ty, dx, dy, dd, l1, l2, a1, a2, r, td, sd, p;
float id, x, y; float id, x, y;
if (alpha == 0) {
child.updateWorldTransform();
return;
}
if (!parent._appliedValid) parent.updateAppliedTransform(); if (!parent._appliedValid) parent.updateAppliedTransform();
if (!child._appliedValid) child.updateAppliedTransform(); if (!child._appliedValid) child.updateAppliedTransform();
px = parent._ax; px = parent._ax;
@ -268,12 +264,8 @@ IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatab
} }
} }
/// Applies the constraint to the constrained bones.
void IkConstraint::apply() {
update();
}
void IkConstraint::update() { void IkConstraint::update() {
if (_mix == 0) return;
switch (_bones.size()) { switch (_bones.size()) {
case 1: { case 1: {
Bone *bone0 = _bones[0]; Bone *bone0 = _bones[0];

View File

@ -37,7 +37,7 @@
#include <spine/Event.h> #include <spine/Event.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>
#include <spine/IkConstraint.h> #include <spine/IkConstraint.h>

View File

@ -57,8 +57,9 @@ PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : U
data.getTarget()->getName())), data.getTarget()->getName())),
_position(data.getPosition()), _position(data.getPosition()),
_spacing(data.getSpacing()), _spacing(data.getSpacing()),
_rotateMix(data.getRotateMix()), _mixRotate(data.getMixRotate()),
_translateMix(data.getTranslateMix()), _mixX(data.getMixX()),
_mixY(data.getMixY()),
_active(false) _active(false)
{ {
_bones.ensureCapacity(_data.getBones().size()); _bones.ensureCapacity(_data.getBones().size());
@ -70,77 +71,95 @@ PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : U
_segments.setSize(10, 0); _segments.setSize(10, 0);
} }
void PathConstraint::apply() {
update();
}
void PathConstraint::update() { void PathConstraint::update() {
Attachment *baseAttachment = _target->getAttachment(); Attachment *baseAttachment = _target->getAttachment();
if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) { if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) {
return; return;
} }
PathAttachment *attachment = static_cast<PathAttachment *>(baseAttachment); PathAttachment *attachment = static_cast<PathAttachment *>(baseAttachment);
float rotateMix = _rotateMix; float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY;
float translateMix = _translateMix; if (mixRotate == 0 && mixX == 0 && mixY == 0) return;
bool translate = translateMix > 0;
bool rotate = rotateMix > 0;
if (!translate && !rotate) {
return;
}
PathConstraintData &data = _data; PathConstraintData &data = _data;
bool percentSpacing = data._spacingMode == SpacingMode_Percent; bool tangents = data._rotateMode == RotateMode_Tangent, scale = data._rotateMode == RotateMode_ChainScale;
RotateMode rotateMode = data._rotateMode;
bool tangents = rotateMode == RotateMode_Tangent, scale = rotateMode == RotateMode_ChainScale;
size_t boneCount = _bones.size(); size_t boneCount = _bones.size();
size_t spacesCount = tangents ? boneCount : boneCount + 1; size_t spacesCount = tangents ? boneCount : boneCount + 1;
_spaces.setSize(spacesCount, 0); _spaces.setSize(spacesCount, 0);
if (scale) _lengths.setSize(boneCount, 0);
float spacing = _spacing; float spacing = _spacing;
if (scale || !percentSpacing) {
if (scale) _lengths.setSize(boneCount, 0);
bool lengthSpacing = data._spacingMode == SpacingMode_Length;
for (size_t i = 0, n = spacesCount - 1; i < n;) { switch(data._spacingMode) {
Bone *boneP = _bones[i]; case SpacingMode_Percent: {
Bone &bone = *boneP; if (scale) {
float setupLength = bone._data.getLength(); for (size_t i = 0, n = spacesCount - 1; i < n; i++) {
if (setupLength < PathConstraint::EPSILON) { Bone *boneP = _bones[i];
if (scale) _lengths[i] = 0; Bone &bone = *boneP;
_spaces[++i] = 0; float setupLength = bone._data.getLength();
} else if (percentSpacing) { if (setupLength < PathConstraint::EPSILON) {
if (scale) { _lengths[i] = 0;
float x = setupLength * bone._a, y = setupLength * bone._c; } else {
float length = MathUtil::sqrt(x * x + y * y); float x = setupLength * bone._a, y = setupLength * bone._c;
_lengths[i] = length; _lengths[i] = MathUtil::sqrt(x * x + y * y);
} }
_spaces[++i] = spacing; }
} else { }
float x = setupLength * bone._a; for (size_t i = 1; i < spacesCount; ++i) {
float y = setupLength * bone._c; _spaces[i] = spacing;
float length = MathUtil::sqrt(x * x + y * y); }
if (scale) { break;
_lengths[i] = length; }
} case SpacingMode_Proportional: {
float sum = 0;
_spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; for (size_t i = 0; i < boneCount;) {
} Bone *boneP = _bones[i];
} Bone &bone = *boneP;
} else { float setupLength = bone._data.getLength();
for (size_t i = 1; i < spacesCount; ++i) { if (setupLength < PathConstraint::EPSILON) {
_spaces[i] = spacing; if (scale) _lengths[i] = 0;
} _spaces[++i] = spacing;
} else {
float x = setupLength * bone._a, y = setupLength * bone._c;
float length = MathUtil::sqrt(x * x + y * y);
if (scale) _lengths[i] = length;
_spaces[++i] = length;
sum += length;
}
}
if (sum > 0) {
sum = spacesCount / sum * spacing;
for (size_t i = 1; i < spacesCount; i++) {
_spaces[i] *= sum;
}
}
break;
}
default: {
bool lengthSpacing = data._spacingMode == SpacingMode_Length;
for (size_t i = 0, n = spacesCount - 1; i < n;) {
Bone *boneP = _bones[i];
Bone &bone = *boneP;
float setupLength = bone._data.getLength();
if (setupLength < PathConstraint::EPSILON) {
if (scale) _lengths[i] = 0;
_spaces[++i] = spacing;
} else {
float x = setupLength * bone._a, y = setupLength * bone._c;
float length = MathUtil::sqrt(x * x + y * y);
if (scale) _lengths[i] = length;
_spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;
}
}
}
} }
Vector<float>& positions = computeWorldPositions(*attachment, spacesCount, tangents, Vector<float>& positions = computeWorldPositions(*attachment, spacesCount, tangents);
data.getPositionMode() == PositionMode_Percent, percentSpacing);
float boneX = positions[0]; float boneX = positions[0];
float boneY = positions[1]; float boneY = positions[1];
float offsetRotation = data.getOffsetRotation(); float offsetRotation = data.getOffsetRotation();
bool tip; bool tip;
if (offsetRotation == 0) { if (offsetRotation == 0) {
tip = rotateMode == RotateMode_Chain; tip = data._rotateMode == RotateMode_Chain;
} else { } else {
tip = false; tip = false;
Bone &p = _target->getBone(); Bone &p = _target->getBone();
@ -150,8 +169,8 @@ void PathConstraint::update() {
for (size_t i = 0, p = 3; i < boneCount; i++, p += 3) { for (size_t i = 0, p = 3; i < boneCount; i++, p += 3) {
Bone *boneP = _bones[i]; Bone *boneP = _bones[i];
Bone &bone = *boneP; Bone &bone = *boneP;
bone._worldX += (boneX - bone._worldX) * translateMix; bone._worldX += (boneX - bone._worldX) * mixX;
bone._worldY += (boneY - bone._worldY) * translateMix; bone._worldY += (boneY - bone._worldY) * mixY;
float x = positions[p]; float x = positions[p];
float y = positions[p + 1]; float y = positions[p + 1];
float dx = x - boneX; float dx = x - boneX;
@ -159,7 +178,7 @@ void PathConstraint::update() {
if (scale) { if (scale) {
float length = _lengths[i]; float length = _lengths[i];
if (length >= PathConstraint::EPSILON) { if (length >= PathConstraint::EPSILON) {
float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1; float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1;
bone._a *= s; bone._a *= s;
bone._c *= s; bone._c *= s;
} }
@ -168,7 +187,7 @@ void PathConstraint::update() {
boneX = x; boneX = x;
boneY = y; boneY = y;
if (rotate) { if (mixRotate > 0) {
float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin; float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin;
if (tangents) if (tangents)
r = positions[p - 1]; r = positions[p - 1];
@ -183,8 +202,8 @@ void PathConstraint::update() {
cos = MathUtil::cos(r); cos = MathUtil::cos(r);
sin = MathUtil::sin(r); sin = MathUtil::sin(r);
float length = bone._data.getLength(); float length = bone._data.getLength();
boneX += (length * (cos * a - sin * c) - dx) * rotateMix; boneX += (length * (cos * a - sin * c) - dx) * mixRotate;
boneY += (length * (sin * a + cos * c) - dy) * rotateMix; boneY += (length * (sin * a + cos * c) - dy) * mixRotate;
} else } else
r += offsetRotation; r += offsetRotation;
@ -193,7 +212,7 @@ void PathConstraint::update() {
else if (r < -MathUtil::Pi) else if (r < -MathUtil::Pi)
r += MathUtil::Pi_2; r += MathUtil::Pi_2;
r *= rotateMix; r *= mixRotate;
cos = MathUtil::cos(r); cos = MathUtil::cos(r);
sin = MathUtil::sin(r); sin = MathUtil::sin(r);
bone._a = cos * a - sin * c; bone._a = cos * a - sin * c;
@ -226,20 +245,28 @@ void PathConstraint::setSpacing(float inValue) {
_spacing = inValue; _spacing = inValue;
} }
float PathConstraint::getRotateMix() { float PathConstraint::getMixRotate() {
return _rotateMix; return _mixRotate;
} }
void PathConstraint::setRotateMix(float inValue) { void PathConstraint::setMixRotate(float inValue) {
_rotateMix = inValue; _mixRotate = inValue;
} }
float PathConstraint::getTranslateMix() { float PathConstraint::getMixX() {
return _translateMix; return _mixX;
} }
void PathConstraint::setTranslateMix(float inValue) { void PathConstraint::setMixX(float inValue) {
_translateMix = inValue; _mixX = inValue;
}
float PathConstraint::getMixY() {
return _mixY;
}
void PathConstraint::setMixY(float inValue) {
_mixY = inValue;
} }
Vector<Bone *> &PathConstraint::getBones() { Vector<Bone *> &PathConstraint::getBones() {
@ -259,7 +286,7 @@ PathConstraintData &PathConstraint::getData() {
} }
Vector<float>& Vector<float>&
PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) { PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents) {
Slot &target = *_target; Slot &target = *_target;
float position = _position; float position = _position;
_positions.setSize(spacesCount * 3 + 2, 0); _positions.setSize(spacesCount * 3 + 2, 0);
@ -275,16 +302,23 @@ PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, boo
Vector<float> &lengths = path.getLengths(); Vector<float> &lengths = path.getLengths();
curveCount -= closed ? 1 : 2; curveCount -= closed ? 1 : 2;
pathLength = lengths[curveCount]; pathLength = lengths[curveCount];
if (percentPosition) position *= pathLength; if (_data._positionMode == PositionMode_Percent) position *= pathLength;
if (percentSpacing) { float multiplier = 0;
for (int i = 1; i < spacesCount; ++i) switch (_data._spacingMode) {
_spaces[i] *= pathLength; case SpacingMode_Percent:
} multiplier = pathLength;
break;
case SpacingMode_Proportional:
multiplier = pathLength / spacesCount;
break;
default:
multiplier = 1;
}
world.setSize(8, 0); world.setSize(8, 0);
for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {
float space = _spaces[i]; float space = _spaces[i] * multiplier;
position += space; position += space;
float p = position; float p = position;
@ -393,19 +427,23 @@ PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, boo
y1 = y2; y1 = y2;
} }
if (percentPosition) if (_data._positionMode == PositionMode_Percent) position *= pathLength;
position *= pathLength;
else
position *= pathLength / path.getLengths()[curveCount - 1];
if (percentSpacing) { float multiplier = 0;
for (int i = 1; i < spacesCount; ++i) switch (_data._spacingMode) {
_spaces[i] *= pathLength; case SpacingMode_Percent:
} multiplier = pathLength;
break;
case SpacingMode_Proportional:
multiplier = pathLength / spacesCount;
break;
default:
multiplier = 1;
}
float curveLength = 0; float curveLength = 0;
for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {
float space = _spaces[i]; float space = _spaces[i] * multiplier;
position += space; position += space;
float p = position; float p = position;

View File

@ -41,90 +41,99 @@
using namespace spine; using namespace spine;
PathConstraintData::PathConstraintData(const String &name) : PathConstraintData::PathConstraintData(const String &name) :
ConstraintData(name), ConstraintData(name),
_target(NULL), _target(NULL),
_positionMode(PositionMode_Fixed), _positionMode(PositionMode_Fixed),
_spacingMode(SpacingMode_Length), _spacingMode(SpacingMode_Length),
_rotateMode(RotateMode_Tangent), _rotateMode(RotateMode_Tangent),
_offsetRotation(0), _offsetRotation(0),
_position(0), _position(0),
_spacing(0), _spacing(0),
_rotateMix(0), _mixRotate(0),
_translateMix(0) { _mixX(0),
_mixY(0) {
} }
Vector<BoneData *> &PathConstraintData::getBones() { Vector<BoneData *> &PathConstraintData::getBones() {
return _bones; return _bones;
} }
SlotData *PathConstraintData::getTarget() { SlotData *PathConstraintData::getTarget() {
return _target; return _target;
} }
void PathConstraintData::setTarget(SlotData *inValue) { void PathConstraintData::setTarget(SlotData *inValue) {
_target = inValue; _target = inValue;
} }
PositionMode PathConstraintData::getPositionMode() { PositionMode PathConstraintData::getPositionMode() {
return _positionMode; return _positionMode;
} }
void PathConstraintData::setPositionMode(PositionMode inValue) { void PathConstraintData::setPositionMode(PositionMode inValue) {
_positionMode = inValue; _positionMode = inValue;
} }
SpacingMode PathConstraintData::getSpacingMode() { SpacingMode PathConstraintData::getSpacingMode() {
return _spacingMode; return _spacingMode;
} }
void PathConstraintData::setSpacingMode(SpacingMode inValue) { void PathConstraintData::setSpacingMode(SpacingMode inValue) {
_spacingMode = inValue; _spacingMode = inValue;
} }
RotateMode PathConstraintData::getRotateMode() { RotateMode PathConstraintData::getRotateMode() {
return _rotateMode; return _rotateMode;
} }
void PathConstraintData::setRotateMode(RotateMode inValue) { void PathConstraintData::setRotateMode(RotateMode inValue) {
_rotateMode = inValue; _rotateMode = inValue;
} }
float PathConstraintData::getOffsetRotation() { float PathConstraintData::getOffsetRotation() {
return _offsetRotation; return _offsetRotation;
} }
void PathConstraintData::setOffsetRotation(float inValue) { void PathConstraintData::setOffsetRotation(float inValue) {
_offsetRotation = inValue; _offsetRotation = inValue;
} }
float PathConstraintData::getPosition() { float PathConstraintData::getPosition() {
return _position; return _position;
} }
void PathConstraintData::setPosition(float inValue) { void PathConstraintData::setPosition(float inValue) {
_position = inValue; _position = inValue;
} }
float PathConstraintData::getSpacing() { float PathConstraintData::getSpacing() {
return _spacing; return _spacing;
} }
void PathConstraintData::setSpacing(float inValue) { void PathConstraintData::setSpacing(float inValue) {
_spacing = inValue; _spacing = inValue;
} }
float PathConstraintData::getRotateMix() { float PathConstraintData::getMixRotate() {
return _rotateMix; return _mixRotate;
} }
void PathConstraintData::setRotateMix(float inValue) { void PathConstraintData::setMixRotate(float inValue) {
_rotateMix = inValue; _mixRotate = inValue;
} }
float PathConstraintData::getTranslateMix() { float PathConstraintData::getMixX() {
return _translateMix; return _mixX;
} }
void PathConstraintData::setTranslateMix(float inValue) { void PathConstraintData::setMixX(float inValue) {
_translateMix = inValue; _mixX = inValue;
}
float PathConstraintData::getMixY() {
return _mixY;
}
void PathConstraintData::setMixY(float inValue) {
_mixY = inValue;
} }

View File

@ -37,7 +37,7 @@
#include <spine/Event.h> #include <spine/Event.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>
#include <spine/PathConstraint.h> #include <spine/PathConstraint.h>

View File

@ -37,7 +37,7 @@
#include <spine/Event.h> #include <spine/Event.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>
#include <spine/PathConstraint.h> #include <spine/PathConstraint.h>

View File

@ -37,7 +37,7 @@
#include <spine/Event.h> #include <spine/Event.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>
#include <spine/PathConstraint.h> #include <spine/PathConstraint.h>

View File

@ -103,8 +103,8 @@ void RegionAttachment::updateOffset() {
_vertexOffset[BRY] = localYCos + localX2Sin; _vertexOffset[BRY] = localYCos + localX2Sin;
} }
void RegionAttachment::setUVs(float u, float v, float u2, float v2, bool rotate) { void RegionAttachment::setUVs(float u, float v, float u2, float v2, float degrees) {
if (rotate) { if (degrees == 90) {
_uvs[URX] = u; _uvs[URX] = u;
_uvs[URY] = v2; _uvs[URY] = v2;
_uvs[BRX] = u; _uvs[BRX] = u;

View File

@ -39,101 +39,48 @@
#include <spine/Bone.h> #include <spine/Bone.h>
#include <spine/BoneData.h> #include <spine/BoneData.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
using namespace spine; using namespace spine;
RTTI_IMPL(RotateTimeline, CurveTimeline) RTTI_IMPL(RotateTimeline, CurveTimeline1)
RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
_frames.setSize(frameCount << 1, 0); PropertyId ids[] = { ((PropertyId)Property_Rotate << 32) | boneIndex };
setPropertyIds(ids, 1);
} }
void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixBlend blend, MixDirection direction MixBlend blend, MixDirection direction
) { ) {
SP_UNUSED(lastTime); SP_UNUSED(lastTime);
SP_UNUSED(pEvents); SP_UNUSED(pEvents);
SP_UNUSED(direction); SP_UNUSED(direction);
Bone *bone = skeleton.getBones()[_boneIndex]; Bone* bone = skeleton._bones[_boneIndex];
if (!bone->_active) return; if (!bone->_active) return;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (blend) { switch (blend) {
case MixBlend_Setup: { case MixBlend_Setup:
bone->_rotation = bone->_data._rotation; bone->_rotation = bone->_data._rotation;
break; return;
} case MixBlend_First:
case MixBlend_First: { bone->_rotation += (bone->_data._rotation - bone->_rotation) * alpha;
float r = bone->_data._rotation - bone->_rotation; default: {}
bone->_rotation += (r - (16384 - (int) (16384.499999999996 - r / 360)) * 360) * alpha; }
break; return;
} }
default: {
// TODO?
break;
}
}
return;
}
if (time >= _frames[_frames.size() - ENTRIES]) { float r = getCurveValue(time);
float r = _frames[_frames.size() + PREV_ROTATION]; switch (blend) {
switch (blend) { case MixBlend_Setup:
case MixBlend_Setup: bone->_rotation = bone->_data._rotation + r * alpha;
bone->_rotation = bone->_data._rotation + r * alpha; break;
break; case MixBlend_First:
case MixBlend_First: case MixBlend_Replace:
case MixBlend_Replace: r += bone->_data._rotation - bone->_rotation;
r += bone->_data._rotation - bone->_rotation; case MixBlend_Add:
r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; bone->_rotation += r * alpha;
// Fall through. }
case MixBlend_Add:
bone->_rotation += r * alpha;
}
return;
}
// Interpolate between the previous frame and the current frame.
int frame = Animation::binarySearch(_frames, time, ENTRIES);
float prevRotation = _frames[frame + PREV_ROTATION];
float frameTime = _frames[frame];
float percent = getCurvePercent((frame >> 1) - 1,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
float r = _frames[frame + ROTATION] - prevRotation;
r = prevRotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * percent;
switch (blend) {
case MixBlend_Setup:
bone->_rotation = bone->_data._rotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
r += bone->_data._rotation - bone->_rotation;
// Fall through.
case MixBlend_Add:
bone->_rotation += (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha;
}
}
int RotateTimeline::getPropertyId() {
return ((int) TimelineType_Rotate << 24) + _boneIndex;
}
void RotateTimeline::setFrame(int frameIndex, float time, float degrees) {
frameIndex <<= 1;
_frames[frameIndex] = time;
_frames[frameIndex + ROTATION] = degrees;
}
int RotateTimeline::getBoneIndex() {
return _boneIndex;
}
void RotateTimeline::setBoneIndex(int inValue) {
_boneIndex = inValue;
}
Vector<float> &RotateTimeline::getFrames() {
return _frames;
} }

View File

@ -43,9 +43,12 @@
using namespace spine; using namespace spine;
RTTI_IMPL(ScaleTimeline, TranslateTimeline) RTTI_IMPL(ScaleTimeline, CurveTimeline2)
ScaleTimeline::ScaleTimeline(int frameCount) : TranslateTimeline(frameCount) { ScaleTimeline::ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, bezierCount), _boneIndex(boneIndex) {
PropertyId ids[] = { ((PropertyId)Property_ScaleX << 32) | boneIndex,
((PropertyId)Property_ScaleY << 32) | boneIndex};
setPropertyIds(ids, 2);
} }
void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
@ -54,100 +57,244 @@ void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
SP_UNUSED(lastTime); SP_UNUSED(lastTime);
SP_UNUSED(pEvents); SP_UNUSED(pEvents);
Bone *boneP = skeleton._bones[_boneIndex]; Bone *bone = skeleton._bones[_boneIndex];
Bone &bone = *boneP; if (!bone->_active) return;
if (!bone._active) return; if (time < _frames[0]) {
switch (blend) {
case MixBlend_Setup:
bone->_scaleX = bone->_data._scaleX;
bone->_scaleY = bone->_data._scaleY;
return;
case MixBlend_First:
bone->_scaleX += (bone->_data._scaleX - bone->_scaleX) * alpha;
bone->_scaleY += (bone->_data._scaleY - bone->_scaleY) * alpha;
default: {}
}
return;
}
if (time < _frames[0]) { float x, y;
switch (blend) { int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES);
case MixBlend_Setup: int curveType = (int)_curves[i / CurveTimeline2::ENTRIES];
bone._scaleX = bone._data._scaleX; switch (curveType) {
bone._scaleY = bone._data._scaleY; case CurveTimeline::LINEAR: {
return; float before = _frames[i];
case MixBlend_First: x = _frames[i + CurveTimeline2::VALUE1];
bone._scaleX += (bone._data._scaleX - bone._scaleX) * alpha; y = _frames[i + CurveTimeline2::VALUE2];
bone._scaleY += (bone._data._scaleY - bone._scaleY) * alpha; float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before);
default: {} x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t;
} y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t;
return; break;
} }
case CurveTimeline::STEPPED: {
x = _frames[i + CurveTimeline2::VALUE1];
y = _frames[i + CurveTimeline2::VALUE2];
break;
}
default: {
x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline2::BEZIER);
y = getBezierValue(time, i, CurveTimeline2::VALUE2,
curveType + CurveTimeline2::BEZIER_SIZE - CurveTimeline2::BEZIER);
}
}
x *= bone->_data._scaleX;
y *= bone->_data._scaleY;
float x, y; if (alpha == 1) {
if (time >= _frames[_frames.size() - ENTRIES]) { if (blend == MixBlend_Add) {
// Time is after last frame. bone->_scaleX += x - bone->_data._scaleX;
x = _frames[_frames.size() + PREV_X] * bone._data._scaleX; bone->_scaleY += y - bone->_data._scaleY;
y = _frames[_frames.size() + PREV_Y] * bone._data._scaleY; } else {
} else { bone->_scaleX = x;
// Interpolate between the previous frame and the current frame. bone->_scaleY = y;
int frame = Animation::binarySearch(_frames, time, ENTRIES); }
x = _frames[frame + PREV_X]; } else {
y = _frames[frame + PREV_Y]; float bx, by;
float frameTime = _frames[frame]; if (direction == MixDirection_Out) {
float percent = getCurvePercent(frame / ENTRIES - 1, switch (blend) {
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); case MixBlend_Setup:
bx = bone->_data._scaleX;
x = (x + (_frames[frame + X] - x) * percent) * bone._data._scaleX; by = bone->_data._scaleY;
y = (y + (_frames[frame + Y] - y) * percent) * bone._data._scaleY; bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
} bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
break;
if (alpha == 1) { case MixBlend_First:
if (blend == MixBlend_Add) { case MixBlend_Replace:
bone._scaleX += x - bone._data._scaleX; bx = bone->_scaleX;
bone._scaleY += y - bone._data._scaleY; by = bone->_scaleY;
} else { bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
bone._scaleX = x; bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
bone._scaleY = y; break;
} case MixBlend_Add:
} else { bx = bone->_scaleX;
// Mixing out uses sign of setup or current pose, else use sign of key. by = bone->_scaleY;
float bx, by; bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bone->_data._scaleX) * alpha;
if (direction == MixDirection_Out) { bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - bone->_data._scaleY) * alpha;
switch (blend) { }
case MixBlend_Setup: } else {
bx = bone._data._scaleX; switch (blend) {
by = bone._data._scaleY; case MixBlend_Setup:
bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; bx = MathUtil::abs(bone->_data._scaleX) * MathUtil::sign(x);
bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; by = MathUtil::abs(bone->_data._scaleY) * MathUtil::sign(y);
break; bone->_scaleX = bx + (x - bx) * alpha;
case MixBlend_First: bone->_scaleY = by + (y - by) * alpha;
case MixBlend_Replace: break;
bx = bone._scaleX; case MixBlend_First:
by = bone._scaleY; case MixBlend_Replace:
bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha; bx = MathUtil::abs(bone->_scaleX) * MathUtil::sign(x);
bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha; by = MathUtil::abs(bone->_scaleY) * MathUtil::sign(y);
break; bone->_scaleX = bx + (x - bx) * alpha;
case MixBlend_Add: bone->_scaleY = by + (y - by) * alpha;
bx = bone._scaleX; break;
by = bone._scaleY; case MixBlend_Add:
bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bone._data._scaleX) * alpha; bx = MathUtil::sign(x);
bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - bone._data._scaleY) * alpha; by = MathUtil::sign(y);
} bone->_scaleX = MathUtil::abs(bone->_scaleX) * bx + (x - MathUtil::abs(bone->_data._scaleX) * bx) * alpha;
} else { bone->_scaleY = MathUtil::abs(bone->_scaleY) * by + (y - MathUtil::abs(bone->_data._scaleY) * by) * alpha;
switch (blend) { }
case MixBlend_Setup: }
bx = MathUtil::abs(bone._data._scaleX) * MathUtil::sign(x); }
by = MathUtil::abs(bone._data._scaleY) * MathUtil::sign(y);
bone._scaleX = bx + (x - bx) * alpha;
bone._scaleY = by + (y - by) * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bx = MathUtil::abs(bone._scaleX) * MathUtil::sign(x);
by = MathUtil::abs(bone._scaleY) * MathUtil::sign(y);
bone._scaleX = bx + (x - bx) * alpha;
bone._scaleY = by + (y - by) * alpha;
break;
case MixBlend_Add:
bx = MathUtil::sign(x);
by = MathUtil::sign(y);
bone._scaleX = MathUtil::abs(bone._scaleX) * bx + (x - MathUtil::abs(bone._data._scaleX) * bx) * alpha;
bone._scaleY = MathUtil::abs(bone._scaleY) * by + (y - MathUtil::abs(bone._data._scaleY) * by) * alpha;
}
}
}
} }
int ScaleTimeline::getPropertyId() { RTTI_IMPL(ScaleXTimeline, CurveTimeline1)
return ((int) TimelineType_Scale << 24) + _boneIndex;
ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
PropertyId ids[] = { ((PropertyId)Property_ScaleX << 32) | boneIndex };
setPropertyIds(ids, 1);
}
void ScaleXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixBlend blend, MixDirection direction
) {
SP_UNUSED(lastTime);
SP_UNUSED(pEvents);
Bone *bone = skeleton._bones[_boneIndex];
if (!bone->_active) return;
if (time < _frames[0]) {
switch (blend) {
case MixBlend_Setup:
bone->_scaleX = bone->_data._scaleX;
return;
case MixBlend_First:
bone->_scaleX += (bone->_data._scaleX - bone->_scaleX) * alpha;
default: {}
}
return;
}
float x = getCurveValue(time) * bone->_data._scaleX;
if (alpha == 1) {
if (blend == MixBlend_Add)
bone->_scaleX += x - bone->_data._scaleX;
else
bone->_scaleX = x;
} else {
// Mixing out uses sign of setup or current pose, else use sign of key.
float bx;
if (direction == MixDirection_Out) {
switch (blend) {
case MixBlend_Setup:
bx = bone->_data._scaleX;
bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bx = bone->_scaleX;
bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
break;
case MixBlend_Add:
bx = bone->_scaleX;
bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bone->_data._scaleX) * alpha;
}
} else {
switch (blend) {
case MixBlend_Setup:
bx = MathUtil::abs(bone->_data._scaleX) * MathUtil::sign(x);
bone->_scaleX = bx + (x - bx) * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bx = MathUtil::abs(bone->_scaleX) * MathUtil::sign(x);
bone->_scaleX = bx + (x - bx) * alpha;
break;
case MixBlend_Add:
bx = MathUtil::sign(x);
bone->_scaleX = MathUtil::abs(bone->_scaleX) * bx + (x - MathUtil::abs(bone->_data._scaleX) * bx) * alpha;
}
}
}
}
RTTI_IMPL(ScaleYTimeline, CurveTimeline1)
ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
PropertyId ids[] = { ((PropertyId)Property_ScaleY << 32) | boneIndex };
setPropertyIds(ids, 1);
}
void ScaleYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixBlend blend, MixDirection direction
) {
SP_UNUSED(lastTime);
SP_UNUSED(pEvents);
Bone *bone = skeleton._bones[_boneIndex];
if (!bone->_active) return;
if (time < _frames[0]) {
switch (blend) {
case MixBlend_Setup:
bone->_scaleY = bone->_data._scaleY;
return;
case MixBlend_First:
bone->_scaleY += (bone->_data._scaleY - bone->_scaleY) * alpha;
default: {}
}
return;
}
float y = getCurveValue(time) * bone->_data._scaleY;
if (alpha == 1) {
if (blend == MixBlend_Add)
bone->_scaleY += y - bone->_data._scaleY;
else
bone->_scaleY = y;
} else {
// Mixing out uses sign of setup or current pose, else use sign of key.
float by = 0;
if (direction == MixDirection_Out) {
switch (blend) {
case MixBlend_Setup:
by = bone->_data._scaleY;
bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
by = bone->_scaleY;
bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
break;
case MixBlend_Add:
by = bone->_scaleY;
bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - bone->_data._scaleY) * alpha;
}
} else {
switch (blend) {
case MixBlend_Setup:
by = MathUtil::abs(bone->_data._scaleY) * MathUtil::sign(y);
bone->_scaleY = by + (y - by) * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
by = MathUtil::abs(bone->_scaleY) * MathUtil::sign(y);
bone->_scaleY = by + (y - by) * alpha;
break;
case MixBlend_Add:
by = MathUtil::sign(y);
bone->_scaleY = MathUtil::abs(bone->_scaleY) * by + (y - MathUtil::abs(bone->_data._scaleY) * by) * alpha;
}
}
}
} }

View File

@ -134,7 +134,6 @@ Skeleton::~Skeleton() {
void Skeleton::updateCache() { void Skeleton::updateCache() {
_updateCache.clear(); _updateCache.clear();
_updateCacheReset.clear();
for (size_t i = 0, n = _bones.size(); i < n; ++i) { for (size_t i = 0, n = _bones.size(); i < n; ++i) {
Bone* bone = _bones[i]; Bone* bone = _bones[i];
@ -213,24 +212,36 @@ void Skeleton::printUpdateCache() {
} }
void Skeleton::updateWorldTransform() { void Skeleton::updateWorldTransform() {
for (size_t i = 0, n = _updateCacheReset.size(); i < n; ++i) {
Bone *boneP = _updateCacheReset[i];
Bone &bone = *boneP;
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;
bone._appliedValid = true;
}
for (size_t i = 0, n = _updateCache.size(); i < n; ++i) { for (size_t i = 0, n = _updateCache.size(); i < n; ++i) {
_updateCache[i]->update(); _updateCache[i]->update();
} }
} }
void Skeleton::updateWorldTransform(Bone* parent) {
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
Bone& rootBone = *getRootBone();
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;
float rotationY = rootBone._rotation + 90 + rootBone._shearY;
float la = MathUtil::cosDeg(rootBone._rotation + rootBone._shearX) * rootBone._scaleX;
float lb = MathUtil::cosDeg(rotationY) * rootBone._scaleY;
float lc = MathUtil::sinDeg(rootBone._rotation + rootBone._shearX) * rootBone._scaleX;
float ld = MathUtil::sinDeg(rotationY) * rootBone._scaleY;
rootBone._a = (pa * la + pb * lc) * _scaleX;
rootBone._b = (pa * lb + pb * ld) * _scaleX;
rootBone._c = (pc * la + pd * lc) * _scaleY;
rootBone._d = (pc * lb + pd * ld) * _scaleY;
// Update everything except root bone.
Bone *rb = getRootBone();
for (size_t i = 0, n = _updateCache.size(); i < n; i++) {
Updatable *updatable = _updateCache[i];
if (updatable != rb) updatable->update();
}
}
void Skeleton::setToSetupPose() { void Skeleton::setToSetupPose() {
setBonesToSetupPose(); setBonesToSetupPose();
setSlotsToSetupPose(); setSlotsToSetupPose();
@ -257,10 +268,12 @@ void Skeleton::setBonesToSetupPose() {
TransformConstraint &constraint = *constraintP; TransformConstraint &constraint = *constraintP;
TransformConstraintData &constraintData = constraint._data; TransformConstraintData &constraintData = constraint._data;
constraint._rotateMix = constraintData._rotateMix; constraint._mixRotate = constraintData._mixRotate;
constraint._translateMix = constraintData._translateMix; constraint._mixX = constraintData._mixX;
constraint._scaleMix = constraintData._scaleMix; constraint._mixY = constraintData._mixY;
constraint._shearMix = constraintData._shearMix; constraint._mixScaleX = constraintData._mixScaleX;
constraint._mixScaleY = constraintData._mixScaleY;
constraint._mixShearY = constraintData._mixShearY;
} }
for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) {
@ -270,8 +283,9 @@ void Skeleton::setBonesToSetupPose() {
constraint._position = constraintData._position; constraint._position = constraintData._position;
constraint._spacing = constraintData._spacing; constraint._spacing = constraintData._spacing;
constraint._rotateMix = constraintData._rotateMix; constraint._mixRotate = constraintData._mixRotate;
constraint._translateMix = constraintData._translateMix; constraint._mixX = constraintData._mixX;
constraint._mixY = constraintData._mixY;
} }
} }
@ -563,15 +577,18 @@ void Skeleton::sortIkConstraint(IkConstraint *constraint) {
Bone *parent = constrained[0]; Bone *parent = constrained[0];
sortBone(parent); sortBone(parent);
if (constrained.size() > 1) { if (constrained.size() == 1) {
Bone *child = constrained[constrained.size() - 1]; _updateCache.add(constraint);
if (!_updateCache.contains(child)) _updateCacheReset.add(child); sortReset(parent->_children);
} else {
Bone* child = constrained[constrained.size() - 1];
sortBone(child);
_updateCache.add(constraint);
sortReset(parent->_children);
child->_sorted = true;
} }
_updateCache.add(constraint);
sortReset(parent->getChildren());
constrained[constrained.size() - 1]->_sorted = true;
} }
void Skeleton::sortPathConstraint(PathConstraint *constraint) { void Skeleton::sortPathConstraint(PathConstraint *constraint) {
@ -617,7 +634,7 @@ void Skeleton::sortTransformConstraint(TransformConstraint *constraint) {
for (size_t i = 0; i < boneCount; i++) { for (size_t i = 0; i < boneCount; i++) {
Bone *child = constrained[i]; Bone *child = constrained[i];
sortBone(child->getParent()); sortBone(child->getParent());
if (!_updateCache.contains(child)) _updateCacheReset.add(child); sortBone(child);
} }
} else { } else {
for (size_t i = 0; i < boneCount; ++i) { for (size_t i = 0; i < boneCount; ++i) {

View File

@ -39,10 +39,39 @@
namespace spine { namespace spine {
RTTI_IMPL_NOPARENT(Timeline) RTTI_IMPL_NOPARENT(Timeline)
Timeline::Timeline() { Timeline::Timeline(size_t frameCount, size_t frameEntries): _propertyIds(), _frames(), _frameEntries(frameEntries) {
_frames.setSize(frameCount * frameEntries, 0);
} }
Timeline::~Timeline() { Timeline::~Timeline() {
} }
Vector<PropertyId> &Timeline::getPropertyIds() {
return _propertyIds;
}
void Timeline::setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount) {
_propertyIds.clear();
_propertyIds.ensureCapacity(propertyIdsCount);
for (size_t i = 0; i < propertyIdsCount; i++) {
_propertyIds.add(propertyIds[i]);
}
}
size_t Timeline::getFrameCount() {
return _frames.size() / _frameEntries;
}
Vector<float> &Timeline::getFrames() {
return _frames;
}
size_t Timeline::getFrameEntries() {
return _frameEntries;
}
float Timeline::getDuration() {
return _frames[_frames.size() - getFrameEntries()];
}
} }

View File

@ -45,18 +45,14 @@ RTTI_IMPL(TransformConstraint, Updatable)
TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Updatable(), TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Updatable(),
_data(data), _data(data),
_target(skeleton.findBone( _target(skeleton.findBone(data.getTarget()->getName())),
data.getTarget()->getName())), _mixRotate(data.getMixRotate()),
_rotateMix( _mixX(data.getMixX()),
data.getRotateMix()), _mixY(data.getMixY()),
_translateMix( _mixScaleX(data.getMixScaleX()),
data.getTranslateMix()), _mixScaleY(data.getMixScaleY()),
_scaleMix( _mixShearY(data.getMixShearY()),
data.getScaleMix()), _active(false) {
_shearMix(
data.getShearMix()),
_active(false)
{
_bones.ensureCapacity(_data.getBones().size()); _bones.ensureCapacity(_data.getBones().size());
for (size_t i = 0; i < _data.getBones().size(); ++i) { for (size_t i = 0; i < _data.getBones().size(); ++i) {
BoneData *boneData = _data.getBones()[i]; BoneData *boneData = _data.getBones()[i];
@ -64,11 +60,9 @@ TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton
} }
} }
void TransformConstraint::apply() {
update();
}
void TransformConstraint::update() { void TransformConstraint::update() {
if (_mixRotate == 0 && _mixX == 0 && _mixY == 0 && _mixScaleX == 0 && _mixScaleX == 0 && _mixShearY == 0) return;
if (_data.isLocal()) { if (_data.isLocal()) {
if (_data.isRelative()) if (_data.isRelative())
applyRelativeLocal(); applyRelativeLocal();
@ -102,40 +96,57 @@ void TransformConstraint::setTarget(Bone *inValue) {
_target = inValue; _target = inValue;
} }
float TransformConstraint::getRotateMix() { float TransformConstraint::getMixRotate() {
return _rotateMix; return _mixRotate;
} }
void TransformConstraint::setRotateMix(float inValue) { void TransformConstraint::setMixRotate(float inValue) {
_rotateMix = inValue; _mixRotate = inValue;
} }
float TransformConstraint::getTranslateMix() { float TransformConstraint::getMixX() {
return _translateMix; return _mixX;
} }
void TransformConstraint::setTranslateMix(float inValue) { void TransformConstraint::setMixX(float inValue) {
_translateMix = inValue; _mixX = inValue;
} }
float TransformConstraint::getScaleMix() { float TransformConstraint::getMixY() {
return _scaleMix; return _mixY;
} }
void TransformConstraint::setScaleMix(float inValue) { void TransformConstraint::setMixY(float inValue) {
_scaleMix = inValue; _mixY = inValue;
} }
float TransformConstraint::getShearMix() { void TransformConstraint::setMixScaleX(float inValue) {
return _shearMix; _mixScaleX = inValue;
} }
void TransformConstraint::setShearMix(float inValue) { float TransformConstraint::getMixScaleX() {
_shearMix = inValue; return _mixScaleX;
}
float TransformConstraint::getMixScaleY() {
return _mixScaleY;
}
void TransformConstraint::setMixScaleY(float inValue) {
_mixScaleY = inValue;
}
float TransformConstraint::getMixShearY() {
return _mixShearY;
}
void TransformConstraint::setMixShearY(float inValue) {
_mixShearY = inValue;
} }
void TransformConstraint::applyAbsoluteWorld() { void TransformConstraint::applyAbsoluteWorld() {
float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY;
bool translate = mixX != 0 || mixY != 0;
Bone &target = *_target; Bone &target = *_target;
float ta = target._a, tb = target._b, tc = target._c, td = target._d; float ta = target._a, tb = target._b, tc = target._c, td = target._d;
float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad;
@ -145,9 +156,7 @@ void TransformConstraint::applyAbsoluteWorld() {
Bone *item = _bones[i]; Bone *item = _bones[i];
Bone &bone = *item; Bone &bone = *item;
bool modified = false; if (mixRotate != 0) {
if (rotateMix != 0) {
float a = bone._a, b = bone._b, c = bone._c, d = bone._d; float a = bone._a, b = bone._b, c = bone._c, d = bone._d;
float r = MathUtil::atan2(tc, ta) - MathUtil::atan2(c, a) + offsetRotation; float r = MathUtil::atan2(tc, ta) - MathUtil::atan2(c, a) + offsetRotation;
if (r > MathUtil::Pi) if (r > MathUtil::Pi)
@ -155,38 +164,36 @@ void TransformConstraint::applyAbsoluteWorld() {
else if (r < -MathUtil::Pi) else if (r < -MathUtil::Pi)
r += MathUtil::Pi_2; r += MathUtil::Pi_2;
r *= rotateMix; r *= mixRotate;
float cos = MathUtil::cos(r), sin = MathUtil::sin(r); float cos = MathUtil::cos(r), sin = MathUtil::sin(r);
bone._a = cos * a - sin * c; bone._a = cos * a - sin * c;
bone._b = cos * b - sin * d; bone._b = cos * b - sin * d;
bone._c = sin * a + cos * c; bone._c = sin * a + cos * c;
bone._d = sin * b + cos * d; bone._d = sin * b + cos * d;
modified = true;
} }
if (translateMix != 0) { if (translate) {
float tx, ty; float tx, ty;
target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); target.localToWorld(_data._offsetX, _data._offsetY, tx, ty);
bone._worldX += (tx - bone._worldX) * translateMix; bone._worldX += (tx - bone._worldX) * mixX;
bone._worldY += (ty - bone._worldY) * translateMix; bone._worldY += (ty - bone._worldY) * mixY;
modified = true;
} }
if (scaleMix > 0) { if (mixScaleX > 0) {
float s = MathUtil::sqrt(bone._a * bone._a + bone._c * bone._c); float s = MathUtil::sqrt(bone._a * bone._a + bone._c * bone._c);
if (s != 0) s = (s + (MathUtil::sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * mixScaleX) / s;
if (s > 0.00001f) s = (s + (MathUtil::sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * scaleMix) / s;
bone._a *= s; bone._a *= s;
bone._c *= s; bone._c *= s;
s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d);
if (s > 0.00001f) s = (s + (MathUtil::sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * scaleMix) / s;
bone._b *= s;
bone._d *= s;
modified = true;
} }
if (shearMix > 0) { if (mixScaleY > 0) {
float s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d);
if (s != 0) s = (s + (MathUtil::sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * mixScaleY) / s;
bone._b *= s;
bone._d *= s;
}
if (mixShearY > 0) {
float b = bone._b, d = bone._d; float b = bone._b, d = bone._d;
float by = MathUtil::atan2(d, b); float by = MathUtil::atan2(d, b);
float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta) - (by - MathUtil::atan2(bone._c, bone._a)); float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta) - (by - MathUtil::atan2(bone._c, bone._a));
@ -195,19 +202,19 @@ void TransformConstraint::applyAbsoluteWorld() {
else if (r < -MathUtil::Pi) else if (r < -MathUtil::Pi)
r += MathUtil::Pi_2; r += MathUtil::Pi_2;
r = by + (r + offsetShearY) * shearMix; r = by + (r + offsetShearY) * mixShearY;
float s = MathUtil::sqrt(b * b + d * d); float s = MathUtil::sqrt(b * b + d * d);
bone._b = MathUtil::cos(r) * s; bone._b = MathUtil::cos(r) * s;
bone._d = MathUtil::sin(r) * s; bone._d = MathUtil::sin(r) * s;
modified = true;
} }
if (modified) bone._appliedValid = false; bone._appliedValid = false;
} }
} }
void TransformConstraint::applyRelativeWorld() { void TransformConstraint::applyRelativeWorld() {
float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY;
bool translate = mixX != 0 || mixY != 0;
Bone &target = *_target; Bone &target = *_target;
float ta = target._a, tb = target._b, tc = target._c, td = target._d; float ta = target._a, tb = target._b, tc = target._c, td = target._d;
float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad;
@ -216,9 +223,7 @@ void TransformConstraint::applyRelativeWorld() {
Bone *item = _bones[i]; Bone *item = _bones[i];
Bone &bone = *item; Bone &bone = *item;
bool modified = false; if (mixRotate != 0) {
if (rotateMix != 0) {
float a = bone._a, b = bone._b, c = bone._c, d = bone._d; float a = bone._a, b = bone._b, c = bone._c, d = bone._d;
float r = MathUtil::atan2(tc, ta) + offsetRotation; float r = MathUtil::atan2(tc, ta) + offsetRotation;
if (r > MathUtil::Pi) if (r > MathUtil::Pi)
@ -226,34 +231,33 @@ void TransformConstraint::applyRelativeWorld() {
else if (r < -MathUtil::Pi) else if (r < -MathUtil::Pi)
r += MathUtil::Pi_2; r += MathUtil::Pi_2;
r *= rotateMix; r *= mixRotate;
float cos = MathUtil::cos(r), sin = MathUtil::sin(r); float cos = MathUtil::cos(r), sin = MathUtil::sin(r);
bone._a = cos * a - sin * c; bone._a = cos * a - sin * c;
bone._b = cos * b - sin * d; bone._b = cos * b - sin * d;
bone._c = sin * a + cos * c; bone._c = sin * a + cos * c;
bone._d = sin * b + cos * d; bone._d = sin * b + cos * d;
modified = true;
} }
if (translateMix != 0) { if (translate) {
float tx, ty; float tx, ty;
target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); target.localToWorld(_data._offsetX, _data._offsetY, tx, ty);
bone._worldX += tx * translateMix; bone._worldX += tx * mixX;
bone._worldY += ty * translateMix; bone._worldY += ty * mixY;
modified = true;
} }
if (scaleMix > 0) { if (mixScaleX != 0) {
float s = (MathUtil::sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * scaleMix + 1; float s = (MathUtil::sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * mixScaleX + 1;
bone._a *= s; bone._a *= s;
bone._c *= s; bone._c *= s;
s = (MathUtil::sqrt(tb * tb + td * td) - 1 + _data._offsetScaleY) * scaleMix + 1; }
bone._b *= s; if (mixScaleY != 0) {
bone._d *= s; float s = (MathUtil::sqrt(tb * tb + td * td) - 1 + _data._offsetScaleY) * mixScaleY + 1;
modified = true; bone._b *= s;
} bone._d *= s;
}
if (shearMix > 0) { if (mixShearY > 0) {
float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta); float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta);
if (r > MathUtil::Pi) if (r > MathUtil::Pi)
r -= MathUtil::Pi_2; r -= MathUtil::Pi_2;
@ -261,19 +265,18 @@ void TransformConstraint::applyRelativeWorld() {
r += MathUtil::Pi_2; r += MathUtil::Pi_2;
float b = bone._b, d = bone._d; float b = bone._b, d = bone._d;
r = MathUtil::atan2(d, b) + (r - MathUtil::Pi / 2 + offsetShearY) * shearMix; r = MathUtil::atan2(d, b) + (r - MathUtil::Pi / 2 + offsetShearY) * mixShearY;
float s = MathUtil::sqrt(b * b + d * d); float s = MathUtil::sqrt(b * b + d * d);
bone._b = MathUtil::cos(r) * s; bone._b = MathUtil::cos(r) * s;
bone._d = MathUtil::sin(r) * s; bone._d = MathUtil::sin(r) * s;
modified = true;
} }
if (modified) bone._appliedValid = false; bone._appliedValid = false;
} }
} }
void TransformConstraint::applyAbsoluteLocal() { void TransformConstraint::applyAbsoluteLocal() {
float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY;
Bone &target = *_target; Bone &target = *_target;
if (!target._appliedValid) target.updateAppliedTransform(); if (!target._appliedValid) target.updateAppliedTransform();
@ -284,29 +287,27 @@ void TransformConstraint::applyAbsoluteLocal() {
if (!bone._appliedValid) bone.updateAppliedTransform(); if (!bone._appliedValid) bone.updateAppliedTransform();
float rotation = bone._arotation; float rotation = bone._arotation;
if (rotateMix != 0) { if (mixRotate != 0) {
float r = target._arotation - rotation + _data._offsetRotation; float r = target._arotation - rotation + _data._offsetRotation;
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360;
rotation += r * rotateMix; rotation += r * mixRotate;
} }
float x = bone._ax, y = bone._ay; float x = bone._ax, y = bone._ay;
if (translateMix != 0) { x += (target._ax - x + _data._offsetX) * mixX;
x += (target._ax - x + _data._offsetX) * translateMix; y += (target._ay - y + _data._offsetY) * mixY;
y += (target._ay - y + _data._offsetY) * translateMix;
}
float scaleX = bone._ascaleX, scaleY = bone._ascaleY; float scaleX = bone._ascaleX, scaleY = bone._ascaleY;
if (scaleMix != 0) { if (mixScaleX != 0 && scaleX != 0)
if (scaleX > 0.00001f) scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * scaleMix) / scaleX; scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * mixScaleX) / scaleX;
if (scaleY > 0.00001f) scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * scaleMix) / scaleY; if (mixScaleY != 0 && scaleY != 0)
} scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * mixScaleY) / scaleY;
float shearY = bone._ashearY; float shearY = bone._ashearY;
if (shearMix != 0) { if (mixShearY != 0) {
float r = target._ashearY - shearY + _data._offsetShearY; float r = target._ashearY - shearY + _data._offsetShearY;
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360;
bone._shearY += r * shearMix; bone._shearY += r * mixShearY;
} }
bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY);
@ -314,7 +315,7 @@ void TransformConstraint::applyAbsoluteLocal() {
} }
void TransformConstraint::applyRelativeLocal() { void TransformConstraint::applyRelativeLocal() {
float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY;
Bone &target = *_target; Bone &target = *_target;
if (!target._appliedValid) target.updateAppliedTransform(); if (!target._appliedValid) target.updateAppliedTransform();
@ -324,25 +325,14 @@ void TransformConstraint::applyRelativeLocal() {
if (!bone._appliedValid) bone.updateAppliedTransform(); if (!bone._appliedValid) bone.updateAppliedTransform();
float rotation = bone._arotation; float rotation = bone._arotation + (target._arotation + _data._offsetRotation) * mixRotate;
if (rotateMix != 0) rotation += (target._arotation + _data._offsetRotation) * rotateMix; float x = bone._ax + (target._ax + _data._offsetX) * mixX;
float y = bone._ay + (target._ay + _data._offsetY) * mixY;
float scaleX = (bone._ascaleX * ((target._ascaleX - 1 + _data._offsetScaleX) * mixScaleX) + 1);
float scaleY = (bone._ascaleY * ((target._ascaleY - 1 + _data._offsetScaleY) * mixScaleY) + 1);
float shearY = bone._ashearY + (target._ashearY + _data._offsetShearY) * mixShearY;
float x = bone._ax, y = bone._ay; bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY);
if (translateMix != 0) {
x += (target._ax + _data._offsetX) * translateMix;
y += (target._ay + _data._offsetY) * translateMix;
}
float scaleX = bone._ascaleX, scaleY = bone._ascaleY;
if (scaleMix != 0) {
if (scaleX > 0.00001f) scaleX *= ((target._ascaleX - 1 + _data._offsetScaleX) * scaleMix) + 1;
if (scaleY > 0.00001f) scaleY *= ((target._ascaleY - 1 + _data._offsetScaleY) * scaleMix) + 1;
}
float shearY = bone._ashearY;
if (shearMix != 0) shearY += (target._ashearY + _data._offsetShearY) * shearMix;
bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY);
} }
} }

View File

@ -41,10 +41,12 @@ using namespace spine;
TransformConstraintData::TransformConstraintData(const String &name) : TransformConstraintData::TransformConstraintData(const String &name) :
ConstraintData(name), ConstraintData(name),
_target(NULL), _target(NULL),
_rotateMix(0), _mixRotate(0),
_translateMix(0), _mixX(0),
_scaleMix(0), _mixY(0),
_shearMix(0), _mixScaleX(0),
_mixScaleY(0),
_mixShearY(0),
_offsetRotation(0), _offsetRotation(0),
_offsetX(0), _offsetX(0),
_offsetY(0), _offsetY(0),
@ -63,20 +65,28 @@ BoneData *TransformConstraintData::getTarget() {
return _target; return _target;
} }
float TransformConstraintData::getRotateMix() { float TransformConstraintData::getMixRotate() {
return _rotateMix; return _mixRotate;
} }
float TransformConstraintData::getTranslateMix() { float TransformConstraintData::getMixX() {
return _translateMix; return _mixX;
} }
float TransformConstraintData::getScaleMix() { float TransformConstraintData::getMixY() {
return _scaleMix; return _mixY;
} }
float TransformConstraintData::getShearMix() { float TransformConstraintData::getMixScaleX() {
return _shearMix; return _mixScaleX;
}
float TransformConstraintData::getMixScaleY() {
return _mixScaleY;
}
float TransformConstraintData::getMixShearY() {
return _mixShearY;
} }
float TransformConstraintData::getOffsetRotation() { float TransformConstraintData::getOffsetRotation() {

View File

@ -37,7 +37,7 @@
#include <spine/Event.h> #include <spine/Event.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>
#include <spine/TransformConstraint.h> #include <spine/TransformConstraint.h>

View File

@ -43,18 +43,12 @@
using namespace spine; using namespace spine;
RTTI_IMPL(TranslateTimeline, CurveTimeline) RTTI_IMPL(TranslateTimeline, CurveTimeline2)
const int TranslateTimeline::ENTRIES = 3; TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, bezierCount), _boneIndex(boneIndex) {
const int TranslateTimeline::PREV_TIME = -3; PropertyId ids[] = { ((PropertyId)Property_X << 32) | boneIndex,
const int TranslateTimeline::PREV_X = -2; ((PropertyId)Property_Y << 32) | boneIndex};
const int TranslateTimeline::PREV_Y = -1; setPropertyIds(ids, 2);
const int TranslateTimeline::X = 1;
const int TranslateTimeline::Y = 2;
TranslateTimeline::TranslateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) {
_frames.ensureCapacity(frameCount * ENTRIES);
_frames.setSize(frameCount * ENTRIES, 0);
} }
TranslateTimeline::~TranslateTimeline() { TranslateTimeline::~TranslateTimeline() {
@ -67,65 +61,152 @@ void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Ve
SP_UNUSED(pEvents); SP_UNUSED(pEvents);
SP_UNUSED(direction); SP_UNUSED(direction);
Bone *boneP = skeleton._bones[_boneIndex]; Bone* bone = skeleton._bones[_boneIndex];
Bone &bone = *boneP; if (!bone->_active) return;
if (!bone._active) return;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (blend) { switch (blend) {
case MixBlend_Setup: case MixBlend_Setup:
bone._x = bone._data._x; bone->_x = bone->_data._x;
bone._y = bone._data._y; bone->_y = bone->_data._y;
return; return;
case MixBlend_First: case MixBlend_First:
bone._x += (bone._data._x - bone._x) * alpha; bone->_x += (bone->_data._x - bone->_x) * alpha;
bone._y += (bone._data._y - bone._y) * alpha; bone->_y += (bone->_data._y - bone->_y) * alpha;
default: {} default: {}
} }
return; return;
} }
float x, y; float x = 0, y = 0;
if (time >= _frames[_frames.size() - ENTRIES]) { int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES);
// Time is after last frame. int curveType = (int)_curves[i / CurveTimeline2::ENTRIES];
x = _frames[_frames.size() + PREV_X]; switch (curveType) {
y = _frames[_frames.size() + PREV_Y]; case CurveTimeline::LINEAR: {
} else { float before = _frames[i];
// Interpolate between the previous frame and the current frame. x = _frames[i + CurveTimeline2::VALUE1];
int frame = Animation::binarySearch(_frames, time, ENTRIES); y = _frames[i + CurveTimeline2::VALUE2];
x = _frames[frame + PREV_X]; float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before);
y = _frames[frame + PREV_Y]; x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t;
float frameTime = _frames[frame]; y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t;
float percent = getCurvePercent(frame / ENTRIES - 1, break;
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); }
case CurveTimeline::STEPPED: {
x = _frames[i + CurveTimeline2::VALUE1];
y = _frames[i + CurveTimeline2::VALUE2];
break;
}
default: {
x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline::BEZIER);
y = getBezierValue(time, i, CurveTimeline2::VALUE2,
curveType + CurveTimeline::BEZIER_SIZE - CurveTimeline::BEZIER);
}
}
x += (_frames[frame + X] - x) * percent; switch (blend) {
y += (_frames[frame + Y] - y) * percent; case MixBlend_Setup:
} bone->_x = bone->_data._x + x * alpha;
bone->_y = bone->_data._y + y * alpha;
switch (blend) { break;
case MixBlend_Setup: case MixBlend_First:
bone._x = bone._data._x + x * alpha; case MixBlend_Replace:
bone._y = bone._data._y + y * alpha; bone->_x += (bone->_data._x + x - bone->_x) * alpha;
break; bone->_y += (bone->_data._y + y - bone->_y) * alpha;
case MixBlend_First: break;
case MixBlend_Replace: case MixBlend_Add:
bone._x += (bone._data._x + x - bone._x) * alpha; bone->_x += x * alpha;
bone._y += (bone._data._y + y - bone._y) * alpha; bone->_y += y * alpha;
break; }
case MixBlend_Add:
bone._x += x * alpha;
bone._y += y * alpha;
}
} }
int TranslateTimeline::getPropertyId() { RTTI_IMPL(TranslateXTimeline, CurveTimeline1)
return ((int) TimelineType_Translate << 24) + _boneIndex;
TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
PropertyId ids[] = { ((PropertyId)Property_X << 32) | boneIndex };
setPropertyIds(ids, 1);
} }
void TranslateTimeline::setFrame(int frameIndex, float time, float x, float y) { TranslateXTimeline::~TranslateXTimeline() {
frameIndex *= ENTRIES; }
_frames[frameIndex] = time;
_frames[frameIndex + X] = x; void TranslateXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
_frames[frameIndex + Y] = y; MixBlend blend, MixDirection direction
) {
SP_UNUSED(lastTime);
SP_UNUSED(pEvents);
SP_UNUSED(direction);
Bone* bone = skeleton._bones[_boneIndex];
if (!bone->_active) return;
if (time < _frames[0]) {
switch (blend) {
case MixBlend_Setup:
bone->_x = bone->_data._x;
return;
case MixBlend_First:
bone->_x += (bone->_data._x - bone->_x) * alpha;
default: {}
}
return;
}
float x = getCurveValue(time);
switch (blend) {
case MixBlend_Setup:
bone->_x = bone->_data._x + x * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bone->_x += (bone->_data._x + x - bone->_x) * alpha;
break;
case MixBlend_Add:
bone->_x += x * alpha;
}
}
RTTI_IMPL(TranslateYTimeline, CurveTimeline1)
TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
PropertyId ids[] = { ((PropertyId)Property_Y << 32) | boneIndex };
setPropertyIds(ids, 1);
}
TranslateYTimeline::~TranslateYTimeline() {
}
void TranslateYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixBlend blend, MixDirection direction
) {
SP_UNUSED(lastTime);
SP_UNUSED(pEvents);
SP_UNUSED(direction);
Bone* bone = skeleton._bones[_boneIndex];
if (!bone->_active) return;
if (time < _frames[0]) {
switch (blend) {
case MixBlend_Setup:
bone->_y = bone->_data._y;
return;
case MixBlend_First:
bone->_y += (bone->_data._y - bone->_y) * alpha;
default: {}
}
return;
}
float y = getCurveValue(time);
switch (blend) {
case MixBlend_Setup:
bone->_y = bone->_data._y + y * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bone->_y += (bone->_data._y + y - bone->_y) * alpha;
break;
case MixBlend_Add:
bone->_y += y * alpha;
}
} }

View File

@ -38,7 +38,7 @@
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/Bone.h> #include <spine/Bone.h>
#include <spine/TimelineType.h> #include <spine/Property.h>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>

View File

@ -157,8 +157,7 @@ void VertexAttachment::setDeformAttachment(VertexAttachment* attachment) {
int VertexAttachment::getNextID() { int VertexAttachment::getNextID() {
static int nextID = 0; static int nextID = 0;
return nextID++;
return (nextID++ & 65535) << 11;
} }
void VertexAttachment::copyTo(VertexAttachment* other) { void VertexAttachment::copyTo(VertexAttachment* other) {

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.8.9) cmake_minimum_required(VERSION 2.8.9)
# #
# First download and extract SFML 2.3.2 for the respective OS we are on # First download and extract SFML 2.4.1 for the respective OS we are on
# #
set(DEPS_DIR "${CMAKE_CURRENT_LIST_DIR}/dependencies/") set(DEPS_DIR "${CMAKE_CURRENT_LIST_DIR}/dependencies/")
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")