[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 ColorTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class DeformTimeline;

View File

@ -50,23 +50,24 @@ namespace spine {
RTTI_DECL
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 int getPropertyId();
/// 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();
size_t getFrameCount();
private:
size_t _slotIndex;
Vector<float> _frames;
int getSlotIndex() { return _slotIndex; }
void setSlotIndex(int inValue) { _slotIndex = inValue; }
protected:
int _slotIndex;
Vector<String> _attachmentNames;
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 AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class ScaleTimeline;
friend class ScaleXTimeline;
@ -71,6 +83,10 @@ class SP_API Bone : public Updatable {
friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;

View File

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

View File

@ -51,6 +51,14 @@ public:
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) {
r = other.r;
g = other.g;
@ -69,6 +77,14 @@ public:
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) {
r += other.r;
g += other.g;

View File

@ -33,48 +33,165 @@
#include <spine/CurveTimeline.h>
namespace spine {
class SP_API ColorTimeline : public CurveTimeline {
friend class SkeletonBinary;
class SP_API RGBATimeline : public CurveTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class SkeletonJson;
RTTI_DECL
RTTI_DECL
public:
static const int ENTRIES;
public:
explicit RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex);
explicit ColorTimeline(int frameCount);
virtual ~RGBATimeline();
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.
void setFrame(int frame, float time, float r, float g, float b, float a);
/// Sets the time and value of the specified keyframe.
void setFrame(int frameIndex, float time, float r, float g, float b, float a);
int getSlotIndex() { return _slotIndex; };
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:
static const int PREV_TIME;
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;
class SP_API RGBTimeline : public CurveTimeline {
friend class SkeletonBinary;
private:
int _slotIndex;
Vector<float> _frames;
};
friend class SkeletonJson;
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 */

View File

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

View File

@ -33,37 +33,47 @@
#include <spine/CurveTimeline.h>
namespace spine {
class VertexAttachment;
class VertexAttachment;
class SP_API DeformTimeline : public CurveTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
class SP_API DeformTimeline : public CurveTimeline {
friend class SkeletonBinary;
RTTI_DECL
friend class SkeletonJson;
public:
explicit DeformTimeline(int frameCount);
RTTI_DECL
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.
void setFrame(int frameIndex, float time, Vector<float>& vertices);
/// Sets the time and value of the specified keyframe.
void setFrame(int frameIndex, float time, Vector<float> &vertices);
int getSlotIndex();
void setSlotIndex(int inValue);
Vector<float>& getFrames();
Vector< Vector<float> >& getVertices();
VertexAttachment* getAttachment();
void setAttachment(VertexAttachment* inValue);
Vector <Vector<float>> &getVertices();
private:
int _slotIndex;
Vector<float> _frames;
Vector< Vector<float> > _frameVertices;
VertexAttachment* _attachment;
};
VertexAttachment *getAttachment();
void setAttachment(VertexAttachment *inValue);
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 */

View File

@ -40,22 +40,17 @@ namespace spine {
RTTI_DECL
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 int getPropertyId();
/// Sets the time and value of the specified keyframe.
/// @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();
size_t getFrameCount();
private:
Vector<float> _frames;
Vector< Vector<int> > _drawOrders;
};
}

View File

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

View File

@ -41,32 +41,25 @@ namespace spine {
RTTI_DECL
public:
static const int ENTRIES;
explicit IkConstraintTimeline(int frameCount);
explicit IkConstraintTimeline(size_t frameCount, size_t bezierCount, int ikConstraintIndex);
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.
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:
static const int PREV_TIME;
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;
int _ikConstraintIndex;
Vector<float> _frames;
int _ikConstraintIndex;
static const int ENTRIES = 6;
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
public:
static const int ENTRIES;
explicit PathConstraintMixTimeline(int frameCount);
explicit PathConstraintMixTimeline(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 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:
static const int PREV_TIME;
static const int PREV_ROTATE;
static const int PREV_TRANSLATE;
static const int ROTATE;
static const int TRANSLATE;
int _pathConstraintIndex;
Vector<float> _frames;
int _pathConstraintIndex;
/// Sets the time and mixes of the specified keyframe.
void setFrame(int frameIndex, float time, float rotateMix, float translateMix);
static const int ENTRIES = 4;
static const int ROTATE = 1;
static const int X = 2;
static const int Y = 2;
};
}

View File

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

View File

@ -33,18 +33,22 @@
#include <spine/PathConstraintPositionTimeline.h>
namespace spine {
class SP_API PathConstraintSpacingTimeline : public PathConstraintPositionTimeline {
class SP_API PathConstraintSpacingTimeline : public CurveTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
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 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_PathConstraintPosition = 1 << 16,
Property_PathConstraintSpacing = 1 << 17,
Property_OathConstraintMix = 1 << 18
Property_PathConstraintMix = 1 << 18
};
}

View File

@ -33,19 +33,65 @@
#include <spine/TranslateTimeline.h>
namespace spine {
class SP_API ShearTimeline : public TranslateTimeline {
class SP_API ShearTimeline : public CurveTimeline2 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
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 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 */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -44,102 +44,461 @@
using namespace spine;
RTTI_IMPL(ColorTimeline, CurveTimeline)
RTTI_IMPL(RGBATimeline, CurveTimeline)
const int ColorTimeline::ENTRIES = 5;
const int ColorTimeline::PREV_TIME = -5;
const int ColorTimeline::PREV_R = -4;
const int ColorTimeline::PREV_G = -3;
const int ColorTimeline::PREV_B = -2;
const int ColorTimeline::PREV_A = -1;
const int ColorTimeline::R = 1;
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);
RGBATimeline::RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount,
RGBATimeline::ENTRIES,
bezierCount),
_slotIndex(slotIndex) {
PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex,
((PropertyId) Property_Alpha << 32) | slotIndex};
setPropertyIds(ids, 2);
}
void ColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixBlend blend, MixDirection direction
RGBATimeline::~RGBATimeline() {
}
void RGBATimeline::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);
SP_UNUSED(lastTime);
SP_UNUSED(pEvents);
SP_UNUSED(direction);
Slot *slotP = skeleton._slots[_slotIndex];
Slot &slot = *slotP;
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;
}
Slot *slot = skeleton._slots[_slotIndex];
if (!slot->_bone._active) return;
float r, g, b, a;
if (time >= _frames[_frames.size() - ENTRIES]) {
// Time is after last frame.
size_t i = _frames.size();
r = _frames[i + PREV_R];
g = _frames[i + PREV_G];
b = _frames[i + PREV_B];
a = _frames[i + PREV_A];
} else {
// Interpolate between the previous frame and the current frame.
size_t frame = (size_t)Animation::binarySearch(_frames, time, ENTRIES);
r = _frames[frame + PREV_R];
g = _frames[frame + PREV_G];
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));
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;
}
r += (_frames[frame + R] - r) * percent;
g += (_frames[frame + G] - g) * percent;
b += (_frames[frame + B] - b) * percent;
a += (_frames[frame + A] - a) * percent;
}
if (alpha == 1) {
slot.getColor().set(r, g, b, a);
} else {
Color &color = slot.getColor();
if (blend == MixBlend_Setup) color.set(slot.getData().getColor());
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
}
float r = 0, g = 0, b = 0, a = 0;
int i = Animation::search(_frames, time, RGBATimeline::ENTRIES);
int curveType = (int) _curves[i / RGBATimeline::ENTRIES];
switch (curveType) {
case RGBATimeline::LINEAR: {
float before = _frames[i];
r = _frames[i + RGBATimeline::R];
g = _frames[i + RGBATimeline::G];
b = _frames[i + RGBATimeline::B];
a = _frames[i + RGBATimeline::A];
float t = (time - before) / (_frames[i + RGBATimeline::ENTRIES] - before);
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() {
return ((int) TimelineType_Color << 24) + _slotIndex;
void RGBATimeline::setFrame(int frame, float time, float r, float g, float b, float a) {
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) {
frameIndex *= ENTRIES;
_frames[frameIndex] = time;
_frames[frameIndex + R] = r;
_frames[frameIndex + G] = g;
_frames[frameIndex + B] = b;
_frames[frameIndex + A] = a;
RTTI_IMPL(RGBTimeline, CurveTimeline)
RGBTimeline::RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : CurveTimeline(frameCount,
RGBTimeline::ENTRIES,
bezierCount),
_slotIndex(slotIndex) {
PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex};
setPropertyIds(ids, 1);
}
int ColorTimeline::getSlotIndex() {
return _slotIndex;
RGBTimeline::~RGBTimeline() {
}
void ColorTimeline::setSlotIndex(int inValue) {
_slotIndex = inValue;
void RGBTimeline::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 &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() {
return _frames;
void RGBTimeline::setFrame(int frame, float time, float r, float g, float b) {
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)
const int CurveTimeline1::ENTRIES = 2;
const int CurveTimeline1::VALUE = 1;
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)
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) {
}

View File

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

View File

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

View File

@ -49,8 +49,9 @@ using namespace spine;
RTTI_IMPL(EventTimeline, Timeline)
EventTimeline::EventTimeline(int frameCount) : Timeline() {
_frames.setSize(frameCount, 0);
EventTimeline::EventTimeline(size_t frameCount) : Timeline(frameCount, 1) {
PropertyId ids[] = {((PropertyId) Property_Event << 32)};
setPropertyIds(ids, 1);
_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);
lastTime = -1.0f;
} else if (lastTime >= _frames[frameCount - 1]) {
// Last time is after last frame.
// Last time is after last i.
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]) {
frame = 0;
i = 0;
} else {
frame = Animation::binarySearch(_frames, lastTime);
float frameTime = _frames[frame];
while (frame > 0) {
// Fire multiple events with the same frame.
if (_frames[frame - 1] != frameTime) break;
frame--;
i = Animation::search(_frames, lastTime) + 1;
float frameTime = _frames[i];
while (i > 0) {
// Fire multiple events with the same i.
if (_frames[i - 1] != frameTime) break;
i--;
}
}
for (; (size_t)frame < frameCount && time >= _frames[frame]; ++frame)
events.add(_events[frame]);
for (; (size_t)i < frameCount && time >= _frames[i]; i++)
events.add(_events[i]);
}
int EventTimeline::getPropertyId() {
return ((int) TimelineType_Event << 24);
void EventTimeline::setFrame(size_t frame, Event *event) {
_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; }
size_t EventTimeline::getFrameCount() { return _frames.size(); }

View File

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

View File

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

View File

@ -45,17 +45,12 @@
using namespace spine;
RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline)
RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline1)
const int PathConstraintPositionTimeline::ENTRIES = 2;
const int PathConstraintPositionTimeline::PREV_TIME = -2;
const int PathConstraintPositionTimeline::PREV_VALUE = -1;
const int PathConstraintPositionTimeline::VALUE = 1;
PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount),
_pathConstraintIndex(0)
{
_frames.setSize(frameCount * ENTRIES, 0);
PathConstraintPositionTimeline::PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex) : CurveTimeline1(frameCount, bezierCount),
_pathConstraintIndex(pathConstraintIndex) {
PropertyId ids[] = { ((PropertyId)Property_PathConstraintPosition << 32) | pathConstraintIndex };
setPropertyIds(ids, 1);
}
PathConstraintPositionTimeline::~PathConstraintPositionTimeline() {
@ -85,32 +80,10 @@ void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, f
}
}
float position;
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));
float position = getCurveValue(time);
position += (_frames[frame + VALUE] - position) * percent;
}
if (blend == MixBlend_Setup)
constraint._position = constraint._data._position + (position - constraint._data._position) * alpha;
else
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)
PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(int frameCount) : PathConstraintPositionTimeline(
frameCount) {
PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, int pathConstraintIndex) : CurveTimeline1(frameCount, bezierCount), _pathConstraintIndex(pathConstraintIndex) {
PropertyId ids[] = { ((PropertyId)Property_PathConstraintSpacing << 32) | pathConstraintIndex };
setPropertyIds(ids, 1);
}
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;
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));
float spacing = getCurveValue(time);
spacing += (_frames[frame + VALUE] - spacing) * percent;
}
if (blend == MixBlend_Setup)
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;
if (blend == MixBlend_Setup)
constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha;
else
constraint._spacing += (spacing - constraint._spacing) * alpha;
}

