Ported first batch of last changes to runtimes.

This commit is contained in:
badlogic 2018-04-20 13:58:39 +02:00
parent ace5d18660
commit 0bbcd971e9
39 changed files with 451 additions and 374 deletions

View File

@ -32,7 +32,7 @@
#define Spine_Animation_h #define Spine_Animation_h
#include <spine/Vector.h> #include <spine/Vector.h>
#include <spine/MixPose.h> #include <spine/MixBlend.h>
#include <spine/MixDirection.h> #include <spine/MixDirection.h>
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
#include <spine/String.h> #include <spine/String.h>
@ -89,7 +89,7 @@ public:
/// Applies all the animation's timelines to the specified skeleton. /// Applies all the animation's timelines to the specified skeleton.
/// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection) /// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection)
void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector<Event *> *pEvents, float alpha, void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction); MixBlend blend, MixDirection direction);
const String &getName(); const String &getName();

View File

@ -33,7 +33,7 @@
#include <spine/Vector.h> #include <spine/Vector.h>
#include <spine/Pool.h> #include <spine/Pool.h>
#include <spine/MixPose.h> #include <spine/MixBlend.h>
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
#include <spine/String.h> #include <spine/String.h>
@ -196,6 +196,10 @@ namespace Spine {
/// ///
float getMixDuration(); float getMixDuration();
void setMixDuration(float inValue); void setMixDuration(float inValue);
float getMixBlend();
void setMixBlend(MixBlend blend);
/// ///
/// The track entry for the previous animation when mixing from the previous animation to this animation, or NULL if no /// The track entry for the previous animation when mixing from the previous animation to this animation, or NULL if no
@ -227,6 +231,7 @@ namespace Spine {
float _animationStart, _animationEnd, _animationLast, _nextAnimationLast; float _animationStart, _animationEnd, _animationLast, _nextAnimationLast;
float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale; float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale;
float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha; float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha;
MixBlend _mixBlend;
Vector<int> _timelineData; Vector<int> _timelineData;
Vector<TrackEntry*> _timelineDipMix; Vector<TrackEntry*> _timelineDipMix;
Vector<float> _timelinesRotation; Vector<float> _timelinesRotation;
@ -400,12 +405,12 @@ namespace Spine {
static Animation* getEmptyAnimation(); static Animation* getEmptyAnimation();
static void applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, Vector<float>& timelinesRotation, int i, bool firstFrame); static void applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixBlend pose, Vector<float>& timelinesRotation, int i, bool firstFrame);
/// Returns true when all mixing from entries are complete. /// Returns true when all mixing from entries are complete.
bool updateMixingFrom(TrackEntry* to, float delta); bool updateMixingFrom(TrackEntry* to, float delta);
float applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose); float applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixBlend currentPose);
void queueEvents(TrackEntry* entry, float animationTime); void queueEvents(TrackEntry* entry, float animationTime);

View File

@ -34,7 +34,7 @@
#include <spine/Timeline.h> #include <spine/Timeline.h>
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
#include <spine/Vector.h> #include <spine/Vector.h>
#include <spine/MixPose.h> #include <spine/MixBlend.h>
#include <spine/MixDirection.h> #include <spine/MixDirection.h>
#include <spine/String.h> #include <spine/String.h>
@ -51,7 +51,7 @@ namespace Spine {
public: public:
explicit AttachmentTimeline(int frameCount); explicit AttachmentTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -47,7 +47,7 @@ public:
explicit ColorTimeline(int frameCount); explicit ColorTimeline(int frameCount);
virtual void virtual void
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixPose pose, apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
MixDirection direction); MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -44,7 +44,7 @@ namespace Spine {
virtual ~CurveTimeline(); virtual ~CurveTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction) = 0; virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction) = 0;
virtual int getPropertyId() = 0; virtual int getPropertyId() = 0;

View File

