[cpp] More 4.0 porting, all of animation and timelines.

This commit is contained in:
badlogic 2021-03-03 16:46:54 +01:00
parent bc20f546cc
commit 7b154fb92f
33 changed files with 1474 additions and 878 deletions

View File

@ -54,7 +54,15 @@ class SP_API Animation : public SpineObject {
friend class AttachmentTimeline; friend class AttachmentTimeline;
friend class ColorTimeline; friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class DeformTimeline; friend class DeformTimeline;

View File

@ -50,23 +50,24 @@ namespace spine {
RTTI_DECL RTTI_DECL
public: public:
explicit AttachmentTimeline(int frameCount); explicit AttachmentTimeline(size_t frameCount, int slotIndex);
virtual ~AttachmentTimeline();
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();
/// Sets the time and value of the specified keyframe. /// Sets the time and value of the specified keyframe.
void setFrame(int frameIndex, float time, const String& attachmentName); void setFrame(int frame, float time, const String& attachmentName);
size_t getSlotIndex();
void setSlotIndex(size_t inValue);
Vector<float>& getFrames();
Vector<String>& getAttachmentNames(); Vector<String>& getAttachmentNames();
size_t getFrameCount();
private: int getSlotIndex() { return _slotIndex; }
size_t _slotIndex;
Vector<float> _frames; void setSlotIndex(int inValue) { _slotIndex = inValue; }
protected:
int _slotIndex;
Vector<String> _attachmentNames; Vector<String> _attachmentNames;
void setAttachment(Skeleton& skeleton, Slot& slot, String* attachmentName); void setAttachment(Skeleton& skeleton, Slot& slot, String* attachmentName);

View File

@ -63,6 +63,18 @@ class SP_API Bone : public Updatable {
friend class PointAttachment; friend class PointAttachment;
friend class AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class ScaleTimeline; friend class ScaleTimeline;
friend class ScaleXTimeline; friend class ScaleXTimeline;
@ -71,6 +83,10 @@ class SP_API Bone : public Updatable {
friend class ShearTimeline; friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline; friend class TranslateTimeline;
friend class TranslateXTimeline; friend class TranslateXTimeline;

View File

@ -52,6 +52,10 @@ class SP_API BoneData : public SpineObject {
friend class ShearTimeline; friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline; friend class TranslateTimeline;
friend class TranslateXTimeline; friend class TranslateXTimeline;

View File

@ -51,6 +51,14 @@ public:
return *this; return *this;
} }
inline Color &set(float _r, float _g, float _b) {
this->r = _r;
this->g = _g;
this->b = _b;
clamp();
return *this;
}
inline Color &set(const Color &other) { inline Color &set(const Color &other) {
r = other.r; r = other.r;
g = other.g; g = other.g;
@ -69,6 +77,14 @@ public:
return *this; return *this;
} }
inline Color &add(float _r, float _g, float _b) {
this->r += _r;
this->g += _g;
this->b += _b;
clamp();
return *this;
}
inline Color &add(const Color &other) { inline Color &add(const Color &other) {
r += other.r; r += other.r;
g += other.g; g += other.g;

View File

@ -33,48 +33,165 @@
#include <spine/CurveTimeline.h> #include <spine/CurveTimeline.h>
namespace spine { namespace spine {
class SP_API ColorTimeline : public CurveTimeline { class SP_API RGBATimeline : public CurveTimeline {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL RTTI_DECL
public: public:
static const int ENTRIES; explicit RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex);
explicit ColorTimeline(int frameCount); virtual ~RGBATimeline();
virtual void virtual void
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); MixDirection direction);
virtual int getPropertyId(); /// Sets the time and value of the specified keyframe.
void setFrame(int frame, float time, float r, float g, float b, float a);
/// Sets the time and value of the specified keyframe. int getSlotIndex() { return _slotIndex; };
void setFrame(int frameIndex, float time, float r, float g, float b, float a);
int getSlotIndex(); void setSlotIndex(int inValue) { _slotIndex = inValue; }
void setSlotIndex(int inValue); protected:
int _slotIndex;
Vector<float> &getFrames(); static const int ENTRIES = 5;
static const int R = 1;
static const int G = 2;
static const int B = 3;
static const int A = 4;
};
protected: class SP_API RGBTimeline : public CurveTimeline {
static const int PREV_TIME; friend class SkeletonBinary;
static const int PREV_R;
static const int PREV_G;
static const int PREV_B;
static const int PREV_A;
static const int R;
static const int G;
static const int B;
static const int A;
private: friend class SkeletonJson;
int _slotIndex;
Vector<float> _frames; RTTI_DECL
};
public:
explicit RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex);
virtual ~RGBTimeline();
virtual void
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
MixDirection direction);
/// Sets the time and value of the specified keyframe.
void setFrame(int frame, float time, float r, float g, float b);
int getSlotIndex() { return _slotIndex; };
void setSlotIndex(int inValue) { _slotIndex = inValue; }
protected:
int _slotIndex;
static const int ENTRIES = 4;
static const int R = 1;
static const int G = 2;
static const int B = 3;
};
class SP_API AlphaTimeline : public CurveTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex);
virtual ~AlphaTimeline();
virtual void
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
MixDirection direction);
int getSlotIndex() { return _slotIndex; };
void setSlotIndex(int inValue) { _slotIndex = inValue; }
protected:
int _slotIndex;
};
class SP_API RGBA2Timeline : public CurveTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex);
virtual ~RGBA2Timeline();
virtual void
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
MixDirection direction);
/// Sets the time and value of the specified keyframe.
void setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2);
int getSlotIndex() { return _slotIndex; };
void setSlotIndex(int inValue) { _slotIndex = inValue; }
protected:
int _slotIndex;
static const int ENTRIES = 8;
static const int R = 1;
static const int G = 2;
static const int B = 3;
static const int A = 4;
static const int R2 = 5;
static const int G2 = 6;
static const int B2 = 7;
};
class SP_API RGB2Timeline : public CurveTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex);
virtual ~RGB2Timeline();
virtual void
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
MixDirection direction);
/// Sets the time and value of the specified keyframe.
void setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2);
int getSlotIndex() { return _slotIndex; };
void setSlotIndex(int inValue) { _slotIndex = inValue; }
protected:
int _slotIndex;
static const int ENTRIES = 7;
static const int R = 1;
static const int G = 2;
static const int B = 3;
static const int R2 = 4;
static const int G2 = 5;
static const int B2 = 6;
};
} }
#endif /* Spine_ColorTimeline_h */ #endif /* Spine_ColorTimeline_h */

View File

@ -72,8 +72,8 @@ namespace spine {
float getCurveValue(float time); float getCurveValue(float time);
protected: protected:
static const int ENTRIES; static const int ENTRIES = 2;
static const int VALUE; static const int VALUE = 1;
}; };
class SP_API CurveTimeline2 : public CurveTimeline { class SP_API CurveTimeline2 : public CurveTimeline {
@ -88,9 +88,9 @@ namespace spine {
float getCurveValue(float time); float getCurveValue(float time);
protected: protected:
static const int ENTRIES; static const int ENTRIES = 3;
static const int VALUE1; static const int VALUE1 = 1;
static const int VALUE2; static const int VALUE2 = 2;
}; };
} }

View File

@ -33,37 +33,47 @@
#include <spine/CurveTimeline.h> #include <spine/CurveTimeline.h>
namespace spine { namespace spine {
class VertexAttachment; class VertexAttachment;
class SP_API DeformTimeline : public CurveTimeline { class SP_API DeformTimeline : public CurveTimeline {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL friend class SkeletonJson;
public: RTTI_DECL
explicit DeformTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction); public:
explicit DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment *attachment);
virtual int getPropertyId(); virtual void
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
MixDirection direction);
/// Sets the time and value of the specified keyframe. /// Sets the time and value of the specified keyframe.
void setFrame(int frameIndex, float time, Vector<float>& vertices); void setFrame(int frameIndex, float time, Vector<float> &vertices);
int getSlotIndex(); Vector <Vector<float>> &getVertices();
void setSlotIndex(int inValue);
Vector<float>& getFrames();
Vector< Vector<float> >& getVertices();
VertexAttachment* getAttachment();
void setAttachment(VertexAttachment* inValue);
private: VertexAttachment *getAttachment();
int _slotIndex;
Vector<float> _frames; void setAttachment(VertexAttachment *inValue);
Vector< Vector<float> > _frameVertices;
VertexAttachment* _attachment; void setBezier(int bezier, int frame, float value, float time1, float value1, float cx1, float cy1,
}; float cx2, float cy2, float time2, float value2);
float getCurvePercent(float time, int frame);
int getSlotIndex() { return _slotIndex; }
void setSlotIndex(int inValue) { _slotIndex = inValue; }
protected:
int _slotIndex;
Vector <Vector<float>> _vertices;
VertexAttachment *_attachment;
};
} }
#endif /* Spine_DeformTimeline_h */ #endif /* Spine_DeformTimeline_h */

View File

@ -40,22 +40,17 @@ namespace spine {
RTTI_DECL RTTI_DECL
public: public:
explicit DrawOrderTimeline(int frameCount); explicit DrawOrderTimeline(size_t 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();
/// Sets the time and value of the specified keyframe. /// Sets the time and value of the specified keyframe.
/// @param drawOrder May be NULL to use bind pose draw order /// @param drawOrder May be NULL to use bind pose draw order
void setFrame(size_t frameIndex, float time, Vector<int>& drawOrder); void setFrame(size_t frame, float time, Vector<int>& drawOrder);
Vector<float>& getFrames();
Vector< Vector<int> >& getDrawOrders(); Vector< Vector<int> >& getDrawOrders();
size_t getFrameCount();
private: private:
Vector<float> _frames;
Vector< Vector<int> > _drawOrders; Vector< Vector<int> > _drawOrders;
}; };
} }

View File

@ -40,23 +40,18 @@ namespace spine {
RTTI_DECL RTTI_DECL
public: public:
explicit EventTimeline(int frameCount); explicit EventTimeline(size_t frameCount);
~EventTimeline(); ~EventTimeline();
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();
/// Sets the time and value of the specified keyframe. /// Sets the time and value of the specified keyframe.
void setFrame(size_t frameIndex, Event* event); void setFrame(size_t frame, Event* event);
Vector<float> getFrames();
Vector<Event*>& getEvents(); Vector<Event*>& getEvents();
size_t getFrameCount();
private: private:
Vector<float> _frames;
Vector<Event*> _events; Vector<Event*> _events;
}; };
} }

View File

@ -41,32 +41,25 @@ namespace spine {
RTTI_DECL RTTI_DECL
public: public:
static const int ENTRIES; explicit IkConstraintTimeline(size_t frameCount, size_t bezierCount, int ikConstraintIndex);
explicit IkConstraintTimeline(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();
/// Sets the time, mix and bend direction of the specified keyframe. /// Sets the time, mix and bend direction of the specified keyframe.
void setFrame (int frameIndex, float time, float mix, float softness, int bendDirection, bool compress, bool stretch); void setFrame (int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch);
int getIkConstraintIndex() { return _ikConstraintIndex; }
void setIkConstraintIndex(int inValue) { _ikConstraintIndex = inValue; }
private: private:
static const int PREV_TIME; int _ikConstraintIndex;
static const int PREV_MIX;
static const int PREV_SOFTNESS;
static const int PREV_BEND_DIRECTION;
static const int PREV_COMPRESS;
static const int PREV_STRETCH;
static const int MIX;
static const int SOFTNESS;
static const int BEND_DIRECTION;
static const int COMPRESS;
static const int STRETCH;
Vector<float> _frames; static const int ENTRIES = 6;
int _ikConstraintIndex; static const int MIX = 1;
static const int SOFTNESS = 2;
static const int BEND_DIRECTION = 3;
static const int COMPRESS = 4;
static const int STRETCH = 5;
}; };
} }

