Timelines are done.

This commit is contained in:
Stephen Gowen 2017-11-26 11:46:06 -05:00
parent 8b53400425
commit 3038a90cc5
30 changed files with 1074 additions and 835 deletions

View File

@ -57,6 +57,9 @@ namespace Spine
friend class Skeleton;
friend class RegionAttachment;
friend class PointAttachment;
friend class ScaleTimeline;
friend class ShearTimeline;
friend class TranslateTimeline;
public:
static void setYDown(bool inValue);

View File

@ -40,6 +40,9 @@ namespace Spine
class BoneData
{
friend class RotateTimeline;
friend class ScaleTimeline;
friend class ShearTimeline;
friend class TranslateTimeline;
public:
BoneData(int index, std::string name, BoneData* parent = NULL);

View File

@ -39,56 +39,25 @@ namespace Spine
{
RTTI_DECL;
public:
EventTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
virtual int getPropertyId();
// internal float[] frames;
// private Event[] events;
//
// public float[] Frames { return frames; } set { frames = inValue; } // time, ...
// public Event[] Events { return events; } set { events = inValue; }
// public int FrameCount { return frames.Length; }
//
//
// public EventTimeline (int frameCount) {
// frames = new float[frameCount];
// events = new Event[frameCount];
// }
//
// /// Sets the time and value of the specified keyframe.
// public void setFrame (int frameIndex, Event e) {
// frames[frameIndex] = e.Time;
// events[frameIndex] = e;
// }
//
// /// Fires events for frames &gt; lastTime and &lt;= time.
// public void Apply (Skeleton skeleton, float lastTime, float time, Vector<Event> firedEvents, float alpha, MixPose pose, MixDirection direction) {
// if (firedEvents == NULL) return;
// float[] frames = _frames;
// int frameCount = frames.Length;
//
// if (lastTime > time) { // Fire events after last time for looped animations.
// Apply(skeleton, lastTime, int.MaxValue, firedEvents, alpha, pose, direction);
// lastTime = -1f;
// } else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame.
// return;
// if (time < frames[0]) return; // Time is before first frame.
//
// int frame;
// if (lastTime < frames[0])
// frame = 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--;
// }
// }
// for (; frame < frameCount && time >= frames[frame]; frame++)
// firedEvents.push_back(events[frame]);
// }
/// Sets the time and value of the specified keyframe.
void setFrame(int frameIndex, Event* e);
Vector<float> getFrames();
void setFrames(Vector<float>& inValue);
Vector<Event*>& getEvents();
void setEvents(Vector<Event*>& inValue);
int getFrameCount();
private:
Vector<float> _frames;
Vector<Event*> _events;
};
}

View File

@ -44,6 +44,7 @@ namespace Spine
class IkConstraint : public Constraint
{
friend class Skeleton;
friend class IkConstraintTimeline;
RTTI_DECL;

View File

@ -43,6 +43,7 @@ namespace Spine
{
friend class IkConstraint;
friend class Skeleton;
friend class IkConstraintTimeline;
public:
IkConstraintData(std::string name);

View File

@ -48,69 +48,15 @@ namespace Spine
virtual int getPropertyId();
/// Sets the time, mix and bend direction of the specified keyframe.
void setFrame (int frameIndex, float time, float mix, int bendDirection);
private:
static const int PREV_TIME, PREV_MIX, PREV_BEND_DIRECTION;
static const int MIX, BEND_DIRECTION;
Vector<float> _frames;
int _ikConstraintIndex;
// public int IkConstraintIndex { return ikConstraintIndex; } set { ikConstraintIndex = inValue; }
// public float[] Frames { return frames; } set { frames = inValue; } // time, mix, bendDirection, ...
//
//
//
// /// Sets the time, mix and bend direction of the specified keyframe.
// public void setFrame (int frameIndex, float time, float mix, int bendDirection) {
// frameIndex *= ENTRIES;
// frames[frameIndex] = time;
// frames[frameIndex + MIX] = mix;
// frames[frameIndex + BEND_DIRECTION] = bendDirection;
// }
//
// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector<Event> firedEvents, float alpha, MixPose pose, MixDirection direction) {
// IkConstraint constraint = skeleton.ikConstraints.Items[ikConstraintIndex];
// float[] frames = _frames;
// if (time < frames[0]) {
// switch (pose) {
// case MixPose_Setup:
// constraint.mix = constraint.data.mix;
// constraint.bendDirection = constraint.data.bendDirection;
// return;
// case MixPose_Current:
// constraint.mix += (constraint.data.mix - constraint.mix) * alpha;
// constraint.bendDirection = constraint.data.bendDirection;
// return;
// }
// return;
// }
//
// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame.
// if (pose == MixPose_Setup) {
// constraint.mix = constraint.data.mix + (frames[frames.Length + PREV_MIX] - constraint.data.mix) * alpha;
// constraint.bendDirection = direction == MixDirection_Out ? constraint.data.bendDirection
// : (int)frames[frames.Length + PREV_BEND_DIRECTION];
// } else {
// constraint.mix += (frames[frames.Length + PREV_MIX] - constraint.mix) * alpha;
// if (direction == MixDirection_In) constraint.bendDirection = (int)frames[frames.Length + PREV_BEND_DIRECTION];
// }
// return;
// }
//
// // Interpolate between the previous frame and the current frame.
// int frame = Animation::binarySearch(frames, time, ENTRIES);
// float mix = frames[frame + PREV_MIX];
// float frameTime = frames[frame];
// float percent = GetCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
//
// if (pose == MixPose_Setup) {
// constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha;
// constraint.bendDirection = direction == MixDirection_Out ? constraint.data.bendDirection : (int)frames[frame + PREV_BEND_DIRECTION];
// } else {
// constraint.mix += (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha;
// if (direction == MixDirection_In) constraint.bendDirection = (int)frames[frame + PREV_BEND_DIRECTION];
// }
// }
};
}

View File