@ -45,7 +45,7 @@ namespace Spine {
public: public:
explicit DeformTimeline(int frameCount); explicit DeformTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -43,7 +43,7 @@ namespace Spine {
public: public:
explicit DrawOrderTimeline(int frameCount); explicit DrawOrderTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -45,7 +45,7 @@ namespace Spine {
~EventTimeline(); ~EventTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -45,7 +45,7 @@ namespace Spine {
explicit IkConstraintTimeline(int frameCount); explicit IkConstraintTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -34,15 +34,12 @@
namespace Spine { namespace Spine {
/// ///
/// Controls how a timeline is mixed with the setup or current pose. /// Controls how a timeline is mixed with the setup or current pose.
/// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) /// See also Timeline::apply(Skeleton&, float, float, Vector&, float, Blend, MixDirection)
enum MixPose { enum MixBlend {
/// The timeline value is mixed with the setup pose (the current pose is not used). MixBlend_Setup = 0,
MixPose_Setup = 0, MixBlend_First,
/// The timeline value is mixed with the current pose. The setup pose is used as the timeline value before the first key, MixBlend_Replace,
/// except for timelines which perform instant transitions, such as DrawOrderTimeline or AttachmentTimeline. MixBlend_Add
MixPose_Current,
/// The timeline value is mixed with the current pose. No change is made before the first key (the current pose is kept until the first key).
MixPose_CurrentLayered
}; };
} }

View File

@ -45,7 +45,7 @@ namespace Spine {
explicit PathConstraintMixTimeline(int frameCount); explicit PathConstraintMixTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -47,7 +47,7 @@ namespace Spine {
virtual ~PathConstraintPositionTimeline(); virtual ~PathConstraintPositionTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -43,7 +43,7 @@ namespace Spine {
public: public:
explicit PathConstraintSpacingTimeline(int frameCount); explicit PathConstraintSpacingTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();
}; };

View File

@ -46,7 +46,7 @@ namespace Spine {
explicit RotateTimeline(int frameCount); explicit RotateTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -43,7 +43,7 @@ namespace Spine {
public: public:
explicit ScaleTimeline(int frameCount); explicit ScaleTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();
}; };

View File

@ -43,7 +43,7 @@ namespace Spine {
public: public:
explicit ShearTimeline(int frameCount); explicit ShearTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();
}; };

View File

@ -33,7 +33,7 @@
#include <spine/RTTI.h> #include <spine/RTTI.h>
#include <spine/Vector.h> #include <spine/Vector.h>
#include <spine/MixPose.h> #include <spine/MixBlend.h>
#include <spine/MixDirection.h> #include <spine/MixDirection.h>
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
@ -59,10 +59,10 @@ public:
/// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting /// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting
/// alpha over time, an animation can be mixed in or out. alpha can also be useful to /// alpha over time, an animation can be mixed in or out. alpha can also be useful to
/// apply animations on top of each other (layered). /// apply animations on top of each other (layered).
/// @param pose Controls how mixing is applied when alpha is than 1. /// @param blend Controls how mixing is applied when alpha is than 1.
/// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline. /// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline.
virtual void virtual void
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixPose pose, apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
MixDirection direction) = 0; MixDirection direction) = 0;
virtual int getPropertyId() = 0; virtual int getPropertyId() = 0;

View File

@ -45,7 +45,7 @@ namespace Spine {
explicit TransformConstraintTimeline(int frameCount); explicit TransformConstraintTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -50,7 +50,7 @@ namespace Spine {
virtual ~TranslateTimeline(); virtual ~TranslateTimeline();
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -45,7 +45,7 @@ namespace Spine {
explicit TwoColorTimeline(int frameCount); explicit TwoColorTimeline(int frameCount);
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
virtual int getPropertyId(); virtual int getPropertyId();

View File

@ -65,7 +65,7 @@
#include <spine/MathUtil.h> #include <spine/MathUtil.h>
#include <spine/MeshAttachment.h> #include <spine/MeshAttachment.h>
#include <spine/MixDirection.h> #include <spine/MixDirection.h>
#include <spine/MixPose.h> #include <spine/MixBlend.h>
#include <spine/PathAttachment.h> #include <spine/PathAttachment.h>
#include <spine/PathConstraint.h> #include <spine/PathConstraint.h>
#include <spine/PathConstraintData.h> #include <spine/PathConstraintData.h>

View File

@ -50,7 +50,7 @@ Animation::~Animation() {
} }
void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector<Event *> *pEvents, float alpha, void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
if (loop && _duration != 0) { if (loop && _duration != 0) {
time = MathUtil::fmod(time, _duration); time = MathUtil::fmod(time, _duration);
if (lastTime > 0) { if (lastTime > 0) {
@ -59,7 +59,7 @@ void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop,
} }
for (int i = 0, n = static_cast<int>(_timelines.size()); i < n; ++i) { for (int i = 0, n = static_cast<int>(_timelines.size()); i < n; ++i) {
_timelines[i]->apply(skeleton, lastTime, time, pEvents, alpha, pose, direction); _timelines[i]->apply(skeleton, lastTime, time, pEvents, alpha, blend, direction);
} }
} }

View File

@ -51,7 +51,7 @@ TrackEntry::TrackEntry() : _animation(NULL), _next(NULL), _mixingFrom(NULL), _tr
_eventThreshold(0), _attachmentThreshold(0), _drawOrderThreshold(0), _animationStart(0), _eventThreshold(0), _attachmentThreshold(0), _drawOrderThreshold(0), _animationStart(0),
_animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0), _animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0),
_trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), _trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0),
_mixDuration(0), _interruptAlpha(0), _totalAlpha(0), _mixDuration(0), _mixBlend(MixBlend_Replace), _interruptAlpha(0), _totalAlpha(0),
_onAnimationEventFunc(dummyOnAnimationEventFunc) { _onAnimationEventFunc(dummyOnAnimationEventFunc) {
} }
@ -139,6 +139,10 @@ void TrackEntry::setMixDuration(float inValue) { _mixDuration = inValue; }
TrackEntry *TrackEntry::getMixingFrom() { return _mixingFrom; } TrackEntry *TrackEntry::getMixingFrom() { return _mixingFrom; }
void TrackEntry::setMixBlend(MixBlend blend) { _mixBlend = blend; }
float TrackEntry::getMixBlend() { return _mixBlend; }
void TrackEntry::resetRotationDirections() { void TrackEntry::resetRotationDirections() {
_timelinesRotation.clear(); _timelinesRotation.clear();
} }
@ -419,12 +423,12 @@ bool AnimationState::apply(Skeleton &skeleton) {
TrackEntry &current = *currentP; TrackEntry &current = *currentP;
applied = true; applied = true;
MixPose currentPose = i == 0 ? MixPose_Current : MixPose_CurrentLayered; MixBlend blend = i == 0 ? MixBlend_First : current._mixBlend;
// apply mixing from entries first. // apply mixing from entries first.
float mix = current._alpha; float mix = current._alpha;
if (current._mixingFrom != NULL) { if (current._mixingFrom != NULL) {
mix *= applyMixingFrom(currentP, skeleton, currentPose); mix *= applyMixingFrom(currentP, skeleton, blend);
} else if (current._trackTime >= current._trackEnd && current._next == NULL) { } else if (current._trackTime >= current._trackEnd && current._next == NULL) {
mix = 0; // Set to setup pose the last time the entry will be applied. mix = 0; // Set to setup pose the last time the entry will be applied.
} }
@ -433,9 +437,9 @@ bool AnimationState::apply(Skeleton &skeleton) {
float animationLast = current._animationLast, animationTime = current.getAnimationTime(); float animationLast = current._animationLast, animationTime = current.getAnimationTime();
int timelineCount = static_cast<int>(current._animation->_timelines.size()); int timelineCount = static_cast<int>(current._animation->_timelines.size());
Vector<Timeline *> &timelines = current._animation->_timelines; Vector<Timeline *> &timelines = current._animation->_timelines;
if (mix == 1) { if (mix == 1 || blend == MixBlend_Add) {
for (int ii = 0; ii < timelineCount; ++ii) { for (int ii = 0; ii < timelineCount; ++ii) {
timelines[ii]->apply(skeleton, animationLast, animationTime, &_events, 1, MixPose_Setup, timelines[ii]->apply(skeleton, animationLast, animationTime, &_events, mix, blend,
MixDirection_In); MixDirection_In);
} }
} else { } else {
@ -451,7 +455,7 @@ bool AnimationState::apply(Skeleton &skeleton) {
Timeline *timeline = timelines[ii]; Timeline *timeline = timelines[ii];
assert(timeline); assert(timeline);
MixPose pose = timelineData[ii] >= AnimationState::First ? MixPose_Setup : currentPose; MixBlend timelineBlend = timelineData[ii] == AnimationState::Subsequent ? blend : MixBlend_Setup;
RotateTimeline *rotateTimeline = NULL; RotateTimeline *rotateTimeline = NULL;
if (timeline->getRTTI().isExactly(RotateTimeline::rtti)) { if (timeline->getRTTI().isExactly(RotateTimeline::rtti)) {
@ -459,10 +463,10 @@ bool AnimationState::apply(Skeleton &skeleton) {
} }
if (rotateTimeline != NULL) { if (rotateTimeline != NULL) {
applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1,
firstFrame); firstFrame);
} else { } else {
timeline->apply(skeleton, animationLast, animationTime, &_events, mix, pose, MixDirection_In); timeline->apply(skeleton, animationLast, animationTime, &_events, mix, timelineBlend, MixDirection_In);
} }
} }
} }
@ -665,20 +669,20 @@ Animation *AnimationState::getEmptyAnimation() {
} }
void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha,
MixPose pose, Vector<float> &timelinesRotation, int i, bool firstFrame) { MixBlend blend, Vector<float> &timelinesRotation, int i, bool firstFrame) {
if (firstFrame) { if (firstFrame) {
timelinesRotation[i] = 0; timelinesRotation[i] = 0;
} }
if (alpha == 1) { if (alpha == 1) {
rotateTimeline->apply(skeleton, 0, time, NULL, 1, pose, MixDirection_In); rotateTimeline->apply(skeleton, 0, time, NULL, 1, blend, MixDirection_In);
return; return;
} }
Bone *bone = skeleton._bones[rotateTimeline->_boneIndex]; Bone *bone = skeleton._bones[rotateTimeline->_boneIndex];
Vector<float>& frames = rotateTimeline->_frames; Vector<float>& frames = rotateTimeline->_frames;
if (time < frames[0]) { if (time < frames[0]) {
if (pose == MixPose_Setup) { if (blend == MixBlend_Setup) {
bone->_rotation = bone->_data._rotation; bone->_rotation = bone->_data._rotation;
} }
return; return;
@ -704,7 +708,7 @@ void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleto
} }
// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
float r1 = pose == MixPose_Setup ? bone->_data._rotation : bone->_rotation; float r1 = blend == MixBlend_Setup ? bone->_data._rotation : bone->_rotation;
float total, diff = r2 - r1; float total, diff = r2 - r1;
if (diff == 0) { if (diff == 0) {
total = timelinesRotation[i]; total = timelinesRotation[i];
@ -767,22 +771,23 @@ bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) {
return false; return false;
} }
float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixPose currentPose) { float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend blend) {
TrackEntry *from = to->_mixingFrom; TrackEntry *from = to->_mixingFrom;
if (from->_mixingFrom != NULL) { if (from->_mixingFrom != NULL) {
applyMixingFrom(from, skeleton, currentPose); applyMixingFrom(from, skeleton, blend);
} }
float mix; float mix;
if (to->_mixDuration == 0) { if (to->_mixDuration == 0) {
// Single frame mix to undo mixingFrom changes. // Single frame mix to undo mixingFrom changes.
mix = 1; mix = 1;
currentPose = MixPose_Setup; if (blend == MixBlend_First) blend = MixBlend_Setup;
} else { } else {
mix = to->_mixTime / to->_mixDuration; mix = to->_mixTime / to->_mixDuration;
if (mix > 1) { if (mix > 1) {
mix = 1; mix = 1;
} }
if (blend != MixBlend_First) blend = from->_mixBlend;
} }
Vector<Event *> *eventBuffer = mix < from->_eventThreshold ? &_events : NULL; Vector<Event *> *eventBuffer = mix < from->_eventThreshold ? &_events : NULL;
@ -790,59 +795,56 @@ float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixPos
float animationLast = from->_animationLast, animationTime = from->getAnimationTime(); float animationLast = from->_animationLast, animationTime = from->getAnimationTime();
Vector<Timeline *> &timelines = from->_animation->_timelines; Vector<Timeline *> &timelines = from->_animation->_timelines;
int timelineCount = static_cast<int>(timelines.size()); int timelineCount = static_cast<int>(timelines.size());
Vector<int> &timelineData = from->_timelineData; float alphaDip = from->_alpha * to->_interruptAlpha, alphaMix = alphaDip * (1 - mix);
Vector<TrackEntry *> &timelineDipMix = from->_timelineDipMix;
bool firstFrame = from->_timelinesRotation.size() == 0; if (blend == MixBlend_Add) {
if (firstFrame) { for (int i = 0; i < timelineCount; i++)
from->_timelinesRotation.setSize(timelines.size() << 1, 0); timelines[i]->apply(skeleton, animationLast, animationTime, eventBuffer, alphaMix, blend, MixDirection_Out);
} } else {
Vector<int> &timelineData = from->_timelineData;
Vector<TrackEntry *> &timelineDipMix = from->_timelineDipMix;
Vector<float> &timelinesRotation = from->_timelinesRotation; bool firstFrame = from->_timelinesRotation.size() == 0;
if (firstFrame) {
MixPose pose; from->_timelinesRotation.setSize(timelines.size() << 1, 0);
float alphaDip = from->_alpha * to->_interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha;
from->_totalAlpha = 0;
for (int i = 0; i < timelineCount; ++i) {
Timeline *timeline = timelines[i];
switch (timelineData[i]) {
case Subsequent:
if (!attachments && timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) {
continue;
}
if (!drawOrder && timeline->getRTTI().isExactly(DrawOrderTimeline::rtti)) {
continue;
}
pose = currentPose;
alpha = alphaMix;
break;
case First:
pose = MixPose_Setup;
alpha = alphaMix;
break;
case Dip:
pose = MixPose_Setup;
alpha = alphaDip;
break;
default:
pose = MixPose_Setup;
TrackEntry *dipMix = timelineDipMix[i];
alpha = alphaDip * MathUtil::max(0.0f, 1 - dipMix->_mixTime / dipMix->_mixDuration);
break;
}
from->_totalAlpha += alpha;
RotateTimeline *rotateTimeline = NULL;
if (timeline->getRTTI().isExactly(RotateTimeline::rtti)) {
rotateTimeline = static_cast<RotateTimeline *>(timeline);
} }
if (rotateTimeline != NULL) { Vector<float> &timelinesRotation = from->_timelinesRotation;
applyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1,
firstFrame); from->_totalAlpha = 0;
} else { for (int i = 0; i < timelineCount; i++) {
timeline->apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection_Out); Timeline *timeline = timelines[i];
MixBlend timelineBlend;
float alpha;
switch (timelineData[i]) {
case AnimationState::Subsequent:
if (!attachments && (timeline->getRTTI().isExactly(AttachmentTimeline::rtti))) continue;
if (!drawOrder && (timeline->getRTTI().isExactly(DrawOrderTimeline::rtti))) continue;
timelineBlend = blend;
alpha = alphaMix;
break;
case AnimationState::First:
timelineBlend = MixBlend_Setup;
alpha = alphaMix;
break;
case AnimationState::Dip:
timelineBlend = MixBlend_Setup;
alpha = alphaDip;
break;
default:
timelineBlend = MixBlend_Setup;
TrackEntry *dipMix = timelineDipMix[i];
alpha = alphaDip * MathUtil::max(0.0f, 1.0f - dipMix->_mixTime / dipMix->_mixDuration);
break;
}
from->_totalAlpha += alpha;
if ((timeline->getRTTI().isExactly(RotateTimeline::rtti))) {
applyRotateTimeline((RotateTimeline*)timeline, skeleton, animationTime, alpha, timelineBlend, timelinesRotation, i << 1,
firstFrame);
} else {
timeline->apply(skeleton, animationLast, animationTime, eventBuffer, alpha, timelineBlend,
MixDirection_Out);
}
} }
} }
@ -976,7 +978,7 @@ void AnimationState::animationsChanged() {
for (int i = 0, n = static_cast<int>(_tracks.size()); i < n; ++i) { for (int i = 0, n = static_cast<int>(_tracks.size()); i < n; ++i) {
TrackEntry *entry = _tracks[i]; TrackEntry *entry = _tracks[i];
if (entry != NULL) { if (entry != NULL && entry->_mixBlend != MixBlend_Add) {
entry->setTimelineData(NULL, _mixingTo, _propertyIDs); entry->setTimelineData(NULL, _mixingTo, _propertyIDs);
} }
} }

View File

@ -54,13 +54,13 @@ AttachmentTimeline::AttachmentTimeline(int frameCount) : Timeline(), _slotIndex(
} }
void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
assert(_slotIndex < skeleton._slots.size()); assert(_slotIndex < skeleton._slots.size());
String *attachmentName; String *attachmentName;
Slot *slotP = skeleton._slots[_slotIndex]; Slot *slotP = skeleton._slots[_slotIndex];
Slot &slot = *slotP; Slot &slot = *slotP;
if (direction == MixDirection_Out && pose == MixPose_Setup) { if (direction == MixDirection_Out && blend == MixBlend_Setup) {
attachmentName = &slot._data._attachmentName; attachmentName = &slot._data._attachmentName;
slot._attachment = attachmentName->length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName); slot._attachment = attachmentName->length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName);
return; return;
@ -68,7 +68,7 @@ void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, V
if (time < _frames[0]) { if (time < _frames[0]) {
// Time is before first frame. // Time is before first frame.
if (pose == MixPose_Setup) { if (blend == MixBlend_Setup || blend == MixBlend_First) {
attachmentName = &slot._data._attachmentName; attachmentName = &slot._data._attachmentName;
slot._attachment = slot._attachment =
attachmentName->length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName); attachmentName->length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName);

View File

@ -58,27 +58,23 @@ ColorTimeline::ColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotI
} }
void ColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void ColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
Slot *slotP = skeleton._slots[_slotIndex]; Slot *slotP = skeleton._slots[_slotIndex];
Slot &slot = *slotP; Slot &slot = *slotP;
if (time < _frames[0]) { if (time < _frames[0]) {
SlotData &slotData = slot._data; SlotData &slotData = slot._data;
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
slot.getColor().set(slotData.getColor()); slot._color.set(slot._data._color);
return; return;
case MixPose_Current: { case MixBlend_First: {
Color &color = slot.getColor(); Color color = slot._color, setup = slot._data._color;
Color &setup = slot.getData().getColor(); color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha,
(setup.b - color.b) * alpha,
(setup.a - color.a) * alpha); (setup.a - color.a) * alpha);
return;
} }
case MixPose_CurrentLayered: default: ;
default:
return;
} }
return;
} }
float r, g, b, a; float r, g, b, a;
@ -110,7 +106,7 @@ void ColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
slot.getColor().set(r, g, b, a); slot.getColor().set(r, g, b, a);
} else { } else {
Color &color = slot.getColor(); Color &color = slot.getColor();
if (pose == MixPose_Setup) color.set(slot.getData().getColor()); if (blend == MixBlend_Setup) color.set(slot.getData().getColor());
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
} }
} }

