diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 9900324be..a2bdae9e3 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -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); diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index e5d82ef31..2d2ce3da6 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -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); diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index e88d50b1a..b1512327e 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -39,56 +39,25 @@ namespace Spine { RTTI_DECL; + public: + EventTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& 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 > lastTime and <= time. -// public void Apply (Skeleton skeleton, float lastTime, float time, Vector 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 getFrames(); + void setFrames(Vector& inValue); + Vector& getEvents(); + void setEvents(Vector& inValue); + int getFrameCount(); + + private: + Vector _frames; + Vector _events; }; } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index c09f8c7cd..387efb900 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -44,6 +44,7 @@ namespace Spine class IkConstraint : public Constraint { friend class Skeleton; + friend class IkConstraintTimeline; RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index 0b516aa7e..9edc33bf0 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -43,6 +43,7 @@ namespace Spine { friend class IkConstraint; friend class Skeleton; + friend class IkConstraintTimeline; public: IkConstraintData(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index 6ab6d35c6..fe570146b 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -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 _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 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]; -// } -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h index 7f6440c48..a88e5a4cc 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -46,6 +46,9 @@ namespace Spine class PathConstraint : public Constraint { friend class Skeleton; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index fc7a77d16..8a41880f2 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -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); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index 65d286470..96f0bd1a8 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -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& 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 _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 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); }; } diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index 72734d4d8..ab6839e1f 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -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 _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 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; -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index a0fa2b9fb..fb959a55a 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -45,41 +45,6 @@ namespace Spine virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); - -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector 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; -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index d0ce306d3..12f941f42 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -39,72 +39,12 @@ namespace Spine { RTTI_DECL; + public: + ScaleTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& 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 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; -// } -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index 1916fd8f4..5618a6529 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -40,55 +40,11 @@ namespace Spine RTTI_DECL; public: + ShearTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& 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 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; -// } -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index 262c3a210..7c5061f60 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -44,6 +44,7 @@ namespace Spine class TransformConstraint : public Constraint { friend class Skeleton; + friend class TransformConstraintTimeline; RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index d3a5aebb3..603175d4f 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -43,6 +43,7 @@ namespace Spine { friend class TransformConstraint; friend class Skeleton; + friend class TransformConstraintTimeline; public: TransformConstraintData(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index e4486d197..6065d4727 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -42,94 +42,20 @@ namespace Spine public: static const int ENTRIES; + TransformConstraintTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& 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 _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 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; -// } -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index 6faac140a..d661f9d3f 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -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& 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 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 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 _frames; + int _boneIndex; }; } diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index d70375d34..ceb23848f 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -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& 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 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 _frames; // time, r, g, b, a, r2, g2, b2, ... + int _slotIndex; }; } diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 8fc87c490..9ae06e982 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -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& lhs, Vector& rhs) + { + if (lhs.size() != rhs.size()) + { + return false; + } + + for (int i = 0, n = static_cast(lhs.size()); i < n; ++i) + { + if (lhs[i] != rhs[i]) + { + return false; + } + } + + return true; + } + + friend bool operator!=(Vector& lhs, Vector& rhs) + { + return !(lhs == rhs); + } + private: size_t _size; size_t _capacity; diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index 2e6f69b03..87ab7a814 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -37,18 +37,83 @@ #include #include #include +#include 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& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + if (events.size() == 0) + { + return; + } + + int frameCount = static_cast(_frames.size()); + + if (lastTime > time) + { + // Fire events after last time for looped animations. + apply(skeleton, lastTime, std::numeric_limits::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 EventTimeline::getFrames() { return _frames; } + void EventTimeline::setFrames(Vector& inValue) { _frames = inValue; } // time, ... + Vector& EventTimeline::getEvents() { return _events; } + void EventTimeline::setEvents(Vector& inValue) { _events = inValue; } + int EventTimeline::getFrameCount() { return static_cast(_frames.size()); } } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index a8c89f715..2b05750e3 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include namespace Spine { @@ -56,11 +58,77 @@ namespace Spine void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& 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; + } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index 772eb4e4f..394ecf48e 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -37,18 +37,90 @@ #include #include #include +#include +#include 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& 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; + } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index 2a1d2949b..75b423ee9 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include 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& 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; + } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index 474930d7e..7d4713585 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include namespace Spine { @@ -49,7 +51,49 @@ namespace Spine void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& 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() diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index f431f589c..0be6f9347 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -37,14 +37,94 @@ #include #include #include +#include +#include namespace Spine { RTTI_IMPL(ScaleTimeline, TranslateTimeline); + ScaleTimeline::ScaleTimeline(int frameCount) : TranslateTimeline(frameCount) + { + // Empty + } + void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& 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() diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index 1f114c972..4b142eccc 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -37,14 +37,72 @@ #include #include #include +#include +#include namespace Spine { RTTI_IMPL(ShearTimeline, TranslateTimeline); + ShearTimeline::ShearTimeline(int frameCount) : TranslateTimeline(frameCount) + { + // Empty + } + void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& 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() diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp index 5132b8b88..3ca3d9dbd 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -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* > clippingPolygons = _triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); + + _clippingPolygons = clippingPolygons; for (Vector** i = _clippingPolygons.begin(); i != _clippingPolygons.end(); ++i) { @@ -97,14 +99,13 @@ namespace Spine Vector& clipOutput = _clipOutput, clippedVertices = _clippedVertices; Vector& clippedTriangles = _clippedTriangles; Vector< Vector* >& polygons = _clippingPolygons; - int polygonsCount = _clippingPolygons.size(); + int polygonsCount = static_cast(_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(clippedVertices.size()); + if (clip(x1, y1, x2, y2, x3, y3, *polygons[p], clipOutput)) + { + int clipOutputLength = static_cast(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(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(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 originalOutput = output; bool clipped = false; -// -// // Avoid copy at the end. -// Vector 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 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 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 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 clippingVertices = clippingArea; + int clippingVerticesLast = static_cast(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 inputVertices = input; + int inputVerticesLength = static_cast(input.size()) - 2, outputStart = static_cast(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 temp = output; + output = input; + output.clear(); + input = temp; + } + + if (originalOutput != output) + { + originalOutput.clear(); + for (int i = 0, n = static_cast(output.size()) - 2; i < n; ++i) + { + originalOutput.push_back(output[i]); + } + } + else + { + originalOutput.reserve(originalOutput.size() - 2); + } return clipped; } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index 01914067f..bb4769cce 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include 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& 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(_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; + } } diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index f7ae4abbe..1a886f7d1 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -37,18 +37,90 @@ #include #include #include +#include +#include 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& 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; + } } diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 9f092c488..9003487b4 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -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& 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(_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; + } }