@ -46,6 +46,9 @@ namespace Spine
class PathConstraint : public Constraint
{
friend class Skeleton;
friend class PathConstraintMixTimeline;
friend class PathConstraintPositionTimeline;
friend class PathConstraintSpacingTimeline;
RTTI_DECL;

View File

@ -47,6 +47,9 @@ namespace Spine
{
friend class PathConstraint;
friend class Skeleton;
friend class PathConstraintMixTimeline;
friend class PathConstraintPositionTimeline;
friend class PathConstraintSpacingTimeline;
public:
PathConstraintData(std::string name);

View File

@ -40,78 +40,23 @@ namespace Spine
RTTI_DECL;
public:
static const int ENTRIES;
PathConstraintMixTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
virtual int getPropertyId();
private:
static const int PREV_TIME, PREV_ROTATE, PREV_TRANSLATE;
static const int ROTATE, TRANSLATE;
Vector<float> _frames;
int _pathConstraintIndex;
// public const int ENTRIES = 3;
// private const int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1;
// private const int ROTATE = 1, TRANSLATE = 2;
//
// internal float[] frames;
//
// public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; }
// public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, ...
//
//
// public PathConstraintMixTimeline (int frameCount)
// : base(frameCount) {
// frames = new float[frameCount * ENTRIES];
// }
//
// /// Sets the time and mixes of the specified keyframe.
// public void setFrame (int frameIndex, float time, float rotateMix, float translateMix) {
// frameIndex *= ENTRIES;
// frames[frameIndex] = time;
// frames[frameIndex + ROTATE] = rotateMix;
// frames[frameIndex + TRANSLATE] = translateMix;
// }
//
// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector<Event> firedEvents, float alpha, MixPose pose, MixDirection direction) {
// PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex];
// float[] frames = _frames;
// if (time < frames[0]) {
// switch (pose) {
// case MixPose_Setup:
// constraint.rotateMix = constraint.data.rotateMix;
// constraint.translateMix = constraint.data.translateMix;
// return;
// case MixPose_Current:
// constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha;
// constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha;
// return;
// }
// return;
// }
//
// float rotate, translate;
// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame.
// rotate = frames[frames.Length + PREV_ROTATE];
// translate = frames[frames.Length + 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));
//
// rotate += (frames[frame + ROTATE] - rotate) * percent;
// translate += (frames[frame + TRANSLATE] - translate) * percent;
// }
//
// if (pose == MixPose_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;
// }
// }
/// Sets the time and mixes of the specified keyframe.
void setFrame(int frameIndex, float time, float rotateMix, float translateMix);
};
}

View File

@ -48,61 +48,15 @@ namespace Spine
virtual int getPropertyId();
/// Sets the time and value of the specified keyframe.
void setFrame(int frameIndex, float time, float value);
protected:
static const int PREV_TIME, PREV_VALUE;
static const int VALUE;
Vector<float> _frames;
int _pathConstraintIndex;
//
//
//
//
// public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; }
// public float[] Frames { return frames; } set { frames = inValue; } // time, position, ...
//
// /// Sets the time and value of the specified keyframe.
// public void setFrame (int frameIndex, float time, float value) {
// frameIndex *= ENTRIES;
// frames[frameIndex] = time;
// frames[frameIndex + VALUE] = inValue;
// }
//
// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector<Event> firedEvents, float alpha, MixPose pose, MixDirection direction) {
// PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex];
// float[] frames = _frames;
// if (time < frames[0]) {
// switch (pose) {
// case MixPose_Setup:
// constraint.position = constraint.data.position;
// return;
// case MixPose_Current:
// constraint.position += (constraint.data.position - constraint.position) * alpha;
// return;
// }
// return;
// }
//
// float position;
// if (time >= frames[frames.Length - ENTRIES]) // Time is after last frame.
// position = frames[frames.Length + 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 (pose == MixPose_Setup)
// constraint.position = constraint.data.position + (position - constraint.data.position) * alpha;
// else
// constraint.position += (position - constraint.position) * alpha;
// }
};
}

View File

@ -45,41 +45,6 @@ namespace Spine
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
virtual int getPropertyId();
// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector<Event> firedEvents, float alpha, MixPose pose, MixDirection direction) {
// PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex];
// float[] frames = _frames;
// if (time < frames[0]) {
// switch (pose) {
// case MixPose_Setup:
// constraint.spacing = constraint.data.spacing;
// return;
// case MixPose_Current:
// constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha;
// return;
// }
// return;
// }
//
// float spacing;
// if (time >= frames[frames.Length - ENTRIES]) // Time is after last frame.
// spacing = frames[frames.Length + 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 (pose == MixPose_Setup)
// constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha;
// else
// constraint.spacing += (spacing - constraint.spacing) * alpha;
// }
};
}

View File

@ -39,72 +39,12 @@ namespace Spine
{
RTTI_DECL;
public:
ScaleTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
virtual int getPropertyId();
// public ScaleTimeline (int frameCount)
// : base(frameCount) {
// }
//
// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector<Event> firedEvents, float alpha, MixPose pose, MixDirection direction) {
// Bone bone = skeleton.bones.Items[boneIndex];
//
// float[] frames = _frames;
// if (time < frames[0]) {
// switch (pose) {
// case MixPose_Setup:
// bone.scaleX = bone.data.scaleX;
// bone.scaleY = bone.data.scaleY;
// return;
// case MixPose_Current:
// bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;
// bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;
// return;
// }
// return;
// }
//
// float x, y;
// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame.
// x = frames[frames.Length + PREV_X] * bone.data.scaleX;
// y = frames[frames.Length + PREV_Y] * bone.data.scaleY;
// } 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));
//
// x = (x + (frames[frame + X] - x) * percent) * bone.data.scaleX;
// y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY;
// }
// if (alpha == 1) {
// bone.scaleX = x;
// bone.scaleY = y;
// } else {
// float bx, by;
// if (pose == MixPose_Setup) {
// bx = bone.data.scaleX;
// by = bone.data.scaleY;
// } else {
// bx = bone.scaleX;
// by = bone.scaleY;
// }
// // Mixing out uses sign of setup or current pose, else use sign of key.
// if (direction == MixDirection_Out) {
// x = (x >= 0 ? x : -x) * (bx >= 0 ? 1 : -1);
// y = (y >= 0 ? y : -y) * (by >= 0 ? 1 : -1);
// } else {
// bx = (bx >= 0 ? bx : -bx) * (x >= 0 ? 1 : -1);
// by = (by >= 0 ? by : -by) * (y >= 0 ? 1 : -1);
// }
// bone.scaleX = bx + (x - bx) * alpha;
// bone.scaleY = by + (y - by) * alpha;
// }
// }
};
}

View File

@ -40,55 +40,11 @@ namespace Spine
RTTI_DECL;
public:
ShearTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
virtual int getPropertyId();
// public ShearTimeline (int frameCount)
// : base(frameCount) {
// }
//
// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector<Event> firedEvents, float alpha, MixPose pose, MixDirection direction) {
// Bone bone = skeleton.bones.Items[boneIndex];
// float[] frames = _frames;
// if (time < frames[0]) {
// switch (pose) {
// case MixPose_Setup:
// bone.shearX = bone.data.shearX;
// bone.shearY = bone.data.shearY;
// return;
// case MixPose_Current:
// bone.shearX += (bone.data.shearX - bone.shearX) * alpha;
// bone.shearY += (bone.data.shearY - bone.shearY) * alpha;
// return;
// }
// return;
// }
//
// float x, y;
// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame.
// x = frames[frames.Length + PREV_X];
// y = frames[frames.Length + 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));
//
// x = x + (frames[frame + X] - x) * percent;
// y = y + (frames[frame + Y] - y) * percent;
// }
// if (pose == MixPose_Setup) {
// bone.shearX = bone.data.shearX + x * alpha;
// bone.shearY = bone.data.shearY + y * alpha;
// } else {
// bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha;
// bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha;
// }
// }
};
}

View File