View File

@ -57,128 +57,194 @@ DeformTimeline::DeformTimeline(int frameCount) : CurveTimeline(frameCount), _slo
} }
void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
Slot *slotP = skeleton._slots[_slotIndex]; Slot *slotP = skeleton._slots[_slotIndex];
Slot &slot = *slotP; Slot &slot = *slotP;
if (slot._attachment == NULL || !slot._attachment->getRTTI().instanceOf(VertexAttachment::rtti)) { Attachment *slotAttachment = slot._attachment;
if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) {
return; return;
} }
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slot._attachment); VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (!vertexAttachment->applyDeform(_attachment)) { if (!vertexAttachment->applyDeform(_attachment)) {
return; return;
} }
Vector<float> &vertices = slot._attachmentVertices; Vector<float> &verticesArray = slot._attachmentVertices;
if (vertices.size() == 0) { if (verticesArray.size() == 0) {
alpha = 1; blend = MixBlend_Setup;
} }
int vertexCount = static_cast<int>(_frameVertices[0].size()); Vector< Vector<float> > &frameVertices = _frameVertices;
int vertexCount = static_cast<int>(frameVertices[0].size());
Vector<float> &frames = _frames;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
vertices.clear(); verticesArray.clear();
return; return;
case MixPose_Current: case MixBlend_First:
if (alpha == 1) { if (alpha == 1) {
vertices.clear(); verticesArray.clear();
return;
}
// Ensure size and preemptively set count.
vertices.setSize(vertexCount, 0);
if (vertexAttachment->_bones.size() == 0) {
// Unweighted vertex positions.
Vector<float> &setupVertices = vertexAttachment->_vertices;
for (int i = 0; i < vertexCount; ++i) {
vertices[i] += (setupVertices[i] - vertices[i]) * alpha;
}
} else {
// Weighted deform offsets.
alpha = 1 - alpha;
for (int i = 0; i < vertexCount; ++i) {
vertices[i] *= alpha;
}
}
return;
default:
return; return;
}
verticesArray.setSize(vertexCount, 0);
Vector<float> &vertices = verticesArray;
if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions.
Vector<float> &setupVertices = vertexAttachment->getVertices();
for (int i = 0; i < vertexCount; i++)
vertices[i] += (setupVertices[i] - vertices[i]) * alpha;
} else {
// Weighted deform offsets.
alpha = 1 - alpha;
for (int i = 0; i < vertexCount; i++)
vertices[i] *= alpha;
}
} }
return;
} }
// Ensure size and preemptively set count. verticesArray.setSize(vertexCount, 0);
vertices.setSize(vertexCount, 0); Vector<float> &vertices = verticesArray;
if (time >= _frames[_frames.size() - 1]) { if (time >= frames[frames.size() - 1]) { // Time is after last frame.
// Time is after last frame. Vector<float> &lastVertices = frameVertices[frames.size() - 1];
Vector<float> &lastVertices = _frameVertices[_frames.size() - 1];
if (alpha == 1) { if (alpha == 1) {
// Vertex positions or deform offsets, no alpha. if (blend == MixBlend_Add) {
vertices.clear(); VertexAttachment *vertexAttachment = static_cast<VertexAttachment*>(slotAttachment);
for (int i = 0; i < vertexCount; ++i) { if (vertexAttachment->getBones().size() == 0) {
float vertex = lastVertices[i]; // Unweighted vertex positions, no alpha.
vertices.add(vertex); Vector<float> &setupVertices = vertexAttachment->getVertices();
} for (int i = 0; i < vertexCount; i++)
} else if (pose == MixPose_Setup) { vertices[i] += lastVertices[i] - setupVertices[i];
if (vertexAttachment->_bones.size() == 0) { } else {
// Unweighted vertex positions, with alpha. // Weighted deform offsets, no alpha.
Vector<float> &setupVertices = vertexAttachment->_vertices; for (int i = 0; i < vertexCount; i++)
for (int i = 0; i < vertexCount; i++) { vertices[i] += lastVertices[i];
float setup = setupVertices[i];
vertices[i] = setup + (lastVertices[i] - setup) * alpha;
} }
} else { } else {
// Weighted deform offsets, with alpha. // Vertex positions or deform offsets, no alpha.
for (int i = 0; i < vertexCount; ++i) { memcpy(vertices.buffer(), lastVertices.buffer(), vertexCount * sizeof(float));
vertices[i] = lastVertices[i] * alpha;
}
} }
} else { } else {
// Vertex positions or deform offsets, with alpha. switch (blend) {
for (int i = 0; i < vertexCount; ++i) { case MixBlend_Setup: {
vertices[i] += (lastVertices[i] - vertices[i]) * alpha; VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, with alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices();
for (int i = 0; i < vertexCount; i++) {
float setup = setupVertices[i];
vertices[i] = setup + (lastVertices[i] - setup) * alpha;
}
} else {
// Weighted deform offsets, with alpha.
for (int i = 0; i < vertexCount; i++)
vertices[i] = lastVertices[i] * alpha;
}
break;
}
case MixBlend_First:
case MixBlend_Replace:
// Vertex positions or deform offsets, with alpha.
for (int i = 0; i < vertexCount; i++)
vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
break;
case MixBlend_Add:
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, no alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices();
for (int i = 0; i < vertexCount; i++)
vertices[i] += (lastVertices[i] - setupVertices[i]) * alpha;
} else {
// Weighted deform offsets, alpha.
for (int i = 0; i < vertexCount; i++)
vertices[i] += lastVertices[i] * alpha;
}
} }
} }
return; return;
} }
// Interpolate between the previous frame and the current frame. // Interpolate between the previous frame and the current frame.
int frame = Animation::binarySearch(_frames, time); int frame = Animation::binarySearch(frames, time);
Vector<float> &prevVertices = _frameVertices[frame - 1]; Vector<float> &prevVertices = frameVertices[frame - 1];
Vector<float> &nextVertices = _frameVertices[frame]; Vector<float> &nextVertices = frameVertices[frame];
float frameTime = _frames[frame]; float frameTime = frames[frame];
float percent = getCurvePercent(frame - 1, 1 - (time - frameTime) / (_frames[frame - 1] - frameTime)); float percent = getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime));
if (alpha == 1) { if (alpha == 1) {
// Vertex positions or deform offsets, no alpha. if (blend == MixBlend_Add) {
for (int i = 0; i < vertexCount; ++i) { VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
float prev = prevVertices[i]; if (vertexAttachment->getBones().size() == 0) {
vertices[i] = prev + (nextVertices[i] - prev) * percent; // Unweighted vertex positions, no alpha.
} Vector<float> &setupVertices = vertexAttachment->getVertices();
} else if (pose == MixPose_Setup) { for (int i = 0; i < vertexCount; i++) {
if (vertexAttachment->_bones.size() == 0) { float prev = prevVertices[i];
// Unweighted vertex positions, with alpha. vertices[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i];
Vector<float> &setupVertices = vertexAttachment->_vertices; }
for (int i = 0; i < vertexCount; ++i) { } else {
float prev = prevVertices[i], setup = setupVertices[i]; // Weighted deform offsets, no alpha.
vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; for (int i = 0; i < vertexCount; i++) {
float prev = prevVertices[i];
vertices[i] += prev + (nextVertices[i] - prev) * percent;
}
} }
} else { } else {
// Weighted deform offsets, with alpha. // Vertex positions or deform offsets, no alpha.
for (int i = 0; i < vertexCount; ++i) { for (int i = 0; i < vertexCount; i++) {
float prev = prevVertices[i]; float prev = prevVertices[i];
vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; vertices[i] = prev + (nextVertices[i] - prev) * percent;
} }
} }
} else { } else {
// Vertex positions or deform offsets, with alpha. switch (blend) {
for (int i = 0; i < vertexCount; ++i) { case MixBlend_Setup: {
float prev = prevVertices[i]; VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, with alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices();
for (int i = 0; i < vertexCount; i++) {
float prev = prevVertices[i], setup = setupVertices[i];
vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
}
} else {
// Weighted deform offsets, with alpha.
for (int i = 0; i < vertexCount; i++) {
float prev = prevVertices[i];
vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
}
}
break;
}
case MixBlend_First:
case MixBlend_Replace:
// Vertex positions or deform offsets, with alpha.
for (int i = 0; i < vertexCount; i++) {
float prev = prevVertices[i];
vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
}
break;
case MixBlend_Add:
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, with alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices();
for (int i = 0; i < vertexCount; i++) {
float prev = prevVertices[i];
vertices[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha;
}
} else {
// Weighted deform offsets, with alpha.
for (int i = 0; i < vertexCount; i++) {
float prev = prevVertices[i];
vertices[i] += (prev + (nextVertices[i] - prev) * percent) * alpha;
}
}
} }
} }
} }