View File

@ -42,26 +42,23 @@ namespace spine {
RTTI_DECL RTTI_DECL
public: public:
static const int ENTRIES; explicit PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex);
explicit PathConstraintMixTimeline(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(); /// Sets the time and mixes of the specified keyframe.
void setFrame(int frameIndex, float time, float mixRotate, float mixX, float mixY);
int getPathConstraintIndex() { return _pathConstraintIndex; }
void setPathConstraintIndex(int inValue) { _pathConstraintIndex = inValue; }
private: private:
static const int PREV_TIME; int _pathConstraintIndex;
static const int PREV_ROTATE;
static const int PREV_TRANSLATE;
static const int ROTATE;
static const int TRANSLATE;
Vector<float> _frames; static const int ENTRIES = 4;
int _pathConstraintIndex; static const int ROTATE = 1;
static const int X = 2;
/// Sets the time and mixes of the specified keyframe. static const int Y = 2;
void setFrame(int frameIndex, float time, float rotateMix, float translateMix);
}; };
} }

View File

@ -34,7 +34,7 @@
namespace spine { namespace spine {
class SP_API PathConstraintPositionTimeline : public CurveTimeline { class SP_API PathConstraintPositionTimeline : public CurveTimeline1 {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
@ -43,23 +43,16 @@ namespace spine {
public: public:
static const int ENTRIES; static const int ENTRIES;
explicit PathConstraintPositionTimeline(int frameCount); explicit PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex);
virtual ~PathConstraintPositionTimeline(); virtual ~PathConstraintPositionTimeline();
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 getPathConstraintIndex() { return _pathConstraintIndex; }
/// Sets the time and value of the specified keyframe.
void setFrame(int frameIndex, float time, float value);
void setPathConstraintIndex(int inValue) { _pathConstraintIndex = inValue; }
protected: protected:
static const int PREV_TIME;
static const int PREV_VALUE;
static const int VALUE;
Vector<float> _frames;
int _pathConstraintIndex; int _pathConstraintIndex;
}; };
} }

View File

@ -33,18 +33,22 @@
#include <spine/PathConstraintPositionTimeline.h> #include <spine/PathConstraintPositionTimeline.h>
namespace spine { namespace spine {
class SP_API PathConstraintSpacingTimeline : public PathConstraintPositionTimeline { class SP_API PathConstraintSpacingTimeline : public CurveTimeline1 {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL RTTI_DECL
public: public:
explicit PathConstraintSpacingTimeline(int frameCount); explicit PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex);
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 getPathConstraintIndex() { return _pathConstraintIndex; }
void setPathConstraintIndex(int inValue) { _pathConstraintIndex = inValue; }
protected:
int _pathConstraintIndex;
}; };
} }

View File

@ -51,7 +51,7 @@ enum Property {
Property_TransformConstraint = 1 << 15, Property_TransformConstraint = 1 << 15,
Property_PathConstraintPosition = 1 << 16, Property_PathConstraintPosition = 1 << 16,
Property_PathConstraintSpacing = 1 << 17, Property_PathConstraintSpacing = 1 << 17,
Property_OathConstraintMix = 1 << 18 Property_PathConstraintMix = 1 << 18
}; };
} }

View File