@ -44,6 +44,7 @@ namespace Spine
class TransformConstraint : public Constraint
{
friend class Skeleton;
friend class TransformConstraintTimeline;
RTTI_DECL;

View File

@ -43,6 +43,7 @@ namespace Spine
{
friend class TransformConstraint;
friend class Skeleton;
friend class TransformConstraintTimeline;
public:
TransformConstraintData(std::string name);

View File

@ -42,94 +42,20 @@ namespace Spine
public:
static const int ENTRIES;
TransformConstraintTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
virtual int getPropertyId();
void setFrame(int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix);
private:
static const int PREV_TIME, PREV_ROTATE, PREV_TRANSLATE, PREV_SCALE, PREV_SHEAR;
static const int ROTATE, TRANSLATE, SCALE, SHEAR;
Vector<float> _frames;
int _transformConstraintIndex;
// internal float[] frames;
//
// public int TransformConstraintIndex { return transformConstraintIndex; } set { transformConstraintIndex = inValue; }
// public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, scale mix, shear mix, ...
//
//
// public TransformConstraintTimeline (int frameCount)
// : base(frameCount) {
// frames = new float[frameCount * ENTRIES];
// }
//
// public void setFrame (int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) {
// frameIndex *= ENTRIES;
// frames[frameIndex] = time;
// frames[frameIndex + ROTATE] = rotateMix;
// frames[frameIndex + TRANSLATE] = translateMix;
// frames[frameIndex + SCALE] = scaleMix;
// frames[frameIndex + SHEAR] = shearMix;
// }
//
// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector<Event> firedEvents, float alpha, MixPose pose, MixDirection direction) {
// TransformConstraint constraint = skeleton.transformConstraints.Items[transformConstraintIndex];
// float[] frames = _frames;
// if (time < frames[0]) {
// var data = constraint.data;
// switch (pose) {
// case MixPose_Setup:
// constraint.rotateMix = data.rotateMix;
// constraint.translateMix = data.translateMix;
// constraint.scaleMix = data.scaleMix;
// constraint.shearMix = data.shearMix;
// return;
// case MixPose_Current:
// constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha;
// constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha;
// constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha;
// constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha;
// return;
// }
// return;
// }
//
// float rotate, translate, scale, shear;
// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame.
// int i = frames.Length;
// 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));
//
// 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 (pose == MixPose_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;
// }
// }
};
}

View File

@ -43,89 +43,23 @@ namespace Spine
RTTI_DECL;
public:
static const int ENTRIES;
TranslateTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
virtual int getPropertyId();
protected:
int _boneIndex;
/// Sets the time and value of the specified keyframe.
void setFrame(int frameIndex, float time, float x, float y);
// public const int ENTRIES = 3;
// protected const int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1;
// protected const int X = 1, Y = 2;
//
// internal float[] frames;
//
// public int getBoneIndex { return boneIndex; } set { boneIndex = inValue; }
// public Vector<float> getFrames { return frames; } set { frames = inValue; } // time, value, value, ...
//
//
// public TranslateTimeline(int frameCount) : CurveTimeline(frameCount)
// {
// frames = new float[frameCount * ENTRIES];
// }
//
// /// Sets the time and value of the specified keyframe.
// public void setFrame(int frameIndex, float time, float x, float y)
// {
// frameIndex *= ENTRIES;
// frames[frameIndex] = time;
// frames[frameIndex + X] = x;
// frames[frameIndex + Y] = y;
// }
//
// override public void apply(Skeleton skeleton, float lastTime, float time, Vector<Event> firedEvents, float alpha, MixPose pose, MixDirection direction)
// {
// Bone bone = skeleton.bones.Items[boneIndex];
//
// float[] frames = _frames;
// if (time < frames[0])
// {
// switch (pose)
// {
// case MixPose_Setup:
// bone.x = bone.data.x;
// bone.y = bone.data.y;
// return;
// case MixPose_Current:
// bone.x += (bone.data.x - bone.x) * alpha;
// bone.y += (bone.data.y - bone.y) * alpha;
// return;
// }
// return;
// }
//
// float x, y;
// if (time >= frames[frames.Length - ENTRIES])
// {
// // Time is after last frame.
// x = frames[frames.Length + PREV_X];
// y = frames[frames.Length + 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));
//
// x += (frames[frame + X] - x) * percent;
// y += (frames[frame + Y] - y) * percent;
// }
//
// if (pose == MixPose_Setup)
// {
// bone.x = bone.data.x + x * alpha;
// bone.y = bone.data.y + y * alpha;
// }
// else
// {
// bone.x += (bone.data.x + x - bone.x) * alpha;
// bone.y += (bone.data.y + y - bone.y) * alpha;
// }
// }
protected:
static const int PREV_TIME, PREV_X, PREV_Y;
static const int X, Y;
Vector<float> _frames;
int _boneIndex;
};
}

View File