View File

@ -55,10 +55,10 @@ DrawOrderTimeline::DrawOrderTimeline(int frameCount) : Timeline() {
} }
void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
Vector<Slot *> &drawOrder = skeleton._drawOrder; Vector<Slot *> &drawOrder = skeleton._drawOrder;
Vector<Slot *> &slots = skeleton._slots; Vector<Slot *> &slots = skeleton._slots;
if (direction == MixDirection_Out && pose == MixPose_Setup) { if (direction == MixDirection_Out && blend == MixBlend_Setup) {
drawOrder.clear(); drawOrder.clear();
drawOrder.ensureCapacity(slots.size()); drawOrder.ensureCapacity(slots.size());
for (int i = 0, n = static_cast<int>(slots.size()); i < n; ++i) { for (int i = 0, n = static_cast<int>(slots.size()); i < n; ++i) {
@ -68,7 +68,7 @@ void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Ve
} }
if (time < _frames[0]) { if (time < _frames[0]) {
if (pose == MixPose_Setup) { if (blend == MixBlend_Setup) {
drawOrder.clear(); drawOrder.clear();
drawOrder.ensureCapacity(slots.size()); drawOrder.ensureCapacity(slots.size());
for (int i = 0, n = static_cast<int>(slots.size()); i < n; ++i) { for (int i = 0, n = static_cast<int>(slots.size()); i < n; ++i) {

View File

@ -54,7 +54,7 @@ EventTimeline::~EventTimeline() {
} }
void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
if (pEvents == NULL) { if (pEvents == NULL) {
return; return;
} }
@ -69,7 +69,7 @@ void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
if (lastTime > time) { if (lastTime > time) {
// Fire events after last time for looped animations. // Fire events after last time for looped animations.
apply(skeleton, lastTime, std::numeric_limits<int>::max(), pEvents, alpha, pose, direction); apply(skeleton, lastTime, std::numeric_limits<int>::max(), pEvents, alpha, blend, direction);
lastTime = -1.0f; lastTime = -1.0f;
} else if (lastTime >= _frames[frameCount - 1]) { } else if (lastTime >= _frames[frameCount - 1]) {
// Last time is after last frame. // Last time is after last frame.

View File

@ -56,20 +56,19 @@ IkConstraintTimeline::IkConstraintTimeline(int frameCount) : CurveTimeline(frame
} }
void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
IkConstraint *constraintP = skeleton._ikConstraints[_ikConstraintIndex]; IkConstraint *constraintP = skeleton._ikConstraints[_ikConstraintIndex];
IkConstraint &constraint = *constraintP; IkConstraint &constraint = *constraintP;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
constraint._mix = constraint._data._mix; constraint._mix = constraint._data._mix;
constraint._bendDirection = constraint._data._bendDirection; constraint._bendDirection = constraint._data._bendDirection;
return; return;
case MixPose_Current: case MixBlend_First:
constraint._mix += (constraint._data._mix - constraint._mix) * alpha; constraint._mix += (constraint._data._mix - constraint._mix) * alpha;
constraint._bendDirection = constraint._data._bendDirection; constraint._bendDirection = constraint._data._bendDirection;
return; return;
case MixPose_CurrentLayered:
default: default:
return; return;
} }
@ -77,7 +76,7 @@ void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time,
if (time >= _frames[_frames.size() - ENTRIES]) { if (time >= _frames[_frames.size() - ENTRIES]) {
// Time is after last frame. // Time is after last frame.
if (pose == MixPose_Setup) { if (blend == MixBlend_Setup) {
constraint._mix = constraint._mix =
constraint._data._mix + (_frames[_frames.size() + PREV_MIX] - constraint._data._mix) * alpha; constraint._data._mix + (_frames[_frames.size() + PREV_MIX] - constraint._data._mix) * alpha;
constraint._bendDirection = direction == MixDirection_Out ? constraint._data._bendDirection constraint._bendDirection = direction == MixDirection_Out ? constraint._data._bendDirection
@ -99,7 +98,7 @@ void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time,
float percent = getCurvePercent(frame / ENTRIES - 1, float percent = getCurvePercent(frame / ENTRIES - 1,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
if (pose == MixPose_Setup) { if (blend == MixBlend_Setup) {
constraint._mix = constraint._mix =
constraint._data._mix + (mix + (_frames[frame + MIX] - mix) * percent - constraint._data._mix) * alpha; constraint._data._mix + (mix + (_frames[frame + MIX] - mix) * percent - constraint._data._mix) * alpha;
constraint._bendDirection = constraint._bendDirection =

View File

@ -58,20 +58,19 @@ PathConstraintMixTimeline::PathConstraintMixTimeline(int frameCount) : CurveTime
void void
PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex];
PathConstraint &constraint = *constraintP; PathConstraint &constraint = *constraintP;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
constraint._rotateMix = constraint._data._rotateMix; constraint._rotateMix = constraint._data._rotateMix;
constraint._translateMix = constraint._data._translateMix; constraint._translateMix = constraint._data._translateMix;
return; return;
case MixPose_Current: case MixBlend_First:
constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha; constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha;
constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha; constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha;
return; return;
case MixPose_CurrentLayered:
default: default:
return; return;
} }
@ -95,7 +94,7 @@ PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time,
translate += (_frames[frame + TRANSLATE] - translate) * percent; translate += (_frames[frame + TRANSLATE] - translate) * percent;
} }
if (pose == MixPose_Setup) { if (blend == MixBlend_Setup) {
constraint._rotateMix = constraint._data._rotateMix + (rotate - constraint._data._rotateMix) * alpha; constraint._rotateMix = constraint._data._rotateMix + (rotate - constraint._data._rotateMix) * alpha;
constraint._translateMix = constraint._translateMix =
constraint._data._translateMix + (translate - constraint._data._translateMix) * alpha; constraint._data._translateMix + (translate - constraint._data._translateMix) * alpha;

View File

@ -58,18 +58,17 @@ PathConstraintPositionTimeline::~PathConstraintPositionTimeline() {
} }
void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents,
float alpha, MixPose pose, MixDirection direction) { float alpha, MixBlend blend, MixDirection direction) {
PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex];
PathConstraint &constraint = *constraintP; PathConstraint &constraint = *constraintP;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
constraint._position = constraint._data._position; constraint._position = constraint._data._position;
return; return;
case MixPose_Current: case MixBlend_First:
constraint._position += (constraint._data._position - constraint._position) * alpha; constraint._position += (constraint._data._position - constraint._position) * alpha;
return; return;
case MixPose_CurrentLayered:
default: default:
return; return;
} }
@ -89,7 +88,7 @@ void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, f
position += (_frames[frame + VALUE] - position) * percent; position += (_frames[frame + VALUE] - position) * percent;
} }
if (pose == MixPose_Setup) { if (blend == MixBlend_Setup) {
constraint._position = constraint._data._position + (position - constraint._data._position) * alpha; constraint._position = constraint._data._position + (position - constraint._data._position) * alpha;
} else { } else {
constraint._position += (position - constraint._position) * alpha; constraint._position += (position - constraint._position) * alpha;

View File

@ -49,18 +49,17 @@ PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(int frameCount) : P
} }
void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents,
float alpha, MixPose pose, MixDirection direction) { float alpha, MixBlend blend, MixDirection direction) {
PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex];
PathConstraint &constraint = *constraintP; PathConstraint &constraint = *constraintP;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
constraint._spacing = constraint._data._spacing; constraint._spacing = constraint._data._spacing;
return; return;
case MixPose_Current: case MixBlend_First:
constraint._spacing += (constraint._data._spacing - constraint._spacing) * alpha; constraint._spacing += (constraint._data._spacing - constraint._spacing) * alpha;
return; return;
case MixPose_CurrentLayered:
default: default:
return; return;
} }
@ -81,7 +80,7 @@ void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, fl
spacing += (_frames[frame + VALUE] - spacing) * percent; spacing += (_frames[frame + VALUE] - spacing) * percent;
} }
if (pose == MixPose_Setup) { if (blend == MixBlend_Setup) {
constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha; constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha;
} else { } else {
constraint._spacing += (spacing - constraint._spacing) * alpha; constraint._spacing += (spacing - constraint._spacing) * alpha;

View File

@ -47,22 +47,21 @@ RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _bon
} }
void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
Bone *bone = skeleton.getBones()[_boneIndex]; Bone *bone = skeleton.getBones()[_boneIndex];
if (time < _frames[0]) { if (time < _frames[0]) {
switch (pose) { switch (blend) {
case MixPose_Setup: { case MixBlend_Setup: {
bone->_rotation = bone->_data._rotation; bone->_rotation = bone->_data._rotation;
break; break;
} }
case MixPose_Current: { case MixBlend_First: {
float rr = bone->_data._rotation - bone->_rotation; float r = bone->_data._rotation - bone->_rotation;
rr -= (16384 - (int) (16384.499999999996 - rr / 360)) * 360; bone->_rotation += (r - (16384 - (int) (16384.499999999996 - r / 360)) * 360) * alpha;
bone->_rotation += rr * alpha;
break; break;
} }
case MixPose_CurrentLayered: { default: {
// TODO? // TODO?
break; break;
} }
@ -72,15 +71,19 @@ void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto
} }
if (time >= _frames[_frames.size() - ENTRIES]) { if (time >= _frames[_frames.size() - ENTRIES]) {
// Time is after last frame. float r = _frames[_frames.size() + PREV_ROTATION];
if (pose == MixPose_Setup) { switch (blend) {
bone->_rotation = bone->_data._rotation + _frames[_frames.size() + PREV_ROTATION] * alpha; case MixBlend_Setup:
} else { bone->_rotation = bone->_data._rotation + r * alpha;
float rr = bone->_data._rotation + _frames[_frames.size() + PREV_ROTATION] - bone->_rotation; break;
rr -= (16384 - (int) (16384.499999999996 - rr / 360)) * 360; // Wrap within -180 and 180. case MixBlend_First:
bone->_rotation += rr * alpha; case MixBlend_Replace:
r += bone->_data._rotation - bone->_rotation;
r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
// Fall through.
case MixBlend_Add:
bone->_rotation += r * alpha;
} }
return; return;
} }
@ -90,18 +93,18 @@ void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto
float frameTime = _frames[frame]; float frameTime = _frames[frame];
float percent = getCurvePercent((frame >> 1) - 1, float percent = getCurvePercent((frame >> 1) - 1,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
float r = _frames[frame + ROTATION] - prevRotation; float r = _frames[frame + ROTATION] - prevRotation;
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; r = prevRotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * percent;
r = prevRotation + r * percent; switch (blend) {
case MixBlend_Setup:
if (pose == MixPose_Setup) { bone->_rotation = bone->_data._rotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha;
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; break;
bone->_rotation = bone->_data._rotation + r * alpha; case MixBlend_First:
} else { case MixBlend_Replace:
r = bone->_data._rotation + r - bone->_rotation; r += bone->_data._rotation - bone->_rotation;
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; // Fall through.
bone->_rotation += r * alpha; case MixBlend_Add:
bone->_rotation += (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha;
} }
} }

View File

@ -46,24 +46,22 @@ ScaleTimeline::ScaleTimeline(int frameCount) : TranslateTimeline(frameCount) {
} }
void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
Bone *boneP = skeleton._bones[_boneIndex]; Bone *boneP = skeleton._bones[_boneIndex];
Bone &bone = *boneP; Bone &bone = *boneP;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
bone._scaleX = bone._data._scaleX; bone._scaleX = bone._data._scaleX;
bone._scaleY = bone._data._scaleY; bone._scaleY = bone._data._scaleY;
return; return;
case MixPose_Current: case MixBlend_First:
bone._scaleX += (bone._data._scaleX - bone._scaleX) * alpha; bone._scaleX += (bone._data._scaleX - bone._scaleX) * alpha;
bone._scaleY += (bone._data._scaleY - bone._scaleY) * alpha; bone._scaleY += (bone._data._scaleY - bone._scaleY) * alpha;
return; default: {}
case MixPose_CurrentLayered:
default:
return;
} }
return;
} }
float x, y; float x, y;
@ -85,27 +83,59 @@ void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
} }
if (alpha == 1) { if (alpha == 1) {
bone._scaleX = x; if (blend == MixBlend_Add) {
bone._scaleY = y; bone._scaleX += x - bone._data._scaleX;
bone._scaleY += y - bone._data._scaleY;
} else {
bone._scaleX = x;
bone._scaleY = y;
}
} else { } 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. // Mixing out uses sign of setup or current pose, else use sign of key.
float bx, by;
if (direction == MixDirection_Out) { if (direction == MixDirection_Out) {
x = (x >= 0 ? x : -x) * (bx >= 0 ? 1 : -1); switch (blend) {
y = (y >= 0 ? y : -y) * (by >= 0 ? 1 : -1); case MixBlend_Setup:
bx = bone._data._scaleX;
by = bone._data._scaleY;
bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bx = bone._scaleX;
by = bone._scaleY;
bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
break;
case MixBlend_Add:
bx = bone._scaleX;
by = bone._scaleY;
bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bone._data._scaleX) * alpha;
bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - bone._data._scaleY) * alpha;
}
} else { } else {
bx = (bx >= 0 ? bx : -bx) * (x >= 0 ? 1 : -1); switch (blend) {
by = (by >= 0 ? by : -by) * (y >= 0 ? 1 : -1); case MixBlend_Setup:
bx = MathUtil::abs(bone._data._scaleX) * MathUtil::sign(x);
by = MathUtil::abs(bone._data._scaleY) * MathUtil::sign(y);
bone._scaleX = bx + (x - bx) * alpha;
bone._scaleY = by + (y - by) * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bx = MathUtil::abs(bone._scaleX) * MathUtil::sign(x);
by = MathUtil::abs(bone._scaleY) * MathUtil::sign(y);
bone._scaleX = bx + (x - bx) * alpha;
bone._scaleY = by + (y - by) * alpha;
break;
case MixBlend_Add:
bx = MathUtil::sign(x);
by = MathUtil::sign(y);
bone._scaleX = MathUtil::abs(bone._scaleX) * bx + (x - MathUtil::abs(bone._data._scaleX) * bx) * alpha;
bone._scaleY = MathUtil::abs(bone._scaleY) * by + (y - MathUtil::abs(bone._data._scaleY) * by) * alpha;
}
} }
bone._scaleX = bx + (x - bx) * alpha;
bone._scaleY = by + (y - by) * alpha;
} }
} }