@ -33,19 +33,65 @@
#include <spine/TranslateTimeline.h> #include <spine/TranslateTimeline.h>
namespace spine { namespace spine {
class SP_API ShearTimeline : public TranslateTimeline { class SP_API ShearTimeline : public CurveTimeline2 {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL RTTI_DECL
public: public:
explicit ShearTimeline(int frameCount); explicit ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
virtual ~ShearTimeline();
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 ShearXTimeline : public CurveTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
virtual ~ShearXTimeline();
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 ShearYTimeline : public CurveTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
virtual ~ShearYTimeline();
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_ShearTimeline_h */ #endif /* Spine_ShearTimeline_h */

View File

@ -64,7 +64,15 @@ class SP_API Skeleton : public SpineObject {
friend class AttachmentTimeline; friend class AttachmentTimeline;
friend class ColorTimeline; friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class DeformTimeline; friend class DeformTimeline;
@ -88,6 +96,10 @@ class SP_API Skeleton : public SpineObject {
friend class ShearTimeline; friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TransformConstraintTimeline; friend class TransformConstraintTimeline;
friend class RotateTimeline; friend class RotateTimeline;

View File

@ -54,7 +54,15 @@ class SP_API Slot : public SpineObject {
friend class AttachmentTimeline; friend class AttachmentTimeline;
friend class ColorTimeline; friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class DeformTimeline; friend class DeformTimeline;

View File

@ -45,7 +45,15 @@ class SP_API SlotData : public SpineObject {
friend class AttachmentTimeline; friend class AttachmentTimeline;
friend class ColorTimeline; friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class DeformTimeline; friend class DeformTimeline;

View File

@ -41,29 +41,27 @@ namespace spine {
RTTI_DECL RTTI_DECL
public: public:
static const int ENTRIES; explicit TransformConstraintTimeline(size_t frameCount, size_t bezierCount, int transformConstraintIndex);
explicit TransformConstraintTimeline(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(); void setFrame(size_t frameIndex, float time, float mixRotate, float mixX, float mixY, float mixScaleX, float mixScaleY, float mixShearY);
void setFrame(size_t frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix); int getTransformConstraintIndex() { return _transformConstraintIndex; }
private: void setTransformConstraintIndex(int inValue) { _transformConstraintIndex = inValue; }
static const int PREV_TIME; private:
static const int PREV_ROTATE; int _transformConstraintIndex;
static const int PREV_TRANSLATE;
static const int PREV_SCALE; static const int ENTRIES = 7;
static const int PREV_SHEAR; static const int ROTATE = 1;
static const int ROTATE; static const int X = 2;
static const int TRANSLATE; static const int Y = 3;
static const int SCALE; static const int SCALEX = 4;
static const int SHEAR; static const int SCALEY = 5;
static const int SHEARY = 6;
Vector<float> _frames; Vector<float> _frames;
int _transformConstraintIndex;
}; };
} }

View File

@ -46,13 +46,12 @@ using namespace spine;
RTTI_IMPL(AttachmentTimeline, Timeline) RTTI_IMPL(AttachmentTimeline, Timeline)
AttachmentTimeline::AttachmentTimeline(int frameCount) : Timeline(), _slotIndex(0) { AttachmentTimeline::AttachmentTimeline(size_t frameCount, int slotIndex) : Timeline(frameCount, 1), _slotIndex(slotIndex) {
_frames.ensureCapacity(frameCount); PropertyId ids[] = {((PropertyId) Property_Attachment << 32) | slotIndex };
setPropertyIds(ids, 1);
_attachmentNames.ensureCapacity(frameCount); _attachmentNames.ensureCapacity(frameCount);
for (size_t i = 0; i < frameCount; ++i) {
_frames.setSize(frameCount, 0);
for (int i = 0; i < frameCount; ++i) {
_attachmentNames.add(String()); _attachmentNames.add(String());
} }
} }
@ -68,63 +67,37 @@ void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, V
SP_UNUSED(pEvents); SP_UNUSED(pEvents);
SP_UNUSED(alpha); SP_UNUSED(alpha);
assert(_slotIndex < skeleton._slots.size());
String *attachmentName; String *attachmentName;
Slot *slotP = skeleton._slots[_slotIndex]; Slot *slot = skeleton._slots[_slotIndex];
Slot &slot = *slotP; if (!slot->_bone._active) return;
if (!slot._bone.isActive()) return;
if (direction == MixDirection_Out) { if (direction == MixDirection_Out) {
if (blend == MixBlend_Setup) setAttachment(skeleton, slot, &slot._data._attachmentName); if (blend == MixBlend_Setup) setAttachment(skeleton, *slot, &slot->_data._attachmentName);
return; return;
} }
if (time < _frames[0]) { if (time < _frames[0]) {
// Time is before first frame. // Time is before first frame.
if (blend == MixBlend_Setup || blend == MixBlend_First) { if (blend == MixBlend_Setup || blend == MixBlend_First) {
setAttachment(skeleton, slot, &slot._data._attachmentName); setAttachment(skeleton, *slot, &slot->_data._attachmentName);
} }
return; return;
} }
size_t frameIndex; size_t frameIndex;
if (time >= _frames[_frames.size() - 1]) { if (time < _frames[0]) {
// Time is after last frame. if (blend == MixBlend_Setup || blend == MixBlend_First) setAttachment(skeleton, *slot, &slot->_data._attachmentName);
frameIndex = _frames.size() - 1; return;
} else { }
frameIndex = Animation::binarySearch(_frames, time, 1) - 1;
}
attachmentName = &_attachmentNames[frameIndex]; setAttachment(skeleton, *slot, &_attachmentNames[Animation::search(_frames, time)]);
slot.setAttachment(attachmentName->length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName));
} }
int AttachmentTimeline::getPropertyId() { void AttachmentTimeline::setFrame(int frame, float time, const String &attachmentName) {
return ((int) TimelineType_Attachment << 24) + _slotIndex; _frames[frame] = time;
} _attachmentNames[frame] = attachmentName;
void AttachmentTimeline::setFrame(int frameIndex, float time, const String &attachmentName) {
_frames[frameIndex] = time;
_attachmentNames[frameIndex] = attachmentName;
}
size_t AttachmentTimeline::getSlotIndex() {
return _slotIndex;
}
void AttachmentTimeline::setSlotIndex(size_t inValue) {
_slotIndex = inValue;
}
Vector<float> &AttachmentTimeline::getFrames() {
return _frames;
} }
Vector<String> &AttachmentTimeline::getAttachmentNames() { Vector<String> &AttachmentTimeline::getAttachmentNames() {
return _attachmentNames; return _attachmentNames;
} }
size_t AttachmentTimeline::getFrameCount() {
return _frames.size();
}

View File

@ -44,102 +44,461 @@
using namespace spine; using namespace spine;
RTTI_IMPL(ColorTimeline, CurveTimeline) RTTI_IMPL(RGBATimeline, CurveTimeline)
const int ColorTimeline::ENTRIES = 5; RGBATimeline::RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount,
const int ColorTimeline::PREV_TIME = -5; RGBATimeline::ENTRIES,
const int ColorTimeline::PREV_R = -4; bezierCount),
const int ColorTimeline::PREV_G = -3; _slotIndex(slotIndex) {
const int ColorTimeline::PREV_B = -2; PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex,
const int ColorTimeline::PREV_A = -1; ((PropertyId) Property_Alpha << 32) | slotIndex};
const int ColorTimeline::R = 1; setPropertyIds(ids, 2);
const int ColorTimeline::G = 2;
const int ColorTimeline::B = 3;
const int ColorTimeline::A = 4;
ColorTimeline::ColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) {
_frames.setSize(frameCount * ENTRIES, 0);
} }
void ColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, RGBATimeline::~RGBATimeline() {
MixBlend blend, MixDirection direction }
void RGBATimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixBlend blend, MixDirection direction
) { ) {
SP_UNUSED(lastTime); SP_UNUSED(lastTime);
SP_UNUSED(pEvents); SP_UNUSED(pEvents);
SP_UNUSED(direction); SP_UNUSED(direction);
Slot *slotP = skeleton._slots[_slotIndex]; Slot *slot = skeleton._slots[_slotIndex];
Slot &slot = *slotP; if (!slot->_bone._active) return;
if (!slot._bone.isActive()) return;
if (time < _frames[0]) {
switch (blend) {
case MixBlend_Setup:
slot._color.set(slot._data._color);
return;
case MixBlend_First: {
Color &color = slot._color, setup = slot._data._color;
color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
(setup.a - color.a) * alpha);
}
default: ;
}
return;
}
float r, g, b, a; if (time < _frames[0]) {
if (time >= _frames[_frames.size() - ENTRIES]) { Color &color = slot->_color, &setup = slot->_data._color;
// Time is after last frame. switch (blend) {
size_t i = _frames.size(); case MixBlend_Setup:
r = _frames[i + PREV_R]; color.set(setup);
g = _frames[i + PREV_G]; return;
b = _frames[i + PREV_B]; case MixBlend_First:
a = _frames[i + PREV_A]; color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
} else { (setup.a - color.a) * alpha);
// Interpolate between the previous frame and the current frame. default: {
size_t frame = (size_t)Animation::binarySearch(_frames, time, ENTRIES); }
r = _frames[frame + PREV_R]; }
g = _frames[frame + PREV_G]; return;
b = _frames[frame + PREV_B]; }
a = _frames[frame + PREV_A];
float frameTime = _frames[frame];
float percent = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
r += (_frames[frame + R] - r) * percent; float r = 0, g = 0, b = 0, a = 0;
g += (_frames[frame + G] - g) * percent; int i = Animation::search(_frames, time, RGBATimeline::ENTRIES);
b += (_frames[frame + B] - b) * percent; int curveType = (int) _curves[i / RGBATimeline::ENTRIES];
a += (_frames[frame + A] - a) * percent; switch (curveType) {
} case RGBATimeline::LINEAR: {
float before = _frames[i];
if (alpha == 1) { r = _frames[i + RGBATimeline::R];
slot.getColor().set(r, g, b, a); g = _frames[i + RGBATimeline::G];
} else { b = _frames[i + RGBATimeline::B];
Color &color = slot.getColor(); a = _frames[i + RGBATimeline::A];
if (blend == MixBlend_Setup) color.set(slot.getData().getColor()); float t = (time - before) / (_frames[i + RGBATimeline::ENTRIES] - before);
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); r += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::R] - r) * t;
} g += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::G] - g) * t;
b += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::B] - b) * t;
a += (_frames[i + RGBATimeline::ENTRIES + RGBATimeline::A] - a) * t;
break;
}
case RGBATimeline::STEPPED: {
r = _frames[i + RGBATimeline::R];
g = _frames[i + RGBATimeline::G];
b = _frames[i + RGBATimeline::B];
a = _frames[i + RGBATimeline::A];
break;
}
default: {
r = getBezierValue(time, i, RGBATimeline::R, curveType - RGBATimeline::BEZIER);
g = getBezierValue(time, i, RGBATimeline::G,
curveType + RGBATimeline::BEZIER_SIZE - RGBATimeline::BEZIER);
b = getBezierValue(time, i, RGBATimeline::B,
curveType + RGBATimeline::BEZIER_SIZE * 2 - RGBATimeline::BEZIER);
a = getBezierValue(time, i, RGBATimeline::A,
curveType + RGBATimeline::BEZIER_SIZE * 3 - RGBATimeline::BEZIER);
}
}
Color &color = slot->_color;
if (alpha == 1)
color.set(r, g, b, a);
else {
if (blend == MixBlend_Setup) color.set(slot->_data._color);
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
}
} }
int ColorTimeline::getPropertyId() { void RGBATimeline::setFrame(int frame, float time, float r, float g, float b, float a) {
return ((int) TimelineType_Color << 24) + _slotIndex; frame *= ENTRIES;
_frames[frame] = time;
_frames[frame + R] = r;
_frames[frame + G] = g;
_frames[frame + B] = b;
_frames[frame + A] = a;
} }
void ColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a) { RTTI_IMPL(RGBTimeline, CurveTimeline)
frameIndex *= ENTRIES;
_frames[frameIndex] = time; RGBTimeline::RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount,
_frames[frameIndex + R] = r; RGBTimeline::ENTRIES,
_frames[frameIndex + G] = g; bezierCount),
_frames[frameIndex + B] = b; _slotIndex(slotIndex) {
_frames[frameIndex + A] = a; PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex};
setPropertyIds(ids, 1);
} }
int ColorTimeline::getSlotIndex() { RGBTimeline::~RGBTimeline() {
return _slotIndex;
} }
void ColorTimeline::setSlotIndex(int inValue) { void RGBTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
_slotIndex = inValue; MixBlend blend, MixDirection direction
) {
SP_UNUSED(lastTime);
SP_UNUSED(pEvents);
SP_UNUSED(direction);
Slot *slot = skeleton._slots[_slotIndex];
if (!slot->_bone._active) return;
if (time < _frames[0]) {
Color &color = slot->_color, &setup = slot->_data._color;
switch (blend) {
case MixBlend_Setup:
color.set(setup);
return;
case MixBlend_First:
color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
(setup.a - color.a) * alpha);
default: {
}
}
return;
}
float r = 0, g = 0, b = 0;
int i = Animation::search(_frames, time, RGBTimeline::ENTRIES);
int curveType = (int) _curves[i / RGBTimeline::ENTRIES];
switch (curveType) {
case RGBTimeline::LINEAR: {
float before = _frames[i];
r = _frames[i + RGBTimeline::R];
g = _frames[i + RGBTimeline::G];
b = _frames[i + RGBTimeline::B];
float t = (time - before) / (_frames[i + RGBTimeline::ENTRIES] - before);
r += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::R] - r) * t;
g += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::G] - g) * t;
b += (_frames[i + RGBTimeline::ENTRIES + RGBTimeline::B] - b) * t;
break;
}
case RGBTimeline::STEPPED: {
r = _frames[i + RGBTimeline::R];
g = _frames[i + RGBTimeline::G];
b = _frames[i + RGBTimeline::B];
break;
}
default: {
r = getBezierValue(time, i, RGBTimeline::R, curveType - RGBTimeline::BEZIER);
g = getBezierValue(time, i, RGBTimeline::G,
curveType + RGBTimeline::BEZIER_SIZE - RGBTimeline::BEZIER);
b = getBezierValue(time, i, RGBTimeline::B,
curveType + RGBTimeline::BEZIER_SIZE * 2 - RGBTimeline::BEZIER);
}
}
Color &color = slot->_color;
if (alpha == 1)
color.set(r, g, b);
else {
Color &setup = slot->_data._color;
if (blend == MixBlend_Setup) color.set(setup.r, setup.g, setup.b);
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha);
}
} }
Vector<float> &ColorTimeline::getFrames() { void RGBTimeline::setFrame(int frame, float time, float r, float g, float b) {
return _frames; frame *= ENTRIES;
_frames[frame] = time;
_frames[frame + R] = r;
_frames[frame + G] = g;
_frames[frame + B] = b;
}
RTTI_IMPL(AlphaTimeline, CurveTimeline1)
AlphaTimeline::AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline1(frameCount,
bezierCount),
_slotIndex(slotIndex) {
PropertyId ids[] = {((PropertyId) Property_Alpha << 32) | slotIndex};
setPropertyIds(ids, 1);
}
AlphaTimeline::~AlphaTimeline() {
}
void AlphaTimeline::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);
Slot *slot = skeleton._slots[_slotIndex];
if (!slot->_bone._active) return;
if (time < _frames[0]) { // Time is before first frame.
Color &color = slot->_color, &setup = slot->_data._color;
switch (blend) {
case MixBlend_Setup:
color.a = setup.a;
return;
case MixBlend_First:
color.a += (setup.a - color.a) * alpha;
default: {
}
}
return;
}
float a = getCurveValue(time);
if (alpha == 1)
slot->_color.a = a;
else {
if (blend == MixBlend_Setup) slot->_color.a = slot->_data._color.a;
slot->_color.a += (a - slot->_color.a) * alpha;
}
}
RTTI_IMPL(RGBA2Timeline, CurveTimeline)
RGBA2Timeline::RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount,
RGBA2Timeline::ENTRIES,
bezierCount),
_slotIndex(slotIndex) {
PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex,
((PropertyId) Property_Alpha << 32) | slotIndex,
((PropertyId) Property_Rgb2 << 32) | slotIndex};
setPropertyIds(ids, 3);
}
RGBA2Timeline::~RGBA2Timeline() {
}
void RGBA2Timeline::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);
Slot *slot = skeleton._slots[_slotIndex];
if (!slot->_bone._active) return;
if (time < _frames[0]) {
Color &light = slot->_color, &dark = slot->_darkColor, &setupLight = slot->_data._color, &setupDark = slot->_data._darkColor;
switch (blend) {
case MixBlend_Setup:
light.set(setupLight);
dark.set(setupDark.r, setupDark.g, setupDark.b);
return;
case MixBlend_First:
light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha,
(setupLight.b - light.b) * alpha,
(setupLight.a - light.a) * alpha);
dark.r += (setupDark.r - dark.r) * alpha;
dark.g += (setupDark.g - dark.g) * alpha;
dark.b += (setupDark.b - dark.b) * alpha;
default: {
}
}
return;
}
float r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;
int i = Animation::search(_frames, time, RGBA2Timeline::ENTRIES);
int curveType = (int) _curves[i / RGBA2Timeline::ENTRIES];
switch (curveType) {
case RGBA2Timeline::LINEAR: {
float before = _frames[i];
r = _frames[i + RGBA2Timeline::R];
g = _frames[i + RGBA2Timeline::G];
b = _frames[i + RGBA2Timeline::B];
a = _frames[i + RGBA2Timeline::A];
r2 = _frames[i + RGBA2Timeline::R2];
g2 = _frames[i + RGBA2Timeline::G2];
b2 = _frames[i + RGBA2Timeline::B2];
float t = (time - before) / (_frames[i + RGBA2Timeline::ENTRIES] - before);
r += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::R] - r) * t;
g += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::G] - g) * t;
b += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::B] - b) * t;
a += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::A] - a) * t;
r2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::R2] - r2) * t;
g2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::G2] - g2) * t;
b2 += (_frames[i + RGBA2Timeline::ENTRIES + RGBA2Timeline::B2] - b2) * t;
break;
}
case RGBA2Timeline::STEPPED: {
r = _frames[i + RGBA2Timeline::R];
g = _frames[i + RGBA2Timeline::G];
b = _frames[i + RGBA2Timeline::B];
a = _frames[i + RGBA2Timeline::A];
r2 = _frames[i + RGBA2Timeline::R2];
g2 = _frames[i + RGBA2Timeline::G2];
b2 = _frames[i + RGBA2Timeline::B2];
break;
}
default: {
r = getBezierValue(time, i, RGBA2Timeline::R, curveType - RGBA2Timeline::BEZIER);
g = getBezierValue(time, i, RGBA2Timeline::G,
curveType + RGBA2Timeline::BEZIER_SIZE - RGBA2Timeline::BEZIER);
b = getBezierValue(time, i, RGBA2Timeline::B,
curveType + RGBA2Timeline::BEZIER_SIZE * 2 - RGBA2Timeline::BEZIER);
a = getBezierValue(time, i, RGBA2Timeline::A,
curveType + RGBA2Timeline::BEZIER_SIZE * 3 - RGBA2Timeline::BEZIER);
r2 = getBezierValue(time, i, RGBA2Timeline::R2,
curveType + RGBA2Timeline::BEZIER_SIZE * 4 - RGBA2Timeline::BEZIER);
g2 = getBezierValue(time, i, RGBA2Timeline::G2,
curveType + RGBA2Timeline::BEZIER_SIZE * 5 - RGBA2Timeline::BEZIER);
b2 = getBezierValue(time, i, RGBA2Timeline::B2,
curveType + RGBA2Timeline::BEZIER_SIZE * 6 - RGBA2Timeline::BEZIER);
}
}
Color &light = slot->_color, &dark = slot->_darkColor;
if (alpha == 1) {
light.set(r, g, b, a);
dark.set(r2, g2, b2);
} else {
if (blend == MixBlend_Setup) {
light.set(slot->_data._color);
dark.set(slot->_data._darkColor);
}
light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);
dark.r += (r2 - dark.r) * alpha;
dark.g += (g2 - dark.g) * alpha;
dark.b += (b2 - dark.b) * alpha;
}
}
void
RGBA2Timeline::setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2) {
frame *= ENTRIES;
_frames[frame] = time;
_frames[frame + R] = r;
_frames[frame + G] = g;
_frames[frame + B] = b;
_frames[frame + A] = a;
_frames[frame + R2] = r2;
_frames[frame + G2] = g2;
_frames[frame + B2] = b2;
}
RTTI_IMPL(RGB2Timeline, CurveTimeline)
RGB2Timeline::RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount,
RGB2Timeline::ENTRIES,
bezierCount),
_slotIndex(slotIndex) {
PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex,
((PropertyId) Property_Rgb2 << 32) | slotIndex};
setPropertyIds(ids, 2);
}
RGB2Timeline::~RGB2Timeline() {
}
void RGB2Timeline::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);
Slot *slot = skeleton._slots[_slotIndex];
if (!slot->_bone._active) return;
if (time < _frames[0]) {
Color &light = slot->_color, &dark = slot->_darkColor, &setupLight = slot->_data._color, &setupDark = slot->_data._darkColor;
switch (blend) {
case MixBlend_Setup:
light.set(setupLight.r, setupLight.g, setupLight.b);
dark.set(setupDark.r, setupDark.g, setupDark.b);
return;
case MixBlend_First:
light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha,
(setupLight.b - light.b) * alpha);
dark.r += (setupDark.r - dark.r) * alpha;
dark.g += (setupDark.g - dark.g) * alpha;
dark.b += (setupDark.b - dark.b) * alpha;
default: {
}
}
return;
}
float r = 0, g = 0, b = 0, r2 = 0, g2 = 0, b2 = 0;
int i = Animation::search(_frames, time, RGB2Timeline::ENTRIES);
int curveType = (int) _curves[i / RGB2Timeline::ENTRIES];
switch (curveType) {
case RGB2Timeline::LINEAR: {
float before = _frames[i];
r = _frames[i + RGB2Timeline::R];
g = _frames[i + RGB2Timeline::G];
b = _frames[i + RGB2Timeline::B];
r2 = _frames[i + RGB2Timeline::R2];
g2 = _frames[i + RGB2Timeline::G2];
b2 = _frames[i + RGB2Timeline::B2];
float t = (time - before) / (_frames[i + RGB2Timeline::ENTRIES] - before);
r += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::R] - r) * t;
g += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::G] - g) * t;
b += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::B] - b) * t;
r2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::R2] - r2) * t;
g2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::G2] - g2) * t;
b2 += (_frames[i + RGB2Timeline::ENTRIES + RGB2Timeline::B2] - b2) * t;
break;
}
case RGB2Timeline::STEPPED: {
r = _frames[i + RGB2Timeline::R];
g = _frames[i + RGB2Timeline::G];
b = _frames[i + RGB2Timeline::B];
r2 = _frames[i + RGB2Timeline::R2];
g2 = _frames[i + RGB2Timeline::G2];
b2 = _frames[i + RGB2Timeline::B2];
break;
}
default: {
r = getBezierValue(time, i, RGB2Timeline::R, curveType - RGB2Timeline::BEZIER);
g = getBezierValue(time, i, RGB2Timeline::G,
curveType + RGB2Timeline::BEZIER_SIZE - RGB2Timeline::BEZIER);
b = getBezierValue(time, i, RGB2Timeline::B,
curveType + RGB2Timeline::BEZIER_SIZE * 2 - RGB2Timeline::BEZIER);
r2 = getBezierValue(time, i, RGB2Timeline::R2,
curveType + RGB2Timeline::BEZIER_SIZE * 4 - RGB2Timeline::BEZIER);
g2 = getBezierValue(time, i, RGB2Timeline::G2,
curveType + RGB2Timeline::BEZIER_SIZE * 5 - RGB2Timeline::BEZIER);
b2 = getBezierValue(time, i, RGB2Timeline::B2,
curveType + RGB2Timeline::BEZIER_SIZE * 6 - RGB2Timeline::BEZIER);
}
}
Color &light = slot->_color, &dark = slot->_darkColor;
if (alpha == 1) {
light.set(r, g, b);
dark.set(r2, g2, b2);
} else {
if (blend == MixBlend_Setup) {
light.set(slot->_data._color.r, slot->_data._color.g, slot->_data._color.b);
dark.set(slot->_data._darkColor);
}
light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha);
dark.r += (r2 - dark.r) * alpha;
dark.g += (g2 - dark.g) * alpha;
dark.b += (b2 - dark.b) * alpha;
}
}
void
RGB2Timeline::setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2) {
frame *= ENTRIES;
_frames[frame] = time;
_frames[frame + R] = r;
_frames[frame + G] = g;
_frames[frame + B] = b;
_frames[frame + R2] = r2;
_frames[frame + G2] = g2;
_frames[frame + B2] = b2;
} }