@ -40,146 +40,27 @@ namespace Spine
RTTI_DECL;
public:
static const int ENTRIES;
TwoColorTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
virtual int getPropertyId();
private:
int _slotIndex;
/// Sets the time and value of the specified keyframe.
void setFrame(int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2);
// public const int ENTRIES = 8;
// protected const int PREV_TIME = -8, PREV_R = -7, PREV_G = -6, PREV_B = -5, PREV_A = -4;
// protected const int PREV_R2 = -3, PREV_G2 = -2, PREV_B2 = -1;
// protected const int R = 1, G = 2, B = 3, A = 4, R2 = 5, G2 = 6, B2 = 7;
//
// internal float[] frames; // time, r, g, b, a, r2, g2, b2, ...
// public float[] Frames { return frames; }
//
// public int SlotIndex {
// get { return slotIndex; }
// set {
// if (value < 0) throw new ArgumentOutOfRangeException("index must be >= 0.");
// slotIndex = inValue;
// }
// }
//
//
// public TwoColorTimeline (int frameCount) :
// base(frameCount) {
// frames = new float[frameCount * ENTRIES];
// }
//
// /// Sets the time and value of the specified keyframe.
// public void setFrame (int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) {
// frameIndex *= ENTRIES;
// frames[frameIndex] = time;
// frames[frameIndex + R] = r;
// frames[frameIndex + G] = g;
// frames[frameIndex + B] = b;
// frames[frameIndex + A] = a;
// frames[frameIndex + R2] = r2;
// frames[frameIndex + G2] = g2;
// frames[frameIndex + B2] = b2;
// }
//
// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector<Event> firedEvents, float alpha, MixPose pose, MixDirection direction) {
// Slot slot = skeleton.slots.Items[slotIndex];
// float[] frames = _frames;
// if (time < frames[0]) { // Time is before first frame.
// var slotData = slot.data;
// switch (pose) {
// case MixPose_Setup:
// // slot.color.set(slot.data.color);
// // slot.darkColor.set(slot.data.darkColor);
// slot.r = slotData.r;
// slot.g = slotData.g;
// slot.b = slotData.b;
// slot.a = slotData.a;
// slot.r2 = slotData.r2;
// slot.g2 = slotData.g2;
// slot.b2 = slotData.b2;
// return;
// case MixPose_Current:
// slot.r += (slot.r - slotData.r) * alpha;
// slot.g += (slot.g - slotData.g) * alpha;
// slot.b += (slot.b - slotData.b) * alpha;
// slot.a += (slot.a - slotData.a) * alpha;
// slot.r2 += (slot.r2 - slotData.r2) * alpha;
// slot.g2 += (slot.g2 - slotData.g2) * alpha;
// slot.b2 += (slot.b2 - slotData.b2) * alpha;
// return;
// }
// return;
// }
//
// float r, g, b, a, r2, g2, b2;
// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame.
// int i = frames.Length;
// r = frames[i + PREV_R];
// g = frames[i + PREV_G];
// b = frames[i + PREV_B];
// a = frames[i + PREV_A];
// r2 = frames[i + PREV_R2];
// g2 = frames[i + PREV_G2];
// b2 = frames[i + PREV_B2];
// } else {
// // Interpolate between the previous frame and the current frame.
// int frame = 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];
// r2 = frames[frame + PREV_R2];
// g2 = frames[frame + PREV_G2];
// b2 = frames[frame + PREV_B2];
// float frameTime = frames[frame];
// float percent = GetCurvePercent(frame / ENTRIES - 1,
// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
//
// r += (frames[frame + R] - r) * percent;
// g += (frames[frame + G] - g) * percent;
// b += (frames[frame + B] - b) * percent;
// a += (frames[frame + A] - a) * percent;
// r2 += (frames[frame + R2] - r2) * percent;
// g2 += (frames[frame + G2] - g2) * percent;
// b2 += (frames[frame + B2] - b2) * percent;
// }
// if (alpha == 1) {
// slot.r = r;
// slot.g = g;
// slot.b = b;
// slot.a = a;
// slot.r2 = r2;
// slot.g2 = g2;
// slot.b2 = b2;
// } else {
// float br, bg, bb, ba, br2, bg2, bb2;
// if (pose == MixPose_Setup) {
// br = slot.data.r;
// bg = slot.data.g;
// bb = slot.data.b;
// ba = slot.data.a;
// br2 = slot.data.r2;
// bg2 = slot.data.g2;
// bb2 = slot.data.b2;
// } else {
// br = slot.r;
// bg = slot.g;
// bb = slot.b;
// ba = slot.a;
// br2 = slot.r2;
// bg2 = slot.g2;
// bb2 = slot.b2;
// }
// slot.r = br + ((r - br) * alpha);
// slot.g = bg + ((g - bg) * alpha);
// slot.b = bb + ((b - bb) * alpha);
// slot.a = ba + ((a - ba) * alpha);
// slot.r2 = br2 + ((r2 - br2) * alpha);
// slot.g2 = bg2 + ((g2 - bg2) * alpha);
// slot.b2 = bb2 + ((b2 - bb2) * alpha);
// }
// }
int getSlotIndex();
void setSlotIndex(int inValue);
private:
static const int PREV_TIME, PREV_R, PREV_G, PREV_B, PREV_A;
static const int PREV_R2, PREV_G2, PREV_B2;
static const int R, G, B, A, R2, G2, B2;
Vector<float> _frames; // time, r, g, b, a, r2, g2, b2, ...
int _slotIndex;
};
}

View File

@ -48,18 +48,53 @@ namespace Spine
// Empty
}
Vector(const Vector& inArray) : _size(inArray._size), _capacity(inArray._capacity), _buffer(NULL)
Vector(const Vector& inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL)
{
if (_capacity > 0)
{
_buffer = allocate(_capacity);
for (size_t i = 0; i < _size; ++i)
{
construct(_buffer + i, inArray._buffer[i]);
construct(_buffer + i, inVector._buffer[i]);
}
}
}
Vector(Vector& inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL)
{
if (_capacity > 0)
{
_buffer = allocate(_capacity);
for (size_t i = 0; i < _size; ++i)
{
construct(_buffer + i, inVector._buffer[i]);
}
}
}
Vector& operator=(Vector& inVector)
{
if (this != &inVector)
{
clear();
deallocate(_buffer);
_size = inVector._size;
_capacity = inVector._capacity;
if (_capacity > 0)
{
_buffer = allocate(_capacity);
for (size_t i = 0; i < _size; ++i)
{
construct(_buffer + i, inVector._buffer[i]);
}
}
}
return *this;
}
~Vector()
{
clear();
@ -179,6 +214,29 @@ namespace Spine
return &_buffer[_size];
}
friend bool operator==(Vector<T>& lhs, Vector<T>& rhs)
{
if (lhs.size() != rhs.size())
{
return false;
}
for (int i = 0, n = static_cast<int>(lhs.size()); i < n; ++i)
{
if (lhs[i] != rhs[i])
{
return false;
}
}
return true;
}
friend bool operator!=(Vector<T>& lhs, Vector<T>& rhs)
{
return !(lhs == rhs);
}
private:
size_t _size;
size_t _capacity;

View File

@ -37,18 +37,83 @@
#include <spine/TimelineType.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#include <spine/Event.h>
namespace Spine
{
RTTI_IMPL(EventTimeline, Timeline);
EventTimeline::EventTimeline(int frameCount) : Timeline()
{
_frames.reserve(frameCount);
_events.reserve(frameCount);
}
void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
// TODO
if (events.size() == 0)
{
return;
}
int frameCount = static_cast<int>(_frames.size());
if (lastTime > time)
{
// Fire events after last time for looped animations.
apply(skeleton, lastTime, std::numeric_limits<int>::max(), events, alpha, pose, direction);
lastTime = -1.0f;
}
else if (lastTime >= _frames[frameCount - 1]) // Last time is after last frame.
{
return;
}
if (time < _frames[0])
{
return; // Time is before first frame.
}
int frame;
if (lastTime < _frames[0])
{
frame = 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--;
}
}
for (; frame < frameCount && time >= _frames[frame]; ++frame)
{
events.push_back(_events[frame]);
}
}
int EventTimeline::getPropertyId()
{
return ((int)TimelineType_Event << 24);
}
void EventTimeline::setFrame(int frameIndex, Event* e)
{
_frames[frameIndex] = e->getTime();
_events[frameIndex] = e;
}
Vector<float> EventTimeline::getFrames() { return _frames; }
void EventTimeline::setFrames(Vector<float>& inValue) { _frames = inValue; } // time, ...
Vector<Event*>& EventTimeline::getEvents() { return _events; }
void EventTimeline::setEvents(Vector<Event*>& inValue) { _events = inValue; }
int EventTimeline::getFrameCount() { return static_cast<int>(_frames.size()); }
}

View File