View File

@ -46,24 +46,22 @@ ShearTimeline::ShearTimeline(int frameCount) : TranslateTimeline(frameCount) {
} }
void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
Bone *boneP = skeleton._bones[_boneIndex]; Bone *boneP = skeleton._bones[_boneIndex];
Bone &bone = *boneP; Bone &bone = *boneP;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
bone._shearX = bone._data._shearX; bone._shearX = bone._data._shearX;
bone._shearY = bone._data._shearY; bone._shearY = bone._data._shearY;
return; return;
case MixPose_Current: case MixBlend_First:
bone._shearX += (bone._data._shearX - bone._shearX) * alpha; bone._shearX += (bone._data._shearX - bone._shearX) * alpha;
bone._shearY += (bone._data._shearY - bone._shearY) * alpha; bone._shearY += (bone._data._shearY - bone._shearY) * alpha;
return; default: {}
case MixPose_CurrentLayered:
default:
return;
} }
return;
} }
float x, y; float x, y;
@ -84,12 +82,19 @@ void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
y = y + (_frames[frame + Y] - y) * percent; y = y + (_frames[frame + Y] - y) * percent;
} }
if (pose == MixPose_Setup) { switch (blend) {
bone._shearX = bone._data._shearX + x * alpha; case MixBlend_Setup:
bone._shearY = bone._data._shearY + y * alpha; bone._shearX = bone._data._shearX + x * alpha;
} else { bone._shearY = bone._data._shearY + y * alpha;
bone._shearX += (bone._data._shearX + x - bone._shearX) * alpha; break;
bone._shearY += (bone._data._shearY + y - bone._shearY) * alpha; case MixBlend_First:
case MixBlend_Replace:
bone._shearX += (bone._data._shearX + x - bone._shearX) * alpha;
bone._shearY += (bone._data._shearY + y - bone._shearY) * alpha;
break;
case MixBlend_Add:
bone._shearX += x * alpha;
bone._shearY += y * alpha;
} }
} }