View File

@ -93,8 +93,7 @@ float CurveTimeline::getBezierValue(float time, size_t frame, size_t valueOffset
} }
RTTI_IMPL(CurveTimeline1, CurveTimeline) RTTI_IMPL(CurveTimeline1, CurveTimeline)
const int CurveTimeline1::ENTRIES = 2;
const int CurveTimeline1::VALUE = 1;
CurveTimeline1::CurveTimeline1(size_t frameCount, size_t bezierCount): CurveTimeline(frameCount, CurveTimeline1::ENTRIES, bezierCount) { CurveTimeline1::CurveTimeline1(size_t frameCount, size_t bezierCount): CurveTimeline(frameCount, CurveTimeline1::ENTRIES, bezierCount) {
} }
@ -131,9 +130,6 @@ float CurveTimeline1::getCurveValue(float time) {
} }
RTTI_IMPL(CurveTimeline2, CurveTimeline) 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(size_t frameCount, size_t bezierCount): CurveTimeline(frameCount, CurveTimeline2::ENTRIES, bezierCount) {
} }

View File

@ -48,251 +48,284 @@ using namespace spine;
RTTI_IMPL(DeformTimeline, CurveTimeline) RTTI_IMPL(DeformTimeline, CurveTimeline)
DeformTimeline::DeformTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0), _attachment(NULL) { DeformTimeline::DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment *attachment)
_frames.ensureCapacity(frameCount); : CurveTimeline(frameCount, 1, bezierCount), _slotIndex(slotIndex), _attachment(attachment) {
_frameVertices.ensureCapacity(frameCount); PropertyId ids[] = {((PropertyId) Property_Deform << 32) | ((slotIndex << 16 | attachment->_id) & 0xffffffff)};
setPropertyIds(ids, 1);
_frames.setSize(frameCount, 0); _vertices.ensureCapacity(frameCount);
for (size_t i = 0; i < frameCount; ++i) {
for (int i = 0; i < frameCount; ++i) { Vector<float> vec;
Vector<float> vec; _vertices.add(vec);
_frameVertices.add(vec); }
}
} }
void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void DeformTimeline::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);
Slot *slotP = skeleton._slots[_slotIndex]; Slot *slotP = skeleton._slots[_slotIndex];
Slot &slot = *slotP; Slot &slot = *slotP;
if (!slot._bone.isActive()) return; if (!slot._bone.isActive()) return;
Attachment *slotAttachment = slot.getAttachment(); Attachment *slotAttachment = slot.getAttachment();
if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) { if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) {
return; return;
} }
VertexAttachment *attachment = static_cast<VertexAttachment *>(slotAttachment); VertexAttachment *attachment = static_cast<VertexAttachment *>(slotAttachment);
if (attachment->_deformAttachment != _attachment) { if (attachment->_deformAttachment != _attachment) {
return; return;
} }
Vector<float> &deformArray = slot._deform; Vector<float> &deformArray = slot._deform;
if (deformArray.size() == 0) { if (deformArray.size() == 0) {
blend = MixBlend_Setup; blend = MixBlend_Setup;
} }
Vector< Vector<float> > &frameVertices = _frameVertices; Vector<Vector<float> > &vertices = _vertices;
size_t vertexCount = frameVertices[0].size(); size_t vertexCount = vertices[0].size();
Vector<float> &frames = _frames; Vector<float> &frames = _frames;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (blend) { switch (blend) {
case MixBlend_Setup: case MixBlend_Setup:
deformArray.clear(); deformArray.clear();
return; return;
case MixBlend_First: { case MixBlend_First: {
if (alpha == 1) { if (alpha == 1) {
deformArray.clear(); deformArray.clear();
return; return;
} }
deformArray.setSize(vertexCount, 0); deformArray.setSize(vertexCount, 0);
Vector<float> &deformInner = deformArray; Vector<float> &deformInner = deformArray;
if (attachment->getBones().size() == 0) { if (attachment->getBones().size() == 0) {
// Unweighted vertex positions. // Unweighted vertex positions.
Vector<float> &setupVertices = attachment->getVertices(); Vector<float> &setupVertices = attachment->getVertices();
for (size_t i = 0; i < vertexCount; i++) for (size_t i = 0; i < vertexCount; i++)
deformInner[i] += (setupVertices[i] - deformInner[i]) * alpha; deformInner[i] += (setupVertices[i] - deformInner[i]) * alpha;
} else { } else {
// Weighted deform offsets. // Weighted deform offsets.
alpha = 1 - alpha; alpha = 1 - alpha;
for (size_t i = 0; i < vertexCount; i++) for (size_t i = 0; i < vertexCount; i++)
deformInner[i] *= alpha; deformInner[i] *= alpha;
} }
} }
case MixBlend_Replace: case MixBlend_Replace:
case MixBlend_Add: case MixBlend_Add:
return; return;
} }
} }
deformArray.setSize(vertexCount, 0); deformArray.setSize(vertexCount, 0);
Vector<float> &deform = deformArray; Vector<float> &deform = deformArray;
if (time >= frames[frames.size() - 1]) { // Time is after last frame. if (time >= frames[frames.size() - 1]) { // Time is after last frame.
Vector<float> &lastVertices = frameVertices[frames.size() - 1]; Vector<float> &lastVertices = vertices[frames.size() - 1];
if (alpha == 1) { if (alpha == 1) {
if (blend == MixBlend_Add) { if (blend == MixBlend_Add) {
VertexAttachment *vertexAttachment = static_cast<VertexAttachment*>(slotAttachment); VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) { if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, no alpha. // Unweighted vertex positions, no alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices(); Vector<float> &setupVertices = vertexAttachment->getVertices();
for (size_t i = 0; i < vertexCount; i++) for (size_t i = 0; i < vertexCount; i++)
deform[i] += lastVertices[i] - setupVertices[i]; deform[i] += lastVertices[i] - setupVertices[i];
} else { } else {
// Weighted deform offsets, no alpha. // Weighted deform offsets, no alpha.
for (size_t i = 0; i < vertexCount; i++) for (size_t i = 0; i < vertexCount; i++)
deform[i] += lastVertices[i]; deform[i] += lastVertices[i];
} }
} else { } else {
// Vertex positions or deform offsets, no alpha. // Vertex positions or deform offsets, no alpha.
memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float)); memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float));
} }
} else { } else {
switch (blend) { switch (blend) {
case MixBlend_Setup: { case MixBlend_Setup: {
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment); VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) { if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, with alpha. // Unweighted vertex positions, with alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices(); Vector<float> &setupVertices = vertexAttachment->getVertices();
for (size_t i = 0; i < vertexCount; i++) { for (size_t i = 0; i < vertexCount; i++) {
float setup = setupVertices[i]; float setup = setupVertices[i];
deform[i] = setup + (lastVertices[i] - setup) * alpha; deform[i] = setup + (lastVertices[i] - setup) * alpha;
} }
} else { } else {
// Weighted deform offsets, with alpha. // Weighted deform offsets, with alpha.
for (size_t i = 0; i < vertexCount; i++) for (size_t i = 0; i < vertexCount; i++)
deform[i] = lastVertices[i] * alpha; deform[i] = lastVertices[i] * alpha;
} }
break; break;
} }
case MixBlend_First: case MixBlend_First:
case MixBlend_Replace: case MixBlend_Replace:
// Vertex positions or deform offsets, with alpha. // Vertex positions or deform offsets, with alpha.
for (size_t i = 0; i < vertexCount; i++) for (size_t i = 0; i < vertexCount; i++)
deform[i] += (lastVertices[i] - deform[i]) * alpha; deform[i] += (lastVertices[i] - deform[i]) * alpha;
break; break;
case MixBlend_Add: case MixBlend_Add:
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment); VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) { if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, no alpha. // Unweighted vertex positions, no alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices(); Vector<float> &setupVertices = vertexAttachment->getVertices();
for (size_t i = 0; i < vertexCount; i++) for (size_t i = 0; i < vertexCount; i++)
deform[i] += (lastVertices[i] - setupVertices[i]) * alpha; deform[i] += (lastVertices[i] - setupVertices[i]) * alpha;
} else { } else {
// Weighted deform offsets, alpha. // Weighted deform offsets, alpha.
for (size_t i = 0; i < vertexCount; i++) for (size_t i = 0; i < vertexCount; i++)
deform[i] += lastVertices[i] * alpha; deform[i] += lastVertices[i] * alpha;
} }
} }
} }
return; return;
} }
// Interpolate between the previous frame and the current frame. // Interpolate between the previous frame and the current frame.
int frame = Animation::binarySearch(frames, time); int frame = Animation::search(frames, time);
Vector<float> &prevVertices = frameVertices[frame - 1]; float percent = getCurvePercent(time, frame);
Vector<float> &nextVertices = frameVertices[frame]; Vector<float> &prevVertices = vertices[frame];
float frameTime = frames[frame]; Vector<float> &nextVertices = vertices[frame + 1];
float percent = getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime));
if (alpha == 1) { if (alpha == 1) {
if (blend == MixBlend_Add) { if (blend == MixBlend_Add) {
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment); VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) { if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, no alpha. // Unweighted vertex positions, no alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices(); Vector<float> &setupVertices = vertexAttachment->getVertices();
for (size_t i = 0; i < vertexCount; i++) { for (size_t i = 0; i < vertexCount; i++) {
float prev = prevVertices[i]; float prev = prevVertices[i];
deform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i]; deform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i];
} }
} else { } else {
// Weighted deform offsets, no alpha. // Weighted deform offsets, no alpha.
for (size_t i = 0; i < vertexCount; i++) { for (size_t i = 0; i < vertexCount; i++) {
float prev = prevVertices[i]; float prev = prevVertices[i];
deform[i] += prev + (nextVertices[i] - prev) * percent; deform[i] += prev + (nextVertices[i] - prev) * percent;
} }
} }
} else { } else {
// Vertex positions or deform offsets, no alpha. // Vertex positions or deform offsets, no alpha.
for (size_t i = 0; i < vertexCount; i++) { for (size_t i = 0; i < vertexCount; i++) {
float prev = prevVertices[i]; float prev = prevVertices[i];
deform[i] = prev + (nextVertices[i] - prev) * percent; deform[i] = prev + (nextVertices[i] - prev) * percent;
} }
} }
} else { } else {
switch (blend) { switch (blend) {
case MixBlend_Setup: { case MixBlend_Setup: {
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment); VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) { if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, with alpha. // Unweighted vertex positions, with alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices(); Vector<float> &setupVertices = vertexAttachment->getVertices();
for (size_t i = 0; i < vertexCount; i++) { for (size_t i = 0; i < vertexCount; i++) {
float prev = prevVertices[i], setup = setupVertices[i]; float prev = prevVertices[i], setup = setupVertices[i];
deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
} }
} else { } else {
// Weighted deform offsets, with alpha. // Weighted deform offsets, with alpha.
for (size_t i = 0; i < vertexCount; i++) { for (size_t i = 0; i < vertexCount; i++) {
float prev = prevVertices[i]; float prev = prevVertices[i];
deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
} }
} }
break; break;
} }
case MixBlend_First: case MixBlend_First:
case MixBlend_Replace: case MixBlend_Replace:
// Vertex positions or deform offsets, with alpha. // Vertex positions or deform offsets, with alpha.
for (size_t i = 0; i < vertexCount; i++) { for (size_t i = 0; i < vertexCount; i++) {
float prev = prevVertices[i]; float prev = prevVertices[i];
deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha; deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha;
} }
break; break;
case MixBlend_Add: case MixBlend_Add:
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment); VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) { if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, with alpha. // Unweighted vertex positions, with alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices(); Vector<float> &setupVertices = vertexAttachment->getVertices();
for (size_t i = 0; i < vertexCount; i++) { for (size_t i = 0; i < vertexCount; i++) {
float prev = prevVertices[i]; float prev = prevVertices[i];
deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha; deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha;
} }
} else { } else {
// Weighted deform offsets, with alpha. // Weighted deform offsets, with alpha.
for (size_t i = 0; i < vertexCount; i++) { for (size_t i = 0; i < vertexCount; i++) {
float prev = prevVertices[i]; float prev = prevVertices[i];
deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha; deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha;
} }
} }
} }
} }
} }
int DeformTimeline::getPropertyId() { void DeformTimeline::setBezier(int bezier, int frame, float value, float time1, float value1, float cx1, float cy1,
assert(_attachment != NULL); float cx2, float cy2, float time2, float value2) {
return ((int) TimelineType_Deform << 24) + _attachment->_id + _slotIndex; SP_UNUSED(value1);
SP_UNUSED(value2);
size_t i = getFrameCount() + bezier * DeformTimeline::BEZIER_SIZE;
if (value == 0) _curves[frame] = DeformTimeline::BEZIER + i;
float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06;
float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = (cy1 - cy2 + 0.33333333) * 0.018;
float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;
float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667;
float x = time1 + dx, y = dy;
for (size_t n = i + DeformTimeline::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;
}
}
float DeformTimeline::getCurvePercent(float time, int frame) {
int i = (int)_curves[frame];
switch (i) {
case DeformTimeline::LINEAR: {
float x = _frames[frame];
return (time - x) / (_frames[frame + getFrameEntries()] - x);
}
case DeformTimeline::STEPPED: {
return 0;
}
default: {}
}
i -= DeformTimeline::BEZIER;
if (_curves[i] > time) {
float x = _frames[frame];
return _curves[i + 1] * (time - x) / (_curves[i] - x);
}
int n = i + DeformTimeline::BEZIER_SIZE;
for (i += 2; i < n; i += 2) {
if (_curves[i] >= time) {
float x = _curves[i - 2], y = _curves[i - 1];
return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y);
}
}
float x = _curves[n - 2], y = _curves[n - 1];
return y + (1 - y) * (time - x) / (_frames[frame + getFrameEntries()] - x);
} }
void DeformTimeline::setFrame(int frameIndex, float time, Vector<float> &vertices) { void DeformTimeline::setFrame(int frameIndex, float time, Vector<float> &vertices) {
_frames[frameIndex] = time; _frames[frameIndex] = time;
_frameVertices[frameIndex].clear(); _vertices[frameIndex].clear();
_frameVertices[frameIndex].addAll(vertices); _vertices[frameIndex].addAll(vertices);
}
int DeformTimeline::getSlotIndex() {
return _slotIndex;
}
void DeformTimeline::setSlotIndex(int inValue) {
_slotIndex = inValue;
}
Vector<float> &DeformTimeline::getFrames() {
return _frames;
} }
Vector<Vector<float> > &DeformTimeline::getVertices() { Vector<Vector<float> > &DeformTimeline::getVertices() {
return _frameVertices; return _vertices;
} }
VertexAttachment *DeformTimeline::getAttachment() { VertexAttachment *DeformTimeline::getAttachment() {
return _attachment; return _attachment;
} }
void DeformTimeline::setAttachment(VertexAttachment *inValue) { void DeformTimeline::setAttachment(VertexAttachment *inValue) {
_attachment = inValue; _attachment = inValue;
} }