@ -37,6 +37,8 @@
#include <spine/TimelineType.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#include <spine/IkConstraint.h>
#include <spine/IkConstraintData.h>
namespace Spine
{
@ -56,11 +58,77 @@ namespace Spine
void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
// TODO
IkConstraint* constraintP = skeleton._ikConstraints[_ikConstraintIndex];
IkConstraint& constraint = *constraintP;
if (time < _frames[0])
{
switch (pose)
{
case MixPose_Setup:
constraint._mix = constraint._data._mix;
constraint._bendDirection = constraint._data._bendDirection;
return;
case MixPose_Current:
constraint._mix += (constraint._data._mix - constraint._mix) * alpha;
constraint._bendDirection = constraint._data._bendDirection;
return;
case MixPose_CurrentLayered:
default:
return;
}
}
if (time >= _frames[_frames.size() - ENTRIES])
{
// Time is after last frame.
if (pose == MixPose_Setup)
{
constraint._mix = constraint._data._mix + (_frames[_frames.size() + PREV_MIX] - constraint._data._mix) * alpha;
constraint._bendDirection = direction == MixDirection_Out ? constraint._data._bendDirection
: (int)_frames[_frames.size() + PREV_BEND_DIRECTION];
}
else
{
constraint._mix += (_frames[_frames.size() + PREV_MIX] - constraint._mix) * alpha;
if (direction == MixDirection_In)
{
constraint._bendDirection = (int)_frames[_frames.size() + PREV_BEND_DIRECTION];
}
}
return;
}
// Interpolate between the previous frame and the current frame.
int frame = Animation::binarySearch(_frames, time, ENTRIES);
float mix = _frames[frame + PREV_MIX];
float frameTime = _frames[frame];
float percent = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
if (pose == MixPose_Setup)
{
constraint._mix = constraint._data._mix + (mix + (_frames[frame + MIX] - mix) * percent - constraint._data._mix) * alpha;
constraint._bendDirection = direction == MixDirection_Out ? constraint._data._bendDirection : (int)_frames[frame + PREV_BEND_DIRECTION];
}
else
{
constraint._mix += (mix + (_frames[frame + MIX] - mix) * percent - constraint._mix) * alpha;
if (direction == MixDirection_In)
{
constraint._bendDirection = (int)_frames[frame + PREV_BEND_DIRECTION];
}
}
}
int IkConstraintTimeline::getPropertyId()
{
return ((int)TimelineType_IkConstraint << 24) + _ikConstraintIndex;
}
void IkConstraintTimeline::setFrame(int frameIndex, float time, float mix, int bendDirection)
{
frameIndex *= ENTRIES;
_frames[frameIndex] = time;
_frames[frameIndex + MIX] = mix;
_frames[frameIndex + BEND_DIRECTION] = bendDirection;
}
}

View File

@ -37,18 +37,90 @@
#include <spine/TimelineType.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#include <spine/PathConstraint.h>
#include <spine/PathConstraintData.h>
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.reserve(frameCount * ENTRIES);
}
void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
// TODO
PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex];
PathConstraint& constraint = *constraintP;
if (time < _frames[0])
{
switch (pose)
{
case MixPose_Setup:
constraint._rotateMix = constraint._data._rotateMix;
constraint._translateMix = constraint._data._translateMix;
return;
case MixPose_Current:
constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha;
constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha;
return;
case MixPose_CurrentLayered:
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));
rotate += (_frames[frame + ROTATE] - rotate) * percent;
translate += (_frames[frame + TRANSLATE] - translate) * percent;
}
if (pose == MixPose_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;
}
}
int PathConstraintMixTimeline::getPropertyId()
{
return ((int)TimelineType_PathConstraintMix << 24) + _pathConstraintIndex;
}
void PathConstraintMixTimeline::setFrame(int frameIndex, float time, float rotateMix, float translateMix)
{
frameIndex *= ENTRIES;
_frames[frameIndex] = time;
_frames[frameIndex + ROTATE] = rotateMix;
_frames[frameIndex + TRANSLATE] = translateMix;
}
}

View File

@ -37,6 +37,8 @@
#include <spine/TimelineType.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#include <spine/PathConstraint.h>
#include <spine/PathConstraintData.h>
namespace Spine
{
@ -47,18 +49,66 @@ namespace Spine
const int PathConstraintPositionTimeline::PREV_VALUE = -1;
const int PathConstraintPositionTimeline::VALUE = 1;
PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount)
PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount), _pathConstraintIndex(0)
{
_frames.reserve(frameCount * ENTRIES);
}
void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
// TODO
PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex];
PathConstraint& constraint = *constraintP;
if (time < _frames[0])
{
switch (pose)
{
case MixPose_Setup:
constraint._position = constraint._data._position;
return;
case MixPose_Current:
constraint._position += (constraint._data._position - constraint._position) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
}
}
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));
position += (_frames[frame + VALUE] - position) * percent;
}
if (pose == MixPose_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

@ -37,6 +37,8 @@
#include <spine/TimelineType.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#include <spine/PathConstraint.h>
#include <spine/PathConstraintData.h>
namespace Spine
{
@ -49,7 +51,49 @@ namespace Spine
void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
// TODO
PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex];
PathConstraint& constraint = *constraintP;
if (time < _frames[0])
{
switch (pose)
{
case MixPose_Setup:
constraint._spacing = constraint._data._spacing;
return;
case MixPose_Current:
constraint._spacing += (constraint._data._spacing - constraint._spacing) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
}
}
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));
spacing += (_frames[frame + VALUE] - spacing) * percent;
}
if (pose == MixPose_Setup)
{
constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha;
}
else
{
constraint._spacing += (spacing - constraint._spacing) * alpha;
}
}
int PathConstraintSpacingTimeline::getPropertyId()

View File

@ -37,14 +37,94 @@
#include <spine/TimelineType.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#include <spine/Bone.h>
#include <spine/BoneData.h>
namespace Spine
{
RTTI_IMPL(ScaleTimeline, TranslateTimeline);
ScaleTimeline::ScaleTimeline(int frameCount) : TranslateTimeline(frameCount)
{
// Empty
}
void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
// TODO
Bone* boneP = skeleton._bones[_boneIndex];
Bone& bone = *boneP;
if (time < _frames[0])
{
switch (pose)
{
case MixPose_Setup:
bone._scaleX = bone._data._scaleX;
bone._scaleY = bone._data._scaleY;
return;
case MixPose_Current:
bone._scaleX += (bone._data._scaleX - bone._scaleX) * alpha;
bone._scaleY += (bone._data._scaleY - bone._scaleY) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
}
}
float x, y;
if (time >= _frames[_frames.size() - ENTRIES])
{
// Time is after last frame.
x = _frames[_frames.size() + PREV_X] * bone._data._scaleX;
y = _frames[_frames.size() + PREV_Y] * bone._data._scaleY;
}
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));
x = (x + (_frames[frame + X] - x) * percent) * bone._data._scaleX;
y = (y + (_frames[frame + Y] - y) * percent) * bone._data._scaleY;
}
if (alpha == 1)
{
bone._scaleX = x;
bone._scaleY = y;
}
else
{
float bx, by;
if (pose == MixPose_Setup)
{
bx = bone._data._scaleX;
by = bone._data._scaleY;
}
else
{
bx = bone._scaleX;
by = bone._scaleY;
}
// Mixing out uses sign of setup or current pose, else use sign of key.
if (direction == MixDirection_Out)
{
x = (x >= 0 ? x : -x) * (bx >= 0 ? 1 : -1);
y = (y >= 0 ? y : -y) * (by >= 0 ? 1 : -1);
}
else
{
bx = (bx >= 0 ? bx : -bx) * (x >= 0 ? 1 : -1);
by = (by >= 0 ? by : -by) * (y >= 0 ? 1 : -1);
}
bone._scaleX = bx + (x - bx) * alpha;
bone._scaleY = by + (y - by) * alpha;
}
}
int ScaleTimeline::getPropertyId()