View File

@ -61,25 +61,24 @@ TransformConstraintTimeline::TransformConstraintTimeline(int frameCount) : Curve
} }
void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents,
float alpha, MixPose pose, MixDirection direction) { float alpha, MixBlend blend, MixDirection direction) {
TransformConstraint *constraintP = skeleton._transformConstraints[_transformConstraintIndex]; TransformConstraint *constraintP = skeleton._transformConstraints[_transformConstraintIndex];
TransformConstraint &constraint = *constraintP; TransformConstraint &constraint = *constraintP;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
constraint._rotateMix = constraint._data._rotateMix; constraint._rotateMix = constraint._data._rotateMix;
constraint._translateMix = constraint._data._translateMix; constraint._translateMix = constraint._data._translateMix;
constraint._scaleMix = constraint._data._scaleMix; constraint._scaleMix = constraint._data._scaleMix;
constraint._shearMix = constraint._data._shearMix; constraint._shearMix = constraint._data._shearMix;
return; return;
case MixPose_Current: case MixBlend_First:
constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha; constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha;
constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha; constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha;
constraint._scaleMix += (constraint._data._scaleMix - constraint._scaleMix) * alpha; constraint._scaleMix += (constraint._data._scaleMix - constraint._scaleMix) * alpha;
constraint._shearMix += (constraint._data._shearMix - constraint._shearMix) * alpha; constraint._shearMix += (constraint._data._shearMix - constraint._shearMix) * alpha;
return; return;
case MixPose_CurrentLayered:
default: default:
return; return;
} }
@ -110,7 +109,7 @@ void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, floa
shear += (_frames[frame + SHEAR] - shear) * percent; shear += (_frames[frame + SHEAR] - shear) * percent;
} }
if (pose == MixPose_Setup) { if (blend == MixBlend_Setup) {
TransformConstraintData &data = constraint._data; TransformConstraintData &data = constraint._data;
constraint._rotateMix = data._rotateMix + (rotate - data._rotateMix) * alpha; constraint._rotateMix = data._rotateMix + (rotate - data._rotateMix) * alpha;
constraint._translateMix = data._translateMix + (translate - data._translateMix) * alpha; constraint._translateMix = data._translateMix + (translate - data._translateMix) * alpha;

View File

@ -58,24 +58,22 @@ TranslateTimeline::~TranslateTimeline() {
} }
void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
Bone *boneP = skeleton._bones[_boneIndex]; Bone *boneP = skeleton._bones[_boneIndex];
Bone &bone = *boneP; Bone &bone = *boneP;
if (time < _frames[0]) { if (time < _frames[0]) {
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
bone._x = bone._data._x; bone._x = bone._data._x;
bone._y = bone._data._y; bone._y = bone._data._y;
return; return;
case MixPose_Current: case MixBlend_First:
bone._x += (bone._data._x - bone._x) * alpha; bone._x += (bone._data._x - bone._x) * alpha;
bone._y += (bone._data._y - bone._y) * alpha; bone._y += (bone._data._y - bone._y) * alpha;
return; default: {}
case MixPose_CurrentLayered:
default:
return;
} }
return;
} }
float x, y; float x, y;
@ -96,12 +94,19 @@ void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Ve
y += (_frames[frame + Y] - y) * percent; y += (_frames[frame + Y] - y) * percent;
} }
if (pose == MixPose_Setup) { switch (blend) {
bone._x = bone._data._x + x * alpha; case MixBlend_Setup:
bone._y = bone._data._y + y * alpha; bone._x = bone._data._x + x * alpha;
} else { bone._y = bone._data._y + y * alpha;
bone._x += (bone._data._x + x - bone._x) * alpha; break;
bone._y += (bone._data._y + y - bone._y) * alpha; case MixBlend_First:
case MixBlend_Replace:
bone._x += (bone._data._x + x - bone._x) * alpha;
bone._y += (bone._data._y + y - bone._y) * alpha;
break;
case MixBlend_Add:
bone._x += x * alpha;
bone._y += y * alpha;
} }
} }