View File

@ -45,13 +45,12 @@ using namespace spine;
RTTI_IMPL(DrawOrderTimeline, Timeline) RTTI_IMPL(DrawOrderTimeline, Timeline)
DrawOrderTimeline::DrawOrderTimeline(int frameCount) : Timeline() { DrawOrderTimeline::DrawOrderTimeline(size_t frameCount) : Timeline(frameCount, 1) {
_frames.ensureCapacity(frameCount); PropertyId ids[] = {((PropertyId) Property_DrawOrder << 32)};
setPropertyIds(ids, 1);
_drawOrders.ensureCapacity(frameCount); _drawOrders.ensureCapacity(frameCount);
for (size_t i = 0; i < frameCount; ++i) {
_frames.setSize(frameCount, 0);
for (int i = 0; i < frameCount; ++i) {
Vector<int> vec; Vector<int> vec;
_drawOrders.add(vec); _drawOrders.add(vec);
} }
@ -86,14 +85,7 @@ void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Ve
return; return;
} }
size_t frame; Vector<int> &drawOrderToSetupIndex = _drawOrders[Animation::search(_frames, time)];
if (time >= _frames[_frames.size() - 1]) {
// Time is after last frame.
frame = _frames.size() - 1;
} else
frame = (size_t)Animation::binarySearch(_frames, time) - 1;
Vector<int> &drawOrderToSetupIndex = _drawOrders[frame];
if (drawOrderToSetupIndex.size() == 0) { if (drawOrderToSetupIndex.size() == 0) {
drawOrder.clear(); drawOrder.clear();
for (size_t i = 0, n = slots.size(); i < n; ++i) for (size_t i = 0, n = slots.size(); i < n; ++i)
@ -104,24 +96,12 @@ void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Ve
} }
} }
int DrawOrderTimeline::getPropertyId() { void DrawOrderTimeline::setFrame(size_t frame, float time, Vector<int> &drawOrder) {
return ((int) TimelineType_DrawOrder << 24); _frames[frame] = time;
} _drawOrders[frame].clear();
_drawOrders[frame].addAll(drawOrder);
void DrawOrderTimeline::setFrame(size_t frameIndex, float time, Vector<int> &drawOrder) {
_frames[frameIndex] = time;
_drawOrders[frameIndex].clear();
_drawOrders[frameIndex].addAll(drawOrder);
}
Vector<float> &DrawOrderTimeline::getFrames() {
return _frames;
} }
Vector<Vector<int> > &DrawOrderTimeline::getDrawOrders() { Vector<Vector<int> > &DrawOrderTimeline::getDrawOrders() {
return _drawOrders; return _drawOrders;
} }
size_t DrawOrderTimeline::getFrameCount() {
return _frames.size();
}