View File

@ -37,14 +37,72 @@
#include <spine/TimelineType.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#include <spine/Bone.h>
#include <spine/BoneData.h>
namespace Spine
{
RTTI_IMPL(ShearTimeline, TranslateTimeline);
ShearTimeline::ShearTimeline(int frameCount) : TranslateTimeline(frameCount)
{
// Empty
}
void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
// TODO
Bone* boneP = skeleton._bones[_boneIndex];
Bone& bone = *boneP;
if (time < _frames[0])
{
switch (pose)
{
case MixPose_Setup:
bone._shearX = bone._data._shearX;
bone._shearY = bone._data._shearY;
return;
case MixPose_Current:
bone._shearX += (bone._data._shearX - bone._shearX) * alpha;
bone._shearY += (bone._data._shearY - bone._shearY) * alpha;
return;
case MixPose_CurrentLayered:
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));
x = x + (_frames[frame + X] - x) * percent;
y = y + (_frames[frame + Y] - y) * percent;
}
if (pose == MixPose_Setup)
{
bone._shearX = bone._data._shearX + x * alpha;
bone._shearY = bone._data._shearY + y * alpha;
}
else
{
bone._shearX += (bone._data._shearX + x - bone._shearX) * alpha;
bone._shearY += (bone._data._shearY + y - bone._shearY) * alpha;
}
}
int ShearTimeline::getPropertyId()

View File

@ -56,7 +56,9 @@ namespace Spine
_clippingPolygon.reserve(n);
clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2);
makeClockwise(_clippingPolygon);
_clippingPolygons = _triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon));
Vector< Vector<float>* > clippingPolygons = _triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon));
_clippingPolygons = clippingPolygons;
for (Vector<float>** i = _clippingPolygons.begin(); i != _clippingPolygons.end(); ++i)
{
@ -97,14 +99,13 @@ namespace Spine
Vector<float>& clipOutput = _clipOutput, clippedVertices = _clippedVertices;
Vector<int>& clippedTriangles = _clippedTriangles;
Vector< Vector<float>* >& polygons = _clippingPolygons;
int polygonsCount = _clippingPolygons.size();
int polygonsCount = static_cast<int>(_clippingPolygons.size());
int index = 0;
clippedVertices.clear();
_clippedUVs.clear();
clippedTriangles.clear();
//outer:
for (int i = 0; i < trianglesLength; i += 3)
{
int vertexOffset = triangles[i] << 1;
@ -121,73 +122,72 @@ namespace Spine
for (int p = 0; p < polygonsCount; p++)
{
int s = clippedVertices.size();
// if (clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput))
// {
// int clipOutputLength = clipOutput.Count;
// if (clipOutputLength == 0)
// {
// continue;
// }
// float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
// float d = 1 / (d0 * d2 + d1 * (y1 - y3));
//
// int clipOutputCount = clipOutputLength >> 1;
// float[] clipOutputItems = clipOutput.Items;
// float[] clippedVerticesItems = clippedVertices.Resize(s + clipOutputCount * 2).Items;
// float[] clippedUVsItems = clippedUVs.Resize(s + clipOutputCount * 2).Items;
// for (int ii = 0; ii < clipOutputLength; ii += 2)
// {
// float x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
// clippedVerticesItems[s] = x;
// clippedVerticesItems[s + 1] = y;
// float c0 = x - x3, c1 = y - y3;
// float a = (d0 * c0 + d1 * c1) * d;
// float b = (d4 * c0 + d2 * c1) * d;
// float c = 1 - a - b;
// clippedUVsItems[s] = u1 * a + u2 * b + u3 * c;
// clippedUVsItems[s + 1] = v1 * a + v2 * b + v3 * c;
// s += 2;
// }
//
// s = clippedTriangles.Count;
// int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3 * (clipOutputCount - 2)).Items;
// clipOutputCount--;
// for (int ii = 1; ii < clipOutputCount; ii++)
// {
// clippedTrianglesItems[s] = index;
// clippedTrianglesItems[s + 1] = index + ii;
// clippedTrianglesItems[s + 2] = index + ii + 1;
// s += 3;
// }
// index += clipOutputCount + 1;
// }
// else
// {
// float[] clippedVerticesItems = clippedVertices.Resize(s + 3 * 2).Items;
// float[] clippedUVsItems = clippedUVs.Resize(s + 3 * 2).Items;
// clippedVerticesItems[s] = x1;
// clippedVerticesItems[s + 1] = y1;
// clippedVerticesItems[s + 2] = x2;
// clippedVerticesItems[s + 3] = y2;
// clippedVerticesItems[s + 4] = x3;
// clippedVerticesItems[s + 5] = y3;
//
// clippedUVsItems[s] = u1;
// clippedUVsItems[s + 1] = v1;
// clippedUVsItems[s + 2] = u2;
// clippedUVsItems[s + 3] = v2;
// clippedUVsItems[s + 4] = u3;
// clippedUVsItems[s + 5] = v3;
//
// s = clippedTriangles.Count;
// int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3).Items;
// clippedTrianglesItems[s] = index;
// clippedTrianglesItems[s + 1] = index + 1;
// clippedTrianglesItems[s + 2] = index + 2;
// index += 3;
// break; //continue outer;
// }
int s = static_cast<int>(clippedVertices.size());
if (clip(x1, y1, x2, y2, x3, y3, *polygons[p], clipOutput))
{
int clipOutputLength = static_cast<int>(clipOutput.size());
if (clipOutputLength == 0)
{
continue;
}
float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
float d = 1 / (d0 * d2 + d1 * (y1 - y3));
int clipOutputCount = clipOutputLength >> 1;
clippedVertices.reserve(s + clipOutputCount * 2);
_clippedUVs.reserve(s + clipOutputCount * 2);
for (int ii = 0; ii < clipOutputLength; ii += 2)
{
float x = clipOutput[ii], y = clipOutput[ii + 1];
clippedVertices[s] = x;
clippedVertices[s + 1] = y;
float c0 = x - x3, c1 = y - y3;
float a = (d0 * c0 + d1 * c1) * d;
float b = (d4 * c0 + d2 * c1) * d;
float c = 1 - a - b;
_clippedUVs[s] = u1 * a + u2 * b + u3 * c;
_clippedUVs[s + 1] = v1 * a + v2 * b + v3 * c;
s += 2;
}
s = static_cast<int>(clippedTriangles.size());
clippedTriangles.reserve(s + 3 * (clipOutputCount - 2));
clipOutputCount--;
for (int ii = 1; ii < clipOutputCount; ii++)
{
clippedTriangles[s] = index;
clippedTriangles[s + 1] = index + ii;
clippedTriangles[s + 2] = index + ii + 1;
s += 3;
}
index += clipOutputCount + 1;
}
else
{
clippedVertices.reserve(s + 3 * 2);
_clippedUVs.reserve(s + 3 * 2);
clippedVertices[s] = x1;
clippedVertices[s + 1] = y1;
clippedVertices[s + 2] = x2;
clippedVertices[s + 3] = y2;
clippedVertices[s + 4] = x3;
clippedVertices[s + 5] = y3;
_clippedUVs[s] = u1;
_clippedUVs[s + 1] = v1;
_clippedUVs[s + 2] = u2;
_clippedUVs[s + 3] = v2;
_clippedUVs[s + 4] = u3;
_clippedUVs[s + 5] = v3;
s = static_cast<int>(clippedTriangles.size());
clippedTriangles.reserve(s + 3);
clippedTriangles[s] = index;
clippedTriangles[s + 1] = index + 1;
clippedTriangles[s + 2] = index + 2;
index += 3;
break;
}
}
}
}
@ -201,105 +201,105 @@ namespace Spine
{
Vector<float> originalOutput = output;
bool clipped = false;
//
// // Avoid copy at the end.
// Vector<float> input = NULL;
// if (clippingArea.Count % 4 >= 2)
// {
// input = output;
// output = scratch;
// }
// else
// {
// input = scratch;
// }
//
// input.Clear();
// input.push_back(x1);
// input.push_back(y1);
// input.push_back(x2);
// input.push_back(y2);
// input.push_back(x3);
// input.push_back(y3);
// input.push_back(x1);
// input.push_back(y1);
// output.Clear();
//
// Vector<float> clippingVertices = clippingArea.Items;
// int clippingVerticesLast = clippingArea.Count - 4;
// for (int i = 0; ; i += 2)
// {
// float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
// float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
// float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
//
// Vector<float> inputVertices = input.Items;
// int inputVerticesLength = input.Count - 2, outputStart = output.Count;
// for (int ii = 0; ii < inputVerticesLength; ii += 2)
// {
// float inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
// float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
// bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
// if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0)
// {
// if (side2)
// {
// // v1 inside, v2 inside
// output.push_back(inputX2);
// output.push_back(inputY2);
// continue;
// }
// // v1 inside, v2 outside
// float c0 = inputY2 - inputY, c2 = inputX2 - inputX;
// float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
// output.push_back(edgeX + (edgeX2 - edgeX) * ua);
// output.push_back(edgeY + (edgeY2 - edgeY) * ua);
// }
// else if (side2)
// {
// // v1 outside, v2 inside
// float c0 = inputY2 - inputY, c2 = inputX2 - inputX;
// float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
// output.push_back(edgeX + (edgeX2 - edgeX) * ua);
// output.push_back(edgeY + (edgeY2 - edgeY) * ua);
// output.push_back(inputX2);
// output.push_back(inputY2);
// }
// clipped = true;
// }
//
// if (outputStart == output.Count)
// {
// // All edges outside.
// originalOutput.Clear();
// return true;
// }
//
// output.push_back(output.Items[0]);
// output.push_back(output.Items[1]);
//
// if (i == clippingVerticesLast)
// {
// break;
// }
// var temp = output;
// output = input;
// output.Clear();
// input = temp;
// }
//
// if (originalOutput != output)
// {
// originalOutput.Clear();
// for (int i = 0, n = output.Count - 2; i < n; i++)
// {
// originalOutput.push_back(output.Items[i]);
// }
// }
// else
// {
// originalOutput.Resize(originalOutput.Count - 2);
// }
// Avoid copy at the end.
Vector<float> input;
if (clippingArea.size() % 4 >= 2)
{
input = output;
output = _scratch;
}
else
{
input = _scratch;
}
input.clear();
input.push_back(x1);
input.push_back(y1);
input.push_back(x2);
input.push_back(y2);
input.push_back(x3);
input.push_back(y3);
input.push_back(x1);
input.push_back(y1);
output.clear();
Vector<float> clippingVertices = clippingArea;
int clippingVerticesLast = static_cast<int>(clippingArea.size()) - 4;
for (int i = 0; ; i += 2)
{
float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
Vector<float> inputVertices = input;
int inputVerticesLength = static_cast<int>(input.size()) - 2, outputStart = static_cast<int>(output.size());
for (int ii = 0; ii < inputVerticesLength; ii += 2)
{
float inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0)
{
if (side2)
{
// v1 inside, v2 inside
output.push_back(inputX2);
output.push_back(inputY2);
continue;
}
// v1 inside, v2 outside
float c0 = inputY2 - inputY, c2 = inputX2 - inputX;
float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push_back(edgeX + (edgeX2 - edgeX) * ua);
output.push_back(edgeY + (edgeY2 - edgeY) * ua);
}
else if (side2)
{
// v1 outside, v2 inside
float c0 = inputY2 - inputY, c2 = inputX2 - inputX;
float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
output.push_back(edgeX + (edgeX2 - edgeX) * ua);
output.push_back(edgeY + (edgeY2 - edgeY) * ua);
output.push_back(inputX2);
output.push_back(inputY2);
}
clipped = true;
}
if (outputStart == output.size())
{
// All edges outside.
originalOutput.clear();
return true;
}
output.push_back(output[0]);
output.push_back(output[1]);
if (i == clippingVerticesLast)
{
break;
}
Vector<float> temp = output;
output = input;
output.clear();
input = temp;
}
if (originalOutput != output)
{
originalOutput.clear();
for (int i = 0, n = static_cast<int>(output.size()) - 2; i < n; ++i)
{
originalOutput.push_back(output[i]);
}
}
else
{
originalOutput.reserve(originalOutput.size() - 2);
}
return clipped;
}