View File

@ -65,18 +65,18 @@ TwoColorTimeline::TwoColorTimeline(int frameCount) : CurveTimeline(frameCount),
} }
void TwoColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, void TwoColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixPose pose, MixDirection direction) { MixBlend blend, MixDirection direction) {
Slot *slotP = skeleton._slots[_slotIndex]; Slot *slotP = skeleton._slots[_slotIndex];
Slot &slot = *slotP; Slot &slot = *slotP;
if (time < _frames[0]) { if (time < _frames[0]) {
// Time is before first frame. // Time is before first frame.
switch (pose) { switch (blend) {
case MixPose_Setup: case MixBlend_Setup:
slot.getColor().set(slot.getData().getColor()); slot.getColor().set(slot.getData().getColor());
slot.getDarkColor().set(slot.getData().getDarkColor()); slot.getDarkColor().set(slot.getData().getDarkColor());
return; return;
case MixPose_Current: { case MixBlend_First: {
Color &color = slot.getColor(); Color &color = slot.getColor();
color.r += (color.r - slot._data.getColor().r) * alpha; color.r += (color.r - slot._data.getColor().r) * alpha;
color.g += (color.g - slot._data.getColor().g) * alpha; color.g += (color.g - slot._data.getColor().g) * alpha;
@ -89,7 +89,6 @@ void TwoColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vec
darkColor.b += (darkColor.b - slot._data.getDarkColor().b) * alpha; darkColor.b += (darkColor.b - slot._data.getDarkColor().b) * alpha;
return; return;
} }
case MixPose_CurrentLayered:
default: default:
return; return;
} }
@ -131,48 +130,19 @@ void TwoColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vec
if (alpha == 1) { if (alpha == 1) {
Color &color = slot.getColor(); Color &color = slot.getColor();
color.r = r; color.set(r, g, b, a);
color.g = g;
color.b = b;
color.a = a;
Color &darkColor = slot.getDarkColor(); Color &darkColor = slot.getDarkColor();
darkColor.r = r2; darkColor.set(r2, g2, b2, 1);
darkColor.g = g2;
darkColor.b = b2;
} else { } else {
float br, bg, bb, ba, br2, bg2, bb2; Color &light = slot._color;
if (pose == MixPose_Setup) { Color &dark = slot._darkColor;
br = slot._data.getColor().r; if (blend == MixBlend_Setup) {
bg = slot._data.getColor().g; light.set(slot._data._color);
bb = slot._data.getColor().b; dark.set(slot._data._darkColor);
ba = slot._data.getColor().a;
br2 = slot._data.getDarkColor().r;
bg2 = slot._data.getDarkColor().g;
bb2 = slot._data.getDarkColor().b;
} else {
Color &color = slot.getColor();
br = color.r;
bg = color.g;
bb = color.b;
ba = color.a;
Color &darkColor = slot.getDarkColor();
br2 = darkColor.r;
bg2 = darkColor.g;
bb2 = darkColor.b;
} }
light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);
Color &color = slot.getColor(); dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0);
color.r = br + ((r - br) * alpha);
color.g = bg + ((g - bg) * alpha);
color.b = bb + ((b - bb) * alpha);
color.a = ba + ((a - ba) * alpha);
Color &darkColor = slot.getDarkColor();
darkColor.r = br2 + ((r2 - br2) * alpha);
darkColor.g = bg2 + ((g2 - bg2) * alpha);
darkColor.b = bb2 + ((b2 - bb2) * alpha);
} }
} }