View File

@ -43,9 +43,15 @@
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,
@ -55,58 +61,152 @@ void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
SP_UNUSED(pEvents);
SP_UNUSED(direction);
Bone *boneP = skeleton._bones[_boneIndex];
Bone &bone = *boneP;
if (!bone._active) return;
Bone *bone = skeleton._bones[_boneIndex];
if (!bone->_active) return;
if (time < _frames[0]) {
switch (blend) {
case MixBlend_Setup:
bone._shearX = bone._data._shearX;
bone._shearY = bone._data._shearY;
return;
case MixBlend_First:
bone._shearX += (bone._data._shearX - bone._shearX) * alpha;
bone._shearY += (bone._data._shearY - bone._shearY) * alpha;
default: {}
}
return;
}
if (time < _frames[0]) {
switch (blend) {
case MixBlend_Setup:
bone->_shearX = bone->_data._shearX;
bone->_shearY = bone->_data._shearY;
return;
case MixBlend_First:
bone->_shearX += (bone->_data._shearX - bone->_shearX) * alpha;
bone->_shearY += (bone->_data._shearY - bone->_shearY) * alpha;
default: {}
}
return;
}
float x, y;
if (time >= _frames[_frames.size() - ENTRIES]) {
// Time is after last frame.
x = _frames[_frames.size() + PREV_X];
y = _frames[_frames.size() + PREV_Y];
} else {
// Interpolate between the previous frame and the current frame.
int frame = Animation::binarySearch(_frames, time, ENTRIES);
x = _frames[frame + PREV_X];
y = _frames[frame + PREV_Y];
float frameTime = _frames[frame];
float percent = getCurvePercent(frame / ENTRIES - 1,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
float x, y;
int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES);
int curveType = (int)_curves[i / CurveTimeline2::ENTRIES];
switch (curveType) {
case CurveTimeline2::LINEAR: {
float before = _frames[i];
x = _frames[i + CurveTimeline2::VALUE1];
y = _frames[i + CurveTimeline2::VALUE2];
float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before);
x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t;
y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t;
break;
}
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;
y = y + (_frames[frame + Y] - y) * percent;
}
switch (blend) {
case MixBlend_Setup:
bone._shearX = bone._data._shearX + x * alpha;
bone._shearY = bone._data._shearY + y * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bone._shearX += (bone._data._shearX + x - bone._shearX) * alpha;
bone._shearY += (bone._data._shearY + y - bone._shearY) * alpha;
break;
case MixBlend_Add:
bone._shearX += x * alpha;
bone._shearY += y * alpha;
}
switch (blend) {
case MixBlend_Setup:
bone->_shearX = bone->_data._shearX + x * alpha;
bone->_shearY = bone->_data._shearY + y * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bone->_shearX += (bone->_data._shearX + x - bone->_shearX) * alpha;
bone->_shearY += (bone->_data._shearY + y - bone->_shearY) * alpha;
break;
case MixBlend_Add:
bone->_shearX += x * alpha;
bone->_shearY += y * alpha;
}
}
int ShearTimeline::getPropertyId() {
return ((int) TimelineType_Shear << 24) + _boneIndex;
RTTI_IMPL(ShearXTimeline, CurveTimeline1)
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)
const int TransformConstraintTimeline::ENTRIES = 5;
const int TransformConstraintTimeline::PREV_TIME = -5;
const int TransformConstraintTimeline::PREV_ROTATE = -4;
const int TransformConstraintTimeline::PREV_TRANSLATE = -3;
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);
TransformConstraintTimeline::TransformConstraintTimeline(size_t frameCount, size_t bezierCount, int transformConstraintIndex) : CurveTimeline(frameCount, TransformConstraintTimeline::ENTRIES, bezierCount),
_transformConstraintIndex(transformConstraintIndex) {
PropertyId ids[] = { ((PropertyId)Property_TransformConstraint << 32) | transformConstraintIndex };
setPropertyIds(ids, 1);
}
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;
if (!constraint.isActive()) return;
TransformConstraintData &data = constraint._data;
if (time < _frames[0]) {
switch (blend) {
case MixBlend_Setup:
constraint._rotateMix = constraint._data._rotateMix;
constraint._translateMix = constraint._data._translateMix;
constraint._scaleMix = constraint._data._scaleMix;
constraint._shearMix = constraint._data._shearMix;
constraint._mixRotate = data._mixRotate;
constraint._mixX = data._mixX;
constraint._mixY = data._mixY;
constraint._mixScaleX = data._mixScaleX;
constraint._mixScaleY = data._mixScaleY;
constraint._mixShearY = data._mixShearY;
return;
case MixBlend_First:
constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha;
constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha;
constraint._scaleMix += (constraint._data._scaleMix - constraint._scaleMix) * alpha;
constraint._shearMix += (constraint._data._shearMix - constraint._shearMix) * alpha;
constraint._mixRotate += (data._mixRotate - constraint._mixRotate) * alpha;
constraint._mixX += (data._mixX - constraint._mixX) * alpha;
constraint._mixY += (data._mixY - constraint._mixY) * alpha;
constraint._mixScaleX += (data._mixScaleX - constraint._mixScaleX) * alpha;
constraint._mixScaleY += (data._mixScaleY - constraint._mixScaleY) * alpha;
constraint._mixShearY += (data._mixShearY - constraint._mixShearY) * alpha;
return;
default:
return;
}
}
float rotate, translate, scale, shear;
if (time >= _frames[_frames.size() - ENTRIES]) {
// Time is after last frame.
size_t i = _frames.size();
rotate = _frames[i + PREV_ROTATE];
translate = _frames[i + PREV_TRANSLATE];
scale = _frames[i + PREV_SCALE];
shear = _frames[i + PREV_SHEAR];
} else {
// Interpolate between the previous frame and the current frame.
int frame = Animation::binarySearch(_frames, time, ENTRIES);
rotate = _frames[frame + PREV_ROTATE];
translate = _frames[frame + PREV_TRANSLATE];
scale = _frames[frame + PREV_SCALE];
shear = _frames[frame + PREV_SHEAR];
float frameTime = _frames[frame];
float percent = getCurvePercent(frame / ENTRIES - 1,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
float rotate, x, y, scaleX, scaleY, shearY;
int i = Animation::search(_frames, time, TransformConstraintTimeline::ENTRIES);
int curveType = (int)_curves[i / TransformConstraintTimeline::ENTRIES];
switch (curveType) {
case TransformConstraintTimeline::LINEAR: {
float before = _frames[i];
rotate = _frames[i + ROTATE];
x = _frames[i + X];
y = _frames[i + Y];
scaleX = _frames[i + SCALEX];
scaleY = _frames[i + SCALEY];
shearY = _frames[i + SHEARY];
float t = (time - before) / (_frames[i + ENTRIES] - before);
rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t;
x += (_frames[i + ENTRIES + X] - x) * t;
y += (_frames[i + ENTRIES + Y] - y) * t;
scaleX += (_frames[i + ENTRIES + SCALEX] - scaleX) * t;
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;
translate += (_frames[frame + TRANSLATE] - translate) * percent;
scale += (_frames[frame + SCALE] - scale) * percent;
shear += (_frames[frame + SHEAR] - shear) * percent;
}
if (blend == MixBlend_Setup) {
TransformConstraintData &data = constraint._data;
constraint._rotateMix = data._rotateMix + (rotate - data._rotateMix) * alpha;
constraint._translateMix = data._translateMix + (translate - data._translateMix) * alpha;
constraint._scaleMix = data._scaleMix + (scale - data._scaleMix) * alpha;
constraint._shearMix = data._shearMix + (shear - data._shearMix) * alpha;
} else {
constraint._rotateMix += (rotate - constraint._rotateMix) * alpha;
constraint._translateMix += (translate - constraint._translateMix) * alpha;
constraint._scaleMix += (scale - constraint._scaleMix) * alpha;
constraint._shearMix += (shear - constraint._shearMix) * alpha;
}
if (blend == MixBlend_Setup) {
constraint._mixRotate = data._mixRotate + (rotate - data._mixRotate) * alpha;
constraint._mixX = data._mixX + (x - data._mixX) * alpha;
constraint._mixY = data._mixY + (y - data._mixY) * alpha;
constraint._mixScaleX = data._mixScaleX + (scaleX - data._mixScaleX) * alpha;
constraint._mixScaleY = data._mixScaleY + (scaleY - data._mixScaleY) * alpha;
constraint._mixShearY = data._mixShearY + (shearY - data._mixShearY) * alpha;
} else {
constraint._mixRotate += (rotate - constraint._mixRotate) * alpha;
constraint._mixX += (x - constraint._mixX) * alpha;
constraint._mixY += (y - constraint._mixY) * alpha;
constraint._mixScaleX += (scaleX - constraint._mixScaleX) * alpha;
constraint._mixScaleY += (scaleY - constraint._mixScaleY) * alpha;
constraint._mixShearY += (shearY - constraint._mixShearY) * alpha;
}
}
int TransformConstraintTimeline::getPropertyId() {
return ((int) TimelineType_TransformConstraint << 24) + _transformConstraintIndex;
}
void TransformConstraintTimeline::setFrame(size_t frameIndex, float time, float rotateMix, float translateMix, float scaleMix,
float shearMix
) {
void TransformConstraintTimeline::setFrame(size_t frameIndex, float time, float mixRotate, float mixX, float mixY, float mixScaleX, float mixScaleY, float mixShearY) {
frameIndex *= ENTRIES;
_frames[frameIndex] = time;
_frames[frameIndex + ROTATE] = rotateMix;
_frames[frameIndex + TRANSLATE] = translateMix;
_frames[frameIndex + SCALE] = scaleMix;
_frames[frameIndex + SHEAR] = shearMix;
_frames[frameIndex + ROTATE] = mixRotate;
_frames[frameIndex + X] = mixX;
_frames[frameIndex + Y] = mixY;
_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}. */
export class RGBTimeline extends CurveTimeline implements SlotTimeline {
static ENTRIES = 5;
static ENTRIES = 4;
static R = 1; static G = 2; static B = 3;
@ -1264,7 +1264,7 @@ module spine {
let light = slot.color, dark = slot.darkColor;
if (alpha == 1) {
slot.color.set(r, g, b, a);
light.set(r, g, b, a);
dark.r = r2;
dark.g = g2;
dark.b = b2;