View File

@ -37,6 +37,8 @@
#include <spine/TimelineType.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#include <spine/TransformConstraint.h>
#include <spine/TransformConstraintData.h>
namespace Spine
{
@ -53,13 +55,95 @@ namespace Spine
const int TransformConstraintTimeline::SCALE = 3;
const int TransformConstraintTimeline::SHEAR = 4;
TransformConstraintTimeline::TransformConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _transformConstraintIndex(0)
{
_frames.reserve(frameCount * ENTRIES);
}
void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
// TODO
TransformConstraint* constraintP = skeleton._transformConstraints[_transformConstraintIndex];
TransformConstraint& constraint = *constraintP;
if (time < _frames[0])
{
switch (pose)
{
case MixPose_Setup:
constraint._rotateMix = constraint._data._rotateMix;
constraint._translateMix = constraint._data._translateMix;
constraint._scaleMix = constraint._data._scaleMix;
constraint._shearMix = constraint._data._shearMix;
return;
case MixPose_Current:
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;
return;
case MixPose_CurrentLayered:
default:
return;
}
}
float rotate, translate, scale, shear;
if (time >= _frames[_frames.size() - ENTRIES])
{
// Time is after last frame.
int i = static_cast<int>(_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));
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 (pose == MixPose_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;
}
}
int TransformConstraintTimeline::getPropertyId()
{
return ((int)TimelineType_TransformConstraint << 24) + _transformConstraintIndex;
}
void TransformConstraintTimeline::setFrame(int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix)
{
frameIndex *= ENTRIES;
_frames[frameIndex] = time;
_frames[frameIndex + ROTATE] = rotateMix;
_frames[frameIndex + TRANSLATE] = translateMix;
_frames[frameIndex + SCALE] = scaleMix;
_frames[frameIndex + SHEAR] = shearMix;
}
}