View File

@ -347,19 +347,22 @@ void coin (SkeletonData* skeletonData, Atlas* atlas) {
skeleton->updateWorldTransform(); skeleton->updateWorldTransform();
drawable->state->setAnimation(0, "rotate", true); drawable->state->setAnimation(0, "rotate", true);
drawable->update(0.1); drawable->update(1);
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - vine"); sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - coin");
window.setFramerateLimit(60); window.setFramerateLimit(60);
sf::Event event; sf::Event event;
sf::Clock deltaClock; sf::Clock deltaClock;
float swirlTime = 0; float swirlTime = 0;
while (window.isOpen()) { while (window.isOpen()) {
while (window.pollEvent(event)) float delta = 0;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) window.close(); if (event.type == sf::Event::Closed) window.close();
if (event.type == sf::Event::MouseButtonPressed) delta += 0.1f;
}
float delta = deltaClock.getElapsedTime().asSeconds(); // float delta = deltaClock.getElapsedTime().asSeconds();
deltaClock.restart(); // deltaClock.restart();
drawable->update(delta); drawable->update(delta);
@ -387,13 +390,13 @@ void owl (SkeletonData* skeletonData, Atlas* atlas) {
TrackEntry* down = drawable->state->setAnimation(5, "down", true); TrackEntry* down = drawable->state->setAnimation(5, "down", true);
left->setAlpha(0); left->setAlpha(0);
// BOZO left->setMixBlend(SP_MIX_BLEND_ADD); left->setMixBlend(MixBlend_Add);
right->setAlpha(0); right->setAlpha(0);
// BOZO right->mixBlend = SP_MIX_BLEND_ADD; right->setMixBlend(MixBlend_Add);
up->setAlpha(0); up->setAlpha(0);
// BOZO up->mixBlend = SP_MIX_BLEND_ADD; up->setMixBlend(MixBlend_Add);
down->setAlpha(0); down->setAlpha(0);
// BOZO down->mixBlend = SP_MIX_BLEND_ADD; down->setMixBlend(MixBlend_Add);
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - owl"); sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - owl");
window.setFramerateLimit(60); window.setFramerateLimit(60);
@ -452,10 +455,10 @@ int main () {
DebugExtension dbgExtension; DebugExtension dbgExtension;
SpineExtension::setInstance(&dbgExtension); SpineExtension::setInstance(&dbgExtension);
testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor.atlas", 0.5f); // testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor.atlas", 0.5f);
testcase(test, "data/tank-pro.json", "data/tank-pro.skel", "data/tank.atlas", 1.0f); // testcase(test, "data/tank-pro.json", "data/tank-pro.skel", "data/tank.atlas", 1.0f);
testcase(spineboy, "data/spineboy-ess.json", "data/spineboy-ess.skel", "data/spineboy.atlas", 0.6f); // testcase(spineboy, "data/spineboy-ess.json", "data/spineboy-ess.skel", "data/spineboy.atlas", 0.6f);
testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl.atlas", 0.5f); // testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl.atlas", 0.5f);
testcase(coin, "data/coin-pro.json", "data/coin-pro.skel", "data/coin.atlas", 0.5f); testcase(coin, "data/coin-pro.json", "data/coin-pro.skel", "data/coin.atlas", 0.5f);
testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine.atlas", 0.5f); testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine.atlas", 0.5f);
testcase(tank, "data/tank-pro.json", "data/tank-pro.skel", "data/tank.atlas", 0.2f); testcase(tank, "data/tank-pro.json", "data/tank-pro.skel", "data/tank.atlas", 0.2f);