View File

@ -49,8 +49,9 @@ using namespace spine;
RTTI_IMPL(EventTimeline, Timeline) RTTI_IMPL(EventTimeline, Timeline)
EventTimeline::EventTimeline(int frameCount) : Timeline() { EventTimeline::EventTimeline(size_t frameCount) : Timeline(frameCount, 1) {
_frames.setSize(frameCount, 0); PropertyId ids[] = {((PropertyId) Property_Event << 32)};
setPropertyIds(ids, 1);
_events.setSize(frameCount, NULL); _events.setSize(frameCount, NULL);
} }
@ -72,40 +73,32 @@ void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
apply(skeleton, lastTime, FLT_MAX, pEvents, alpha, blend, direction); apply(skeleton, lastTime, FLT_MAX, pEvents, alpha, blend, direction);
lastTime = -1.0f; lastTime = -1.0f;
} else if (lastTime >= _frames[frameCount - 1]) { } else if (lastTime >= _frames[frameCount - 1]) {
// Last time is after last frame. // Last time is after last i.
return; return;
} }
if (time < _frames[0]) return; // Time is before first frame. if (time < _frames[0]) return; // Time is before first i.
int frame; int i;
if (lastTime < _frames[0]) { if (lastTime < _frames[0]) {
frame = 0; i = 0;
} else { } else {
frame = Animation::binarySearch(_frames, lastTime); i = Animation::search(_frames, lastTime) + 1;
float frameTime = _frames[frame]; float frameTime = _frames[i];
while (frame > 0) { while (i > 0) {
// Fire multiple events with the same frame. // Fire multiple events with the same i.
if (_frames[frame - 1] != frameTime) break; if (_frames[i - 1] != frameTime) break;
frame--; i--;
} }
} }
for (; (size_t)frame < frameCount && time >= _frames[frame]; ++frame) for (; (size_t)i < frameCount && time >= _frames[i]; i++)
events.add(_events[frame]); events.add(_events[i]);
} }
int EventTimeline::getPropertyId() { void EventTimeline::setFrame(size_t frame, Event *event) {
return ((int) TimelineType_Event << 24); _frames[frame] = event->getTime();
_events[frame] = event;
} }
void EventTimeline::setFrame(size_t frameIndex, Event *event) {
_frames[frameIndex] = event->getTime();
_events[frameIndex] = event;
}
Vector<float> EventTimeline::getFrames() { return _frames; }
Vector<Event *> &EventTimeline::getEvents() { return _events; } Vector<Event *> &EventTimeline::getEvents() { return _events; }
size_t EventTimeline::getFrameCount() { return _frames.size(); }

View File

@ -47,21 +47,9 @@ using namespace spine;
RTTI_IMPL(IkConstraintTimeline, CurveTimeline) RTTI_IMPL(IkConstraintTimeline, CurveTimeline)
const int IkConstraintTimeline::ENTRIES = 6; IkConstraintTimeline::IkConstraintTimeline(size_t frameCount, size_t bezierCount, int ikConstraintIndex) : CurveTimeline(frameCount, IkConstraintTimeline::ENTRIES, bezierCount), _ikConstraintIndex(ikConstraintIndex) {
const int IkConstraintTimeline::PREV_TIME = -6; PropertyId ids[] = { ((PropertyId)Property_IkConstraint << 32) | ikConstraintIndex };
const int IkConstraintTimeline::PREV_MIX = -5; setPropertyIds(ids, 1);
const int IkConstraintTimeline::PREV_SOFTNESS = -4;
const int IkConstraintTimeline::PREV_BEND_DIRECTION = -3;
const int IkConstraintTimeline::PREV_COMPRESS = -2;
const int IkConstraintTimeline::PREV_STRETCH = -1;
const int IkConstraintTimeline::MIX = 1;
const int IkConstraintTimeline::SOFTNESS = 2;
const int IkConstraintTimeline::BEND_DIRECTION = 3;
const int IkConstraintTimeline::COMPRESS = 4;
const int IkConstraintTimeline::STRETCH = 5;
IkConstraintTimeline::IkConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _ikConstraintIndex(0) {
_frames.setSize(frameCount * ENTRIES, 0);
} }
void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
@ -94,77 +82,62 @@ void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time,
} }
} }
if (time >= _frames[_frames.size() - ENTRIES]) { float mix = 0, softness = 0;
// Time is after last frame. int i = Animation::search(_frames, time, IkConstraintTimeline::ENTRIES);
if (blend == MixBlend_Setup) { int curveType = (int)_curves[i / IkConstraintTimeline::ENTRIES];
constraint._mix = switch (curveType) {
constraint._data._mix + (_frames[_frames.size() + PREV_MIX] - constraint._data._mix) * alpha; case IkConstraintTimeline::LINEAR: {
constraint._softness = constraint._data._softness float before = _frames[i];
+ (_frames[_frames.size() + PREV_SOFTNESS] - constraint._data._softness) * alpha; mix = _frames[i + IkConstraintTimeline::MIX];
if (direction == MixDirection_Out) { softness = _frames[i + IkConstraintTimeline::SOFTNESS];
constraint._bendDirection = constraint._data._bendDirection; float t = (time - before) / (_frames[i + IkConstraintTimeline::ENTRIES] - before);
constraint._compress = constraint._data._compress; mix += (_frames[i + IkConstraintTimeline::ENTRIES + IkConstraintTimeline::MIX] - mix) * t;
constraint._stretch = constraint._data._stretch; softness += (_frames[i + IkConstraintTimeline::ENTRIES + IkConstraintTimeline::SOFTNESS] - softness) * t;
} else { break;
constraint._bendDirection = (int) _frames[_frames.size() + PREV_BEND_DIRECTION]; }
constraint._compress = _frames[_frames.size() + PREV_COMPRESS] != 0; case IkConstraintTimeline::STEPPED: {
constraint._stretch = _frames[_frames.size() + PREV_STRETCH] != 0; mix = _frames[i + IkConstraintTimeline::MIX];
} softness = _frames[i + IkConstraintTimeline::SOFTNESS];
} else { break;
constraint._mix += (_frames[_frames.size() + PREV_MIX] - constraint._mix) * alpha; }
constraint._softness += (_frames[_frames.size() + PREV_SOFTNESS] - constraint._softness) * alpha; default: {
if (direction == MixDirection_In) { mix = getBezierValue(time, i, IkConstraintTimeline::MIX, curveType - IkConstraintTimeline::BEZIER);
constraint._bendDirection = (int) _frames[_frames.size() + PREV_BEND_DIRECTION]; softness = getBezierValue(time, i, IkConstraintTimeline::SOFTNESS,
constraint._compress = _frames[_frames.size() + PREV_COMPRESS] != 0; curveType + IkConstraintTimeline::BEZIER_SIZE -
constraint._stretch = _frames[_frames.size() + PREV_STRETCH] != 0; IkConstraintTimeline::BEZIER);
} }
} }
return;
}
// Interpolate between the previous frame and the current frame. if (blend == MixBlend_Setup) {
int frame = Animation::binarySearch(_frames, time, ENTRIES); constraint._mix = constraint._data._mix + (mix - constraint._data._mix) * alpha;
float mix = _frames[frame + PREV_MIX]; constraint._softness = constraint._data._softness + (softness - constraint._data._softness) * alpha;
float softness = _frames[frame + PREV_SOFTNESS];
float frameTime = _frames[frame];
float percent = getCurvePercent(frame / ENTRIES - 1,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
if (blend == MixBlend_Setup) { if (direction == MixDirection_Out) {
constraint._mix = constraint._bendDirection = constraint._data._bendDirection;
constraint._data._mix + (mix + (_frames[frame + MIX] - mix) * percent - constraint._data._mix) * alpha; constraint._compress = constraint._data._compress;
constraint._softness = constraint._data._softness constraint._stretch = constraint._data._stretch;
+ (softness + (_frames[frame + SOFTNESS] - softness) * percent - constraint._data._softness) * alpha; } else {
if (direction == MixDirection_Out) { constraint._bendDirection = _frames[i + IkConstraintTimeline::BEND_DIRECTION];
constraint._bendDirection = constraint._data._bendDirection; constraint._compress = _frames[i + IkConstraintTimeline::COMPRESS] != 0;
constraint._compress = constraint._data._compress; constraint._stretch = _frames[i + IkConstraintTimeline::STRETCH] != 0;
constraint._stretch = constraint._data._stretch; }
} else { } else {
constraint._bendDirection = (int) _frames[_frames.size() + PREV_BEND_DIRECTION]; constraint._mix += (mix - constraint._mix) * alpha;
constraint._compress = _frames[frame + PREV_COMPRESS] != 0; constraint._softness += (softness - constraint._softness) * alpha;
constraint._stretch = _frames[frame + PREV_STRETCH] != 0; if (direction == MixDirection_In) {
} constraint._bendDirection = _frames[i + IkConstraintTimeline::BEND_DIRECTION];
} else { constraint._compress = _frames[i + IkConstraintTimeline::COMPRESS] != 0;
constraint._mix += (mix + (_frames[frame + MIX] - mix) * percent - constraint._mix) * alpha; constraint._stretch = _frames[i + IkConstraintTimeline::STRETCH] != 0;
constraint._softness += (softness + (_frames[frame + SOFTNESS] - softness) * percent - constraint._softness) * alpha; }
if (direction == MixDirection_In) { }
constraint._bendDirection = (int) _frames[frame + PREV_BEND_DIRECTION];
constraint._compress = _frames[frame + PREV_COMPRESS] != 0;
constraint._stretch = _frames[frame + PREV_STRETCH] != 0;
}
}
} }
int IkConstraintTimeline::getPropertyId() { void IkConstraintTimeline::setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch) {
return ((int) TimelineType_IkConstraint << 24) + _ikConstraintIndex; frame *= ENTRIES;
} _frames[frame] = time;
_frames[frame + MIX] = mix;
void IkConstraintTimeline::setFrame(int frameIndex, float time, float mix, float softness, int bendDirection, bool compress, bool stretch) { _frames[frame + SOFTNESS] = softness;
frameIndex *= ENTRIES; _frames[frame + BEND_DIRECTION] = (float)bendDirection;
_frames[frameIndex] = time; _frames[frame + COMPRESS] = compress ? 1 : 0;
_frames[frameIndex + MIX] = mix; _frames[frame + STRETCH] = stretch ? 1 : 0;
_frames[frameIndex + SOFTNESS] = softness;
_frames[frameIndex + BEND_DIRECTION] = (float)bendDirection;
_frames[frameIndex + COMPRESS] = compress ? 1 : 0;
_frames[frameIndex + STRETCH] = stretch ? 1 : 0;
} }