View File

@ -37,18 +37,90 @@
#include <spine/TimelineType.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#include <spine/Bone.h>
#include <spine/BoneData.h>
namespace Spine
{
RTTI_IMPL(TranslateTimeline, CurveTimeline);
const int TranslateTimeline::ENTRIES = 3;
const int TranslateTimeline::PREV_TIME = -3;
const int TranslateTimeline::PREV_X = -2;
const int TranslateTimeline::PREV_Y = -1;
const int TranslateTimeline::X = 1;
const int TranslateTimeline::Y = 2;
TranslateTimeline::TranslateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0)
{
_frames.reserve(frameCount * ENTRIES);
}
void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
// TODO
Bone* boneP = skeleton._bones[_boneIndex];
Bone& bone = *boneP;
if (time < _frames[0])
{
switch (pose)
{
case MixPose_Setup:
bone._x = bone._data._x;
bone._y = bone._data._y;
return;
case MixPose_Current:
bone._x += (bone._data._x - bone._x) * alpha;
bone._y += (bone._data._y - bone._y) * alpha;
return;
case MixPose_CurrentLayered:
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));
x += (_frames[frame + X] - x) * percent;
y += (_frames[frame + Y] - y) * percent;
}
if (pose == MixPose_Setup)
{
bone._x = bone._data._x + x * alpha;
bone._y = bone._data._y + y * alpha;
}
else
{
bone._x += (bone._data._x + x - bone._x) * alpha;
bone._y += (bone._data._y + y - bone._y) * alpha;
}
}
int TranslateTimeline::getPropertyId()
{
return ((int)TimelineType_Translate << 24) + _boneIndex;
}
void TranslateTimeline::setFrame(int frameIndex, float time, float x, float y)
{
frameIndex *= ENTRIES;
_frames[frameIndex] = time;
_frames[frameIndex + X] = x;
_frames[frameIndex + Y] = y;
}
}

View File

@ -42,13 +42,169 @@ namespace Spine
{
RTTI_IMPL(TwoColorTimeline, CurveTimeline);
const int TwoColorTimeline::ENTRIES = 8;
const int TwoColorTimeline::PREV_TIME = -8;
const int TwoColorTimeline::PREV_R = -7;
const int TwoColorTimeline::PREV_G = -6;
const int TwoColorTimeline::PREV_B = -5;
const int TwoColorTimeline::PREV_A = -4;
const int TwoColorTimeline::PREV_R2 = -3;
const int TwoColorTimeline::PREV_G2 = -2;
const int TwoColorTimeline::PREV_B2 = -1;
const int TwoColorTimeline::R = 1;
const int TwoColorTimeline::G = 2;
const int TwoColorTimeline::B = 3;
const int TwoColorTimeline::A = 4;
const int TwoColorTimeline::R2 = 5;
const int TwoColorTimeline::G2 = 6;
const int TwoColorTimeline::B2 = 7;
TwoColorTimeline::TwoColorTimeline(int frameCount) : CurveTimeline(frameCount)
{
_frames.reserve(frameCount * ENTRIES);
}
void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
// TODO
Slot* slotP = skeleton._slots[_slotIndex];
Slot& slot = *slotP;
if (time < _frames[0])
{
// Time is before first frame.
switch (pose)
{
case MixPose_Setup:
slot._r = slot._data._r;
slot._g = slot._data._g;
slot._b = slot._data._b;
slot._a = slot._data._a;
slot._r2 = slot._data._r2;
slot._g2 = slot._data._g2;
slot._b2 = slot._data._b2;
return;
case MixPose_Current:
slot._r += (slot._r - slot._data._r) * alpha;
slot._g += (slot._g - slot._data._g) * alpha;
slot._b += (slot._b - slot._data._b) * alpha;
slot._a += (slot._a - slot._data._a) * alpha;
slot._r2 += (slot._r2 - slot._data._r2) * alpha;
slot._g2 += (slot._g2 - slot._data._g2) * alpha;
slot._b2 += (slot._b2 - slot._data._b2) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
}
}
float r, g, b, a, r2, g2, b2;
if (time >= _frames[_frames.size() - ENTRIES])
{
// Time is after last frame.
int i = static_cast<int>(_frames.size());
r = _frames[i + PREV_R];
g = _frames[i + PREV_G];
b = _frames[i + PREV_B];
a = _frames[i + PREV_A];
r2 = _frames[i + PREV_R2];
g2 = _frames[i + PREV_G2];
b2 = _frames[i + PREV_B2];
}
else
{
// Interpolate between the previous frame and the current frame.
int frame = 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];
r2 = _frames[frame + PREV_R2];
g2 = _frames[frame + PREV_G2];
b2 = _frames[frame + PREV_B2];
float frameTime = _frames[frame];
float percent = getCurvePercent(frame / ENTRIES - 1,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
r += (_frames[frame + R] - r) * percent;
g += (_frames[frame + G] - g) * percent;
b += (_frames[frame + B] - b) * percent;
a += (_frames[frame + A] - a) * percent;
r2 += (_frames[frame + R2] - r2) * percent;
g2 += (_frames[frame + G2] - g2) * percent;
b2 += (_frames[frame + B2] - b2) * percent;
}
if (alpha == 1)
{
slot._r = r;
slot._g = g;
slot._b = b;
slot._a = a;
slot._r2 = r2;
slot._g2 = g2;
slot._b2 = b2;
}
else
{
float br, bg, bb, ba, br2, bg2, bb2;
if (pose == MixPose_Setup)
{
br = slot._data._r;
bg = slot._data._g;
bb = slot._data._b;
ba = slot._data._a;
br2 = slot._data._r2;
bg2 = slot._data._g2;
bb2 = slot._data._b2;
}
else
{
br = slot._r;
bg = slot._g;
bb = slot._b;
ba = slot._a;
br2 = slot._r2;
bg2 = slot._g2;
bb2 = slot._b2;
}
slot._r = br + ((r - br) * alpha);
slot._g = bg + ((g - bg) * alpha);
slot._b = bb + ((b - bb) * alpha);
slot._a = ba + ((a - ba) * alpha);
slot._r2 = br2 + ((r2 - br2) * alpha);
slot._g2 = bg2 + ((g2 - bg2) * alpha);
slot._b2 = bb2 + ((b2 - bb2) * alpha);
}
}
int TwoColorTimeline::getPropertyId()
{
return ((int)TimelineType_TwoColor << 24) + _slotIndex;
}
void TwoColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2)
{
frameIndex *= ENTRIES;
_frames[frameIndex] = time;
_frames[frameIndex + R] = r;
_frames[frameIndex + G] = g;
_frames[frameIndex + B] = b;
_frames[frameIndex + A] = a;
_frames[frameIndex + R2] = r2;
_frames[frameIndex + G2] = g2;
_frames[frameIndex + B2] = b2;
}
int TwoColorTimeline::getSlotIndex()
{
return _slotIndex;
}
void TwoColorTimeline::setSlotIndex(int inValue)
{
assert(inValue >= 0);
_slotIndex = inValue;
}
}