View File

@ -47,17 +47,10 @@ using namespace spine;
RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline) RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline)
const int PathConstraintMixTimeline::ENTRIES = 3; PathConstraintMixTimeline::PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex) : CurveTimeline(frameCount, PathConstraintMixTimeline::ENTRIES, bezierCount),
const int PathConstraintMixTimeline::PREV_TIME = -3; _pathConstraintIndex(pathConstraintIndex) {
const int PathConstraintMixTimeline::PREV_ROTATE = -2; PropertyId ids[] = { ((PropertyId)Property_PathConstraintMix << 32) | pathConstraintIndex };
const int PathConstraintMixTimeline::PREV_TRANSLATE = -1; setPropertyIds(ids, 1);
const int PathConstraintMixTimeline::ROTATE = 1;
const int PathConstraintMixTimeline::TRANSLATE = 2;
PathConstraintMixTimeline::PathConstraintMixTimeline(int frameCount) : CurveTimeline(frameCount),
_pathConstraintIndex(0)
{
_frames.setSize(frameCount * ENTRIES, 0);
} }
void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
@ -71,56 +64,66 @@ void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float
PathConstraint &constraint = *constraintP; PathConstraint &constraint = *constraintP;
if (!constraint.isActive()) return; if (!constraint.isActive()) return;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (blend) { switch (blend) {
case MixBlend_Setup: case MixBlend_Setup:
constraint._rotateMix = constraint._data._rotateMix; constraint._mixRotate = constraint._data._mixRotate;
constraint._translateMix = constraint._data._translateMix; constraint._mixX = constraint._data._mixX;
return; constraint._mixY = constraint._data._mixY;
case MixBlend_First: return;
constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha; case MixBlend_First:
constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha; constraint._mixRotate += (constraint._data._mixRotate - constraint._mixRotate) * alpha;
return; constraint._mixX += (constraint._data._mixX - constraint._mixX) * alpha;
default: constraint._mixY += (constraint._data._mixY - constraint._mixY) * alpha;
return; default: {}
} }
} return;
}
float rotate, translate; float rotate, x, y;
if (time >= _frames[_frames.size() - ENTRIES]) { int i = Animation::search(_frames, time, PathConstraintMixTimeline::ENTRIES);
// Time is after last frame. int curveType = (int)_curves[i >> 2];
rotate = _frames[_frames.size() + PREV_ROTATE]; switch (curveType) {
translate = _frames[_frames.size() + PREV_TRANSLATE]; case LINEAR: {
} else { float before = _frames[i];
// Interpolate between the previous frame and the current frame. rotate = _frames[i + ROTATE];
int frame = Animation::binarySearch(_frames, time, ENTRIES); x = _frames[i + X];
rotate = _frames[frame + PREV_ROTATE]; y = _frames[i + Y];
translate = _frames[frame + PREV_TRANSLATE]; float t = (time - before) / (_frames[i + ENTRIES] - before);
float frameTime = _frames[frame]; rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t;
float percent = getCurvePercent(frame / ENTRIES - 1, x += (_frames[i + ENTRIES + X] - x) * t;
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); y += (_frames[i + ENTRIES + Y] - y) * t;
break;
}
case STEPPED: {
rotate = _frames[i + ROTATE];
x = _frames[i + X];
y = _frames[i + Y];
break;
}
default: {
rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER);
x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER);
y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER);
}
}
rotate += (_frames[frame + ROTATE] - rotate) * percent; if (blend == MixBlend_Setup) {
translate += (_frames[frame + TRANSLATE] - translate) * percent; PathConstraintData data = constraint._data;
} constraint._mixRotate = data._mixRotate + (rotate - data._mixRotate) * alpha;
constraint._mixX = data._mixX + (x - data._mixX) * alpha;
if (blend == MixBlend_Setup) { constraint._mixY = data._mixY + (y - data._mixY) * alpha;
constraint._rotateMix = constraint._data._rotateMix + (rotate - constraint._data._rotateMix) * alpha; } else {
constraint._translateMix = constraint._mixRotate += (rotate - constraint._mixRotate) * alpha;
constraint._data._translateMix + (translate - constraint._data._translateMix) * alpha; constraint._mixX += (x - constraint._mixX) * alpha;
} else { constraint._mixY += (y - constraint._mixY) * alpha;
constraint._rotateMix += (rotate - constraint._rotateMix) * alpha; }
constraint._translateMix += (translate - constraint._translateMix) * alpha;
}
} }
int PathConstraintMixTimeline::getPropertyId() { void PathConstraintMixTimeline::setFrame(int frameIndex, float time, float mixRotate, float mixX, float mixY) {
return ((int) TimelineType_PathConstraintMix << 24) + _pathConstraintIndex;
}
void PathConstraintMixTimeline::setFrame(int frameIndex, float time, float rotateMix, float translateMix) {
frameIndex *= ENTRIES; frameIndex *= ENTRIES;
_frames[frameIndex] = time; _frames[frameIndex] = time;
_frames[frameIndex + ROTATE] = rotateMix; _frames[frameIndex + ROTATE] = mixRotate;
_frames[frameIndex + TRANSLATE] = translateMix; _frames[frameIndex + X] = mixX;
_frames[frameIndex + Y] = mixY;
} }

View File

@ -45,17 +45,12 @@
using namespace spine; using namespace spine;
RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline) RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline1)
const int PathConstraintPositionTimeline::ENTRIES = 2; PathConstraintPositionTimeline::PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex) : CurveTimeline1(frameCount, bezierCount),
const int PathConstraintPositionTimeline::PREV_TIME = -2; _pathConstraintIndex(pathConstraintIndex) {
const int PathConstraintPositionTimeline::PREV_VALUE = -1; PropertyId ids[] = { ((PropertyId)Property_PathConstraintPosition << 32) | pathConstraintIndex };
const int PathConstraintPositionTimeline::VALUE = 1; setPropertyIds(ids, 1);
PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount),
_pathConstraintIndex(0)
{
_frames.setSize(frameCount * ENTRIES, 0);
} }
PathConstraintPositionTimeline::~PathConstraintPositionTimeline() { PathConstraintPositionTimeline::~PathConstraintPositionTimeline() {
@ -85,32 +80,10 @@ void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, f
} }
} }
float position; float position = getCurveValue(time);
if (time >= _frames[_frames.size() - ENTRIES]) {
// Time is after last frame.
position = _frames[_frames.size() + PREV_VALUE];
} else {
// Interpolate between the previous frame and the current frame.
int frame = Animation::binarySearch(_frames, time, ENTRIES);
position = _frames[frame + PREV_VALUE];
float frameTime = _frames[frame];
float percent = getCurvePercent(frame / ENTRIES - 1,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
position += (_frames[frame + VALUE] - position) * percent;
}
if (blend == MixBlend_Setup) if (blend == MixBlend_Setup)
constraint._position = constraint._data._position + (position - constraint._data._position) * alpha; constraint._position = constraint._data._position + (position - constraint._data._position) * alpha;
else else
constraint._position += (position - constraint._position) * alpha; constraint._position += (position - constraint._position) * alpha;
} }
int PathConstraintPositionTimeline::getPropertyId() {
return ((int) TimelineType_PathConstraintPosition << 24) + _pathConstraintIndex;
}
void PathConstraintPositionTimeline::setFrame(int frameIndex, float time, float value) {
frameIndex *= ENTRIES;
_frames[frameIndex] = time;
_frames[frameIndex + VALUE] = value;
}

View File

@ -47,8 +47,9 @@ using namespace spine;
RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline) RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline)
PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(int frameCount) : PathConstraintPositionTimeline( PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex) : CurveTimeline1(frameCount, bezierCount), _pathConstraintIndex(pathConstraintIndex) {
frameCount) { PropertyId ids[] = { ((PropertyId)Property_PathConstraintSpacing << 32) | pathConstraintIndex };
setPropertyIds(ids, 1);
} }
void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents,
@ -75,27 +76,10 @@ void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, fl
} }
} }
float spacing; float spacing = getCurveValue(time);
if (time >= _frames[_frames.size() - ENTRIES]) {
// Time is after last frame.
spacing = _frames[_frames.size() + PREV_VALUE];
} else {
// Interpolate between the previous frame and the current frame.
int frame = Animation::binarySearch(_frames, time, ENTRIES);
spacing = _frames[frame + PREV_VALUE];
float frameTime = _frames[frame];
float percent = getCurvePercent(frame / ENTRIES - 1,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
spacing += (_frames[frame + VALUE] - spacing) * percent; if (blend == MixBlend_Setup)
} constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha;
else
if (blend == MixBlend_Setup) constraint._spacing += (spacing - constraint._spacing) * alpha;
constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha;
else
constraint._spacing += (spacing - constraint._spacing) * alpha;
}
int PathConstraintSpacingTimeline::getPropertyId() {
return ((int) TimelineType_PathConstraintSpacing << 24) + _pathConstraintIndex;
} }

View File

@ -43,9 +43,15 @@
using namespace spine; using namespace spine;
RTTI_IMPL(ShearTimeline, TranslateTimeline) RTTI_IMPL(ShearTimeline, CurveTimeline2)
ShearTimeline::ShearTimeline(int frameCount) : TranslateTimeline(frameCount) { ShearTimeline::ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, bezierCount), _boneIndex(boneIndex) {
PropertyId ids[] = { ((PropertyId)Property_ShearX << 32) | boneIndex,
((PropertyId)Property_ShearY << 32) | boneIndex};
setPropertyIds(ids, 2);
}
ShearTimeline::~ShearTimeline() {
} }
void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
@ -55,58 +61,152 @@ void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
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._shearX = bone._data._shearX; bone->_shearX = bone->_data._shearX;
bone._shearY = bone._data._shearY; bone->_shearY = bone->_data._shearY;
return; return;
case MixBlend_First: case MixBlend_First:
bone._shearX += (bone._data._shearX - bone._shearX) * alpha; bone->_shearX += (bone->_data._shearX - bone->_shearX) * alpha;
bone._shearY += (bone._data._shearY - bone._shearY) * alpha; bone->_shearY += (bone->_data._shearY - bone->_shearY) * alpha;
default: {} default: {}
} }
return; return;
} }
float x, y; float x, y;
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 CurveTimeline2::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 CurveTimeline2::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 = x + (_frames[frame + X] - x) * percent; switch (blend) {
y = y + (_frames[frame + Y] - y) * percent; case MixBlend_Setup:
} bone->_shearX = bone->_data._shearX + x * alpha;
bone->_shearY = bone->_data._shearY + y * alpha;
switch (blend) { break;
case MixBlend_Setup: case MixBlend_First:
bone._shearX = bone._data._shearX + x * alpha; case MixBlend_Replace:
bone._shearY = bone._data._shearY + y * alpha; bone->_shearX += (bone->_data._shearX + x - bone->_shearX) * alpha;
break; bone->_shearY += (bone->_data._shearY + y - bone->_shearY) * alpha;
case MixBlend_First: break;
case MixBlend_Replace: case MixBlend_Add:
bone._shearX += (bone._data._shearX + x - bone._shearX) * alpha; bone->_shearX += x * alpha;
bone._shearY += (bone._data._shearY + y - bone._shearY) * alpha; bone->_shearY += y * alpha;
break; }
case MixBlend_Add:
bone._shearX += x * alpha;
bone._shearY += y * alpha;
}
} }
int ShearTimeline::getPropertyId() { RTTI_IMPL(ShearXTimeline, CurveTimeline1)
return ((int) TimelineType_Shear << 24) + _boneIndex;
ShearXTimeline::ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
PropertyId ids[] = { ((PropertyId)Property_ShearX << 32) | boneIndex };
setPropertyIds(ids, 1);
}
ShearXTimeline::~ShearXTimeline() {
}
void ShearXTimeline::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->_shearX = bone->_data._shearX;
return;
case MixBlend_First:
bone->_shearX += (bone->_data._shearX - bone->_shearX) * alpha;
default: {}
}
return;
}
float x = getCurveValue(time);
switch (blend) {
case MixBlend_Setup:
bone->_shearX = bone->_data._shearX + x * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bone->_shearX += (bone->_data._shearX + x - bone->_shearX) * alpha;
break;
case MixBlend_Add:
bone->_shearX += x * alpha;
}
}
RTTI_IMPL(ShearYTimeline, CurveTimeline1)
ShearYTimeline::ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
PropertyId ids[] = { ((PropertyId)Property_ShearX << 32) | boneIndex };
setPropertyIds(ids, 1);
}
ShearYTimeline::~ShearYTimeline() {
}
void ShearYTimeline::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->_shearY = bone->_data._shearY;
return;
case MixBlend_First:
bone->_shearY += (bone->_data._shearY - bone->_shearY) * alpha;
default: {}
}
return;
}
float y = getCurveValue(time);
switch (blend) {
case MixBlend_Setup:
bone->_shearY = bone->_data._shearY + y * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bone->_shearY += (bone->_data._shearY + y - bone->_shearY) * alpha;
break;
case MixBlend_Add:
bone->_shearY += y * alpha;
}
} }

View File

@ -47,21 +47,10 @@ using namespace spine;
RTTI_IMPL(TransformConstraintTimeline, CurveTimeline) RTTI_IMPL(TransformConstraintTimeline, CurveTimeline)
const int TransformConstraintTimeline::ENTRIES = 5; TransformConstraintTimeline::TransformConstraintTimeline(size_t frameCount, size_t bezierCount, int transformConstraintIndex) : CurveTimeline(frameCount, TransformConstraintTimeline::ENTRIES, bezierCount),
const int TransformConstraintTimeline::PREV_TIME = -5; _transformConstraintIndex(transformConstraintIndex) {
const int TransformConstraintTimeline::PREV_ROTATE = -4; PropertyId ids[] = { ((PropertyId)Property_TransformConstraint << 32) | transformConstraintIndex };
const int TransformConstraintTimeline::PREV_TRANSLATE = -3; setPropertyIds(ids, 1);
const int TransformConstraintTimeline::PREV_SCALE = -2;
const int TransformConstraintTimeline::PREV_SHEAR = -1;
const int TransformConstraintTimeline::ROTATE = 1;
const int TransformConstraintTimeline::TRANSLATE = 2;
const int TransformConstraintTimeline::SCALE = 3;
const int TransformConstraintTimeline::SHEAR = 4;
TransformConstraintTimeline::TransformConstraintTimeline(int frameCount) : CurveTimeline(frameCount),
_transformConstraintIndex(0)
{
_frames.setSize(frameCount * ENTRIES, 0);
} }
void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents,
@ -74,75 +63,94 @@ void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, floa
TransformConstraint &constraint = *constraintP; TransformConstraint &constraint = *constraintP;
if (!constraint.isActive()) return; if (!constraint.isActive()) return;
TransformConstraintData &data = constraint._data;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (blend) { switch (blend) {
case MixBlend_Setup: case MixBlend_Setup:
constraint._rotateMix = constraint._data._rotateMix; constraint._mixRotate = data._mixRotate;
constraint._translateMix = constraint._data._translateMix; constraint._mixX = data._mixX;
constraint._scaleMix = constraint._data._scaleMix; constraint._mixY = data._mixY;
constraint._shearMix = constraint._data._shearMix; constraint._mixScaleX = data._mixScaleX;
constraint._mixScaleY = data._mixScaleY;
constraint._mixShearY = data._mixShearY;
return; return;
case MixBlend_First: case MixBlend_First:
constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha; constraint._mixRotate += (data._mixRotate - constraint._mixRotate) * alpha;
constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha; constraint._mixX += (data._mixX - constraint._mixX) * alpha;
constraint._scaleMix += (constraint._data._scaleMix - constraint._scaleMix) * alpha; constraint._mixY += (data._mixY - constraint._mixY) * alpha;
constraint._shearMix += (constraint._data._shearMix - constraint._shearMix) * alpha; constraint._mixScaleX += (data._mixScaleX - constraint._mixScaleX) * alpha;
constraint._mixScaleY += (data._mixScaleY - constraint._mixScaleY) * alpha;
constraint._mixShearY += (data._mixShearY - constraint._mixShearY) * alpha;
return; return;
default: default:
return; return;
} }
} }
float rotate, translate, scale, shear; float rotate, x, y, scaleX, scaleY, shearY;
if (time >= _frames[_frames.size() - ENTRIES]) { int i = Animation::search(_frames, time, TransformConstraintTimeline::ENTRIES);
// Time is after last frame. int curveType = (int)_curves[i / TransformConstraintTimeline::ENTRIES];
size_t i = _frames.size(); switch (curveType) {
rotate = _frames[i + PREV_ROTATE]; case TransformConstraintTimeline::LINEAR: {
translate = _frames[i + PREV_TRANSLATE]; float before = _frames[i];
scale = _frames[i + PREV_SCALE]; rotate = _frames[i + ROTATE];
shear = _frames[i + PREV_SHEAR]; x = _frames[i + X];
} else { y = _frames[i + Y];
// Interpolate between the previous frame and the current frame. scaleX = _frames[i + SCALEX];
int frame = Animation::binarySearch(_frames, time, ENTRIES); scaleY = _frames[i + SCALEY];
rotate = _frames[frame + PREV_ROTATE]; shearY = _frames[i + SHEARY];
translate = _frames[frame + PREV_TRANSLATE]; float t = (time - before) / (_frames[i + ENTRIES] - before);
scale = _frames[frame + PREV_SCALE]; rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t;
shear = _frames[frame + PREV_SHEAR]; x += (_frames[i + ENTRIES + X] - x) * t;
float frameTime = _frames[frame]; y += (_frames[i + ENTRIES + Y] - y) * t;
float percent = getCurvePercent(frame / ENTRIES - 1, scaleX += (_frames[i + ENTRIES + SCALEX] - scaleX) * t;
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); scaleY += (_frames[i + ENTRIES + SCALEY] - scaleY) * t;
shearY += (_frames[i + ENTRIES + SHEARY] - shearY) * t;
break;
}
case TransformConstraintTimeline::STEPPED: {
rotate = _frames[i + ROTATE];
x = _frames[i + X];
y = _frames[i + Y];
scaleX = _frames[i + SCALEX];
scaleY = _frames[i + SCALEY];
shearY = _frames[i + SHEARY];
break;
}
default: {
rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER);
x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER);
y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER);
scaleX = getBezierValue(time, i, SCALEX, curveType + BEZIER_SIZE * 3 - BEZIER);
scaleY = getBezierValue(time, i, SCALEY, curveType + BEZIER_SIZE * 4 - BEZIER);
shearY = getBezierValue(time, i, SHEARY, curveType + BEZIER_SIZE * 5 - BEZIER);
}
}
rotate += (_frames[frame + ROTATE] - rotate) * percent; if (blend == MixBlend_Setup) {
translate += (_frames[frame + TRANSLATE] - translate) * percent; constraint._mixRotate = data._mixRotate + (rotate - data._mixRotate) * alpha;
scale += (_frames[frame + SCALE] - scale) * percent; constraint._mixX = data._mixX + (x - data._mixX) * alpha;
shear += (_frames[frame + SHEAR] - shear) * percent; constraint._mixY = data._mixY + (y - data._mixY) * alpha;
} constraint._mixScaleX = data._mixScaleX + (scaleX - data._mixScaleX) * alpha;
constraint._mixScaleY = data._mixScaleY + (scaleY - data._mixScaleY) * alpha;
if (blend == MixBlend_Setup) { constraint._mixShearY = data._mixShearY + (shearY - data._mixShearY) * alpha;
TransformConstraintData &data = constraint._data; } else {
constraint._rotateMix = data._rotateMix + (rotate - data._rotateMix) * alpha; constraint._mixRotate += (rotate - constraint._mixRotate) * alpha;
constraint._translateMix = data._translateMix + (translate - data._translateMix) * alpha; constraint._mixX += (x - constraint._mixX) * alpha;
constraint._scaleMix = data._scaleMix + (scale - data._scaleMix) * alpha; constraint._mixY += (y - constraint._mixY) * alpha;
constraint._shearMix = data._shearMix + (shear - data._shearMix) * alpha; constraint._mixScaleX += (scaleX - constraint._mixScaleX) * alpha;
} else { constraint._mixScaleY += (scaleY - constraint._mixScaleY) * alpha;
constraint._rotateMix += (rotate - constraint._rotateMix) * alpha; constraint._mixShearY += (shearY - constraint._mixShearY) * alpha;
constraint._translateMix += (translate - constraint._translateMix) * alpha; }
constraint._scaleMix += (scale - constraint._scaleMix) * alpha;
constraint._shearMix += (shear - constraint._shearMix) * alpha;
}
} }
int TransformConstraintTimeline::getPropertyId() { void TransformConstraintTimeline::setFrame(size_t frameIndex, float time, float mixRotate, float mixX, float mixY, float mixScaleX, float mixScaleY, float mixShearY) {
return ((int) TimelineType_TransformConstraint << 24) + _transformConstraintIndex;
}
void TransformConstraintTimeline::setFrame(size_t frameIndex, float time, float rotateMix, float translateMix, float scaleMix,
float shearMix
) {
frameIndex *= ENTRIES; frameIndex *= ENTRIES;
_frames[frameIndex] = time; _frames[frameIndex] = time;
_frames[frameIndex + ROTATE] = rotateMix; _frames[frameIndex + ROTATE] = mixRotate;
_frames[frameIndex + TRANSLATE] = translateMix; _frames[frameIndex + X] = mixX;
_frames[frameIndex + SCALE] = scaleMix; _frames[frameIndex + Y] = mixY;
_frames[frameIndex + SHEAR] = shearMix; _frames[frameIndex + SCALEX] = mixScaleX;
_frames[frameIndex + SCALEY] = mixScaleY;
_frames[frameIndex + SHEARY] = mixShearY;
} }

View File

@ -1034,7 +1034,7 @@ module spine {
/** Changes a slot's {@link Slot#color}. */ /** Changes a slot's {@link Slot#color}. */
export class RGBTimeline extends CurveTimeline implements SlotTimeline { export class RGBTimeline extends CurveTimeline implements SlotTimeline {
static ENTRIES = 5; static ENTRIES = 4;
static R = 1; static G = 2; static B = 3; static R = 1; static G = 2; static B = 3;
@ -1264,7 +1264,7 @@ module spine {
let light = slot.color, dark = slot.darkColor; let light = slot.color, dark = slot.darkColor;
if (alpha == 1) { if (alpha == 1) {
slot.color.set(r, g, b, a); light.set(r, g, b, a);
dark.r = r2; dark.r = r2;
dark.g = g2; dark.g = g2;
dark.b = b2; dark.b = b2;