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
#include <spine/Vector.h>
#include <spine/MixPose.h>
#include <spine/MixBlend.h>
#include <spine/MixDirection.h>
#include <spine/SpineObject.h>
#include <spine/String.h>
@ -89,7 +89,7 @@ public:
/// Applies all the animation's timelines to the specified skeleton.
/// 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,
MixPose pose, MixDirection direction);
MixBlend blend, MixDirection direction);
const String &getName();

View File

@ -33,7 +33,7 @@
#include <spine/Vector.h>
#include <spine/Pool.h>
#include <spine/MixPose.h>
#include <spine/MixBlend.h>
#include <spine/SpineObject.h>
#include <spine/String.h>
@ -196,6 +196,10 @@ namespace Spine {
///
float getMixDuration();
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
@ -227,6 +231,7 @@ namespace Spine {
float _animationStart, _animationEnd, _animationLast, _nextAnimationLast;
float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale;
float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha;
MixBlend _mixBlend;
Vector<int> _timelineData;
Vector<TrackEntry*> _timelineDipMix;
Vector<float> _timelinesRotation;
@ -400,12 +405,12 @@ namespace Spine {
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.
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);

View File

@ -34,7 +34,7 @@
#include <spine/Timeline.h>
#include <spine/SpineObject.h>
#include <spine/Vector.h>
#include <spine/MixPose.h>
#include <spine/MixBlend.h>
#include <spine/MixDirection.h>
#include <spine/String.h>
@ -51,7 +51,7 @@ namespace Spine {
public:
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();

View File

@ -47,7 +47,7 @@ public:
explicit ColorTimeline(int frameCount);
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);
virtual int getPropertyId();

View File

@ -44,7 +44,7 @@ namespace Spine {
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;

View File

@ -45,7 +45,7 @@ namespace Spine {
public:
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();

View File

@ -43,7 +43,7 @@ namespace Spine {
public:
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();

View File

@ -45,7 +45,7 @@ namespace Spine {
~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();

View File

@ -45,7 +45,7 @@ namespace Spine {
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();

View File

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

View File

@ -45,7 +45,7 @@ namespace Spine {
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();

View File

@ -47,7 +47,7 @@ namespace Spine {
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();

View File

@ -43,7 +43,7 @@ namespace Spine {
public:
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();
};

View File

@ -46,7 +46,7 @@ namespace Spine {
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();

View File

@ -43,7 +43,7 @@ namespace Spine {
public:
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();
};

View File

@ -43,7 +43,7 @@ namespace Spine {
public:
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();
};

View File

@ -33,7 +33,7 @@
#include <spine/RTTI.h>
#include <spine/Vector.h>
#include <spine/MixPose.h>
#include <spine/MixBlend.h>
#include <spine/MixDirection.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
/// 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).
/// @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.
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;
virtual int getPropertyId() = 0;

View File

@ -45,7 +45,7 @@ namespace Spine {
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();

View File

@ -50,7 +50,7 @@ namespace Spine {
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();

View File

@ -45,7 +45,7 @@ namespace Spine {
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();

View File

@ -65,7 +65,7 @@
#include <spine/MathUtil.h>
#include <spine/MeshAttachment.h>
#include <spine/MixDirection.h>
#include <spine/MixPose.h>
#include <spine/MixBlend.h>
#include <spine/PathAttachment.h>
#include <spine/PathConstraint.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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
if (loop && _duration != 0) {
time = MathUtil::fmod(time, _duration);
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) {
_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),
_animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(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) {
}
@ -139,6 +139,10 @@ void TrackEntry::setMixDuration(float inValue) { _mixDuration = inValue; }
TrackEntry *TrackEntry::getMixingFrom() { return _mixingFrom; }
void TrackEntry::setMixBlend(MixBlend blend) { _mixBlend = blend; }
float TrackEntry::getMixBlend() { return _mixBlend; }
void TrackEntry::resetRotationDirections() {
_timelinesRotation.clear();
}
@ -419,12 +423,12 @@ bool AnimationState::apply(Skeleton &skeleton) {
TrackEntry &current = *currentP;
applied = true;
MixPose currentPose = i == 0 ? MixPose_Current : MixPose_CurrentLayered;
MixBlend blend = i == 0 ? MixBlend_First : current._mixBlend;
// apply mixing from entries first.
float mix = current._alpha;
if (current._mixingFrom != NULL) {
mix *= applyMixingFrom(currentP, skeleton, currentPose);
mix *= applyMixingFrom(currentP, skeleton, blend);
} else if (current._trackTime >= current._trackEnd && current._next == NULL) {
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();
int timelineCount = static_cast<int>(current._animation->_timelines.size());
Vector<Timeline *> &timelines = current._animation->_timelines;
if (mix == 1) {
if (mix == 1 || blend == MixBlend_Add) {
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);
}
} else {
@ -451,7 +455,7 @@ bool AnimationState::apply(Skeleton &skeleton) {
Timeline *timeline = timelines[ii];
assert(timeline);
MixPose pose = timelineData[ii] >= AnimationState::First ? MixPose_Setup : currentPose;
MixBlend timelineBlend = timelineData[ii] == AnimationState::Subsequent ? blend : MixBlend_Setup;
RotateTimeline *rotateTimeline = NULL;
if (timeline->getRTTI().isExactly(RotateTimeline::rtti)) {
@ -459,10 +463,10 @@ bool AnimationState::apply(Skeleton &skeleton) {
}
if (rotateTimeline != NULL) {
applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1,
applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1,
firstFrame);
} 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,
MixPose pose, Vector<float> &timelinesRotation, int i, bool firstFrame) {
MixBlend blend, Vector<float> &timelinesRotation, int i, bool firstFrame) {
if (firstFrame) {
timelinesRotation[i] = 0;
}
if (alpha == 1) {
rotateTimeline->apply(skeleton, 0, time, NULL, 1, pose, MixDirection_In);
rotateTimeline->apply(skeleton, 0, time, NULL, 1, blend, MixDirection_In);
return;
}
Bone *bone = skeleton._bones[rotateTimeline->_boneIndex];
Vector<float>& frames = rotateTimeline->_frames;
if (time < frames[0]) {
if (pose == MixPose_Setup) {
if (blend == MixBlend_Setup) {
bone->_rotation = bone->_data._rotation;
}
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.
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;
if (diff == 0) {
total = timelinesRotation[i];
@ -767,22 +771,23 @@ bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) {
return false;
}
float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixPose currentPose) {
float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend blend) {
TrackEntry *from = to->_mixingFrom;
if (from->_mixingFrom != NULL) {
applyMixingFrom(from, skeleton, currentPose);
applyMixingFrom(from, skeleton, blend);
}
float mix;
if (to->_mixDuration == 0) {
// Single frame mix to undo mixingFrom changes.
mix = 1;
currentPose = MixPose_Setup;
if (blend == MixBlend_First) blend = MixBlend_Setup;
} else {
mix = to->_mixTime / to->_mixDuration;
if (mix > 1) {
mix = 1;
}
if (blend != MixBlend_First) blend = from->_mixBlend;
}
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();
Vector<Timeline *> &timelines = from->_animation->_timelines;
int timelineCount = static_cast<int>(timelines.size());
Vector<int> &timelineData = from->_timelineData;
Vector<TrackEntry *> &timelineDipMix = from->_timelineDipMix;
float alphaDip = from->_alpha * to->_interruptAlpha, alphaMix = alphaDip * (1 - mix);
bool firstFrame = from->_timelinesRotation.size() == 0;
if (firstFrame) {
from->_timelinesRotation.setSize(timelines.size() << 1, 0);
}
if (blend == MixBlend_Add) {
for (int i = 0; i < timelineCount; i++)
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;
MixPose pose;
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);
bool firstFrame = from->_timelinesRotation.size() == 0;
if (firstFrame) {
from->_timelinesRotation.setSize(timelines.size() << 1, 0);
}
if (rotateTimeline != NULL) {
applyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1,
firstFrame);
} else {
timeline->apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection_Out);
Vector<float> &timelinesRotation = from->_timelinesRotation;
from->_totalAlpha = 0;
for (int i = 0; i < timelineCount; i++) {
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) {
TrackEntry *entry = _tracks[i];
if (entry != NULL) {
if (entry != NULL && entry->_mixBlend != MixBlend_Add) {
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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
assert(_slotIndex < skeleton._slots.size());
String *attachmentName;
Slot *slotP = skeleton._slots[_slotIndex];
Slot &slot = *slotP;
if (direction == MixDirection_Out && pose == MixPose_Setup) {
if (direction == MixDirection_Out && blend == MixBlend_Setup) {
attachmentName = &slot._data._attachmentName;
slot._attachment = attachmentName->length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName);
return;
@ -68,7 +68,7 @@ void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, V
if (time < _frames[0]) {
// Time is before first frame.
if (pose == MixPose_Setup) {
if (blend == MixBlend_Setup || blend == MixBlend_First) {
attachmentName = &slot._data._attachmentName;
slot._attachment =
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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
Slot *slotP = skeleton._slots[_slotIndex];
Slot &slot = *slotP;
if (time < _frames[0]) {
SlotData &slotData = slot._data;
switch (pose) {
case MixPose_Setup:
slot.getColor().set(slotData.getColor());
switch (blend) {
case MixBlend_Setup:
slot._color.set(slot._data._color);
return;
case MixPose_Current: {
Color &color = slot.getColor();
Color &setup = slot.getData().getColor();
color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha,
(setup.b - color.b) * alpha,
case MixBlend_First: {
Color color = slot._color, setup = slot._data._color;
color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,
(setup.a - color.a) * alpha);
return;
}
case MixPose_CurrentLayered:
default:
return;
default: ;
}
return;
}
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);
} else {
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);
}
}

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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
Slot *slotP = skeleton._slots[_slotIndex];
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;
}
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slot._attachment);
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (!vertexAttachment->applyDeform(_attachment)) {
return;
}
Vector<float> &vertices = slot._attachmentVertices;
if (vertices.size() == 0) {
alpha = 1;
Vector<float> &verticesArray = slot._attachmentVertices;
if (verticesArray.size() == 0) {
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]) {
switch (pose) {
case MixPose_Setup:
vertices.clear();
return;
case MixPose_Current:
if (alpha == 1) {
vertices.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:
switch (blend) {
case MixBlend_Setup:
verticesArray.clear();
return;
case MixBlend_First:
if (alpha == 1) {
verticesArray.clear();
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.
vertices.setSize(vertexCount, 0);
verticesArray.setSize(vertexCount, 0);
Vector<float> &vertices = verticesArray;
if (time >= _frames[_frames.size() - 1]) {
// Time is after last frame.
Vector<float> &lastVertices = _frameVertices[_frames.size() - 1];
if (time >= frames[frames.size() - 1]) { // Time is after last frame.
Vector<float> &lastVertices = frameVertices[frames.size() - 1];
if (alpha == 1) {
// Vertex positions or deform offsets, no alpha.
vertices.clear();
for (int i = 0; i < vertexCount; ++i) {
float vertex = lastVertices[i];
vertices.add(vertex);
}
} else if (pose == MixPose_Setup) {
if (vertexAttachment->_bones.size() == 0) {
// Unweighted vertex positions, with alpha.
Vector<float> &setupVertices = vertexAttachment->_vertices;
for (int i = 0; i < vertexCount; i++) {
float setup = setupVertices[i];
vertices[i] = setup + (lastVertices[i] - setup) * alpha;
if (blend == MixBlend_Add) {
VertexAttachment *vertexAttachment = static_cast<VertexAttachment*>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, no alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices();
for (int i = 0; i < vertexCount; i++)
vertices[i] += lastVertices[i] - setupVertices[i];
} else {
// Weighted deform offsets, no alpha.
for (int i = 0; i < vertexCount; i++)
vertices[i] += lastVertices[i];
}
} else {
// Weighted deform offsets, with alpha.
for (int i = 0; i < vertexCount; ++i) {
vertices[i] = lastVertices[i] * alpha;
}
// Vertex positions or deform offsets, no alpha.
memcpy(vertices.buffer(), lastVertices.buffer(), vertexCount * sizeof(float));
}
} else {
// Vertex positions or deform offsets, with alpha.
for (int i = 0; i < vertexCount; ++i) {
vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
switch (blend) {
case MixBlend_Setup: {
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, with alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices();
for (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;
}
// Interpolate between the previous frame and the current frame.
int frame = Animation::binarySearch(_frames, time);
Vector<float> &prevVertices = _frameVertices[frame - 1];
Vector<float> &nextVertices = _frameVertices[frame];
float frameTime = _frames[frame];
float percent = getCurvePercent(frame - 1, 1 - (time - frameTime) / (_frames[frame - 1] - frameTime));
int frame = Animation::binarySearch(frames, time);
Vector<float> &prevVertices = frameVertices[frame - 1];
Vector<float> &nextVertices = frameVertices[frame];
float frameTime = frames[frame];
float percent = getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime));
if (alpha == 1) {
// Vertex positions or deform offsets, no alpha.
for (int i = 0; i < vertexCount; ++i) {
float prev = prevVertices[i];
vertices[i] = prev + (nextVertices[i] - prev) * percent;
}
} else if (pose == MixPose_Setup) {
if (vertexAttachment->_bones.size() == 0) {
// Unweighted vertex positions, with alpha.
Vector<float> &setupVertices = vertexAttachment->_vertices;
for (int i = 0; i < vertexCount; ++i) {
float prev = prevVertices[i], setup = setupVertices[i];
vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
if (blend == MixBlend_Add) {
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, no alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices();
for (int i = 0; i < vertexCount; i++) {
float prev = prevVertices[i];
vertices[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i];
}
} else {
// Weighted deform offsets, no alpha.
for (int i = 0; i < vertexCount; i++) {
float prev = prevVertices[i];
vertices[i] += prev + (nextVertices[i] - prev) * percent;
}
}
} else {
// Weighted deform offsets, with alpha.
for (int i = 0; i < vertexCount; ++i) {
// Vertex positions or deform offsets, no alpha.
for (int i = 0; i < vertexCount; i++) {
float prev = prevVertices[i];
vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
vertices[i] = prev + (nextVertices[i] - prev) * percent;
}
}
} else {
// 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;
switch (blend) {
case MixBlend_Setup: {
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
if (vertexAttachment->getBones().size() == 0) {
// Unweighted vertex positions, with alpha.
Vector<float> &setupVertices = vertexAttachment->getVertices();
for (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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
Vector<Slot *> &drawOrder = skeleton._drawOrder;
Vector<Slot *> &slots = skeleton._slots;
if (direction == MixDirection_Out && pose == MixPose_Setup) {
if (direction == MixDirection_Out && blend == MixBlend_Setup) {
drawOrder.clear();
drawOrder.ensureCapacity(slots.size());
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 (pose == MixPose_Setup) {
if (blend == MixBlend_Setup) {
drawOrder.clear();
drawOrder.ensureCapacity(slots.size());
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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
if (pEvents == NULL) {
return;
}
@ -69,7 +69,7 @@ void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
if (lastTime > time) {
// 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;
} else if (lastTime >= _frames[frameCount - 1]) {
// 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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
IkConstraint *constraintP = skeleton._ikConstraints[_ikConstraintIndex];
IkConstraint &constraint = *constraintP;
if (time < _frames[0]) {
switch (pose) {
case MixPose_Setup:
switch (blend) {
case MixBlend_Setup:
constraint._mix = constraint._data._mix;
constraint._bendDirection = constraint._data._bendDirection;
return;
case MixPose_Current:
case MixBlend_First:
constraint._mix += (constraint._data._mix - constraint._mix) * alpha;
constraint._bendDirection = constraint._data._bendDirection;
return;
case MixPose_CurrentLayered:
default:
return;
}
@ -77,7 +76,7 @@ void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time,
if (time >= _frames[_frames.size() - ENTRIES]) {
// Time is after last frame.
if (pose == MixPose_Setup) {
if (blend == MixBlend_Setup) {
constraint._mix =
constraint._data._mix + (_frames[_frames.size() + PREV_MIX] - constraint._data._mix) * alpha;
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,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
if (pose == MixPose_Setup) {
if (blend == MixBlend_Setup) {
constraint._mix =
constraint._data._mix + (mix + (_frames[frame + MIX] - mix) * percent - constraint._data._mix) * alpha;
constraint._bendDirection =

View File

@ -58,20 +58,19 @@ PathConstraintMixTimeline::PathConstraintMixTimeline(int frameCount) : CurveTime
void
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 &constraint = *constraintP;
if (time < _frames[0]) {
switch (pose) {
case MixPose_Setup:
switch (blend) {
case MixBlend_Setup:
constraint._rotateMix = constraint._data._rotateMix;
constraint._translateMix = constraint._data._translateMix;
return;
case MixPose_Current:
case MixBlend_First:
constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha;
constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
}
@ -95,7 +94,7 @@ PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time,
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._translateMix =
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,
float alpha, MixPose pose, MixDirection direction) {
float alpha, MixBlend blend, MixDirection direction) {
PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex];
PathConstraint &constraint = *constraintP;
if (time < _frames[0]) {
switch (pose) {
case MixPose_Setup:
switch (blend) {
case MixBlend_Setup:
constraint._position = constraint._data._position;
return;
case MixPose_Current:
case MixBlend_First:
constraint._position += (constraint._data._position - constraint._position) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
}
@ -89,7 +88,7 @@ void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, f
position += (_frames[frame + VALUE] - position) * percent;
}
if (pose == MixPose_Setup) {
if (blend == MixBlend_Setup) {
constraint._position = constraint._data._position + (position - constraint._data._position) * alpha;
} else {
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,
float alpha, MixPose pose, MixDirection direction) {
float alpha, MixBlend blend, MixDirection direction) {
PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex];
PathConstraint &constraint = *constraintP;
if (time < _frames[0]) {
switch (pose) {
case MixPose_Setup:
switch (blend) {
case MixBlend_Setup:
constraint._spacing = constraint._data._spacing;
return;
case MixPose_Current:
case MixBlend_First:
constraint._spacing += (constraint._data._spacing - constraint._spacing) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
}
@ -81,7 +80,7 @@ void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, fl
spacing += (_frames[frame + VALUE] - spacing) * percent;
}
if (pose == MixPose_Setup) {
if (blend == MixBlend_Setup) {
constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha;
} else {
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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
Bone *bone = skeleton.getBones()[_boneIndex];
if (time < _frames[0]) {
switch (pose) {
case MixPose_Setup: {
switch (blend) {
case MixBlend_Setup: {
bone->_rotation = bone->_data._rotation;
break;
}
case MixPose_Current: {
float rr = bone->_data._rotation - bone->_rotation;
rr -= (16384 - (int) (16384.499999999996 - rr / 360)) * 360;
bone->_rotation += rr * alpha;
case MixBlend_First: {
float r = bone->_data._rotation - bone->_rotation;
bone->_rotation += (r - (16384 - (int) (16384.499999999996 - r / 360)) * 360) * alpha;
break;
}
case MixPose_CurrentLayered: {
default: {
// TODO?
break;
}
@ -72,15 +71,19 @@ void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto
}
if (time >= _frames[_frames.size() - ENTRIES]) {
// Time is after last frame.
if (pose == MixPose_Setup) {
bone->_rotation = bone->_data._rotation + _frames[_frames.size() + PREV_ROTATION] * alpha;
} else {
float rr = bone->_data._rotation + _frames[_frames.size() + PREV_ROTATION] - bone->_rotation;
rr -= (16384 - (int) (16384.499999999996 - rr / 360)) * 360; // Wrap within -180 and 180.
bone->_rotation += rr * alpha;
float r = _frames[_frames.size() + PREV_ROTATION];
switch (blend) {
case MixBlend_Setup:
bone->_rotation = bone->_data._rotation + r * alpha;
break;
case MixBlend_First:
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;
}
@ -90,18 +93,18 @@ void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto
float frameTime = _frames[frame];
float percent = getCurvePercent((frame >> 1) - 1,
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
float r = _frames[frame + ROTATION] - prevRotation;
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360;
r = prevRotation + r * percent;
if (pose == MixPose_Setup) {
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360;
bone->_rotation = bone->_data._rotation + r * alpha;
} else {
r = bone->_data._rotation + r - bone->_rotation;
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360;
bone->_rotation += r * alpha;
r = prevRotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * percent;
switch (blend) {
case MixBlend_Setup:
bone->_rotation = bone->_data._rotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
r += bone->_data._rotation - bone->_rotation;
// Fall through.
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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
Bone *boneP = skeleton._bones[_boneIndex];
Bone &bone = *boneP;
if (time < _frames[0]) {
switch (pose) {
case MixPose_Setup:
switch (blend) {
case MixBlend_Setup:
bone._scaleX = bone._data._scaleX;
bone._scaleY = bone._data._scaleY;
return;
case MixPose_Current:
case MixBlend_First:
bone._scaleX += (bone._data._scaleX - bone._scaleX) * alpha;
bone._scaleY += (bone._data._scaleY - bone._scaleY) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
default: {}
}
return;
}
float x, y;
@ -85,27 +83,59 @@ void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
}
if (alpha == 1) {
bone._scaleX = x;
bone._scaleY = y;
if (blend == MixBlend_Add) {
bone._scaleX += x - bone._data._scaleX;
bone._scaleY += y - bone._data._scaleY;
} else {
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.
float bx, by;
if (direction == MixDirection_Out) {
x = (x >= 0 ? x : -x) * (bx >= 0 ? 1 : -1);
y = (y >= 0 ? y : -y) * (by >= 0 ? 1 : -1);
switch (blend) {
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 {
bx = (bx >= 0 ? bx : -bx) * (x >= 0 ? 1 : -1);
by = (by >= 0 ? by : -by) * (y >= 0 ? 1 : -1);
switch (blend) {
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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
Bone *boneP = skeleton._bones[_boneIndex];
Bone &bone = *boneP;
if (time < _frames[0]) {
switch (pose) {
case MixPose_Setup:
switch (blend) {
case MixBlend_Setup:
bone._shearX = bone._data._shearX;
bone._shearY = bone._data._shearY;
return;
case MixPose_Current:
case MixBlend_First:
bone._shearX += (bone._data._shearX - bone._shearX) * alpha;
bone._shearY += (bone._data._shearY - bone._shearY) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
default: {}
}
return;
}
float x, y;
@ -84,12 +82,19 @@ void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
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;
switch (blend) {
case MixBlend_Setup:
bone._shearX = bone._data._shearX + x * alpha;
bone._shearY = bone._data._shearY + y * alpha;
break;
case MixBlend_First:
case MixBlend_Replace:
bone._shearX += (bone._data._shearX + x - bone._shearX) * alpha;
bone._shearY += (bone._data._shearY + y - bone._shearY) * alpha;
break;
case MixBlend_Add:
bone._shearX += x * alpha;
bone._shearY += y * alpha;
}
}

View File

@ -61,25 +61,24 @@ TransformConstraintTimeline::TransformConstraintTimeline(int frameCount) : Curve
}
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 &constraint = *constraintP;
if (time < _frames[0]) {
switch (pose) {
case MixPose_Setup:
switch (blend) {
case MixBlend_Setup:
constraint._rotateMix = constraint._data._rotateMix;
constraint._translateMix = constraint._data._translateMix;
constraint._scaleMix = constraint._data._scaleMix;
constraint._shearMix = constraint._data._shearMix;
return;
case MixPose_Current:
case MixBlend_First:
constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha;
constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha;
constraint._scaleMix += (constraint._data._scaleMix - constraint._scaleMix) * alpha;
constraint._shearMix += (constraint._data._shearMix - constraint._shearMix) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
}
@ -110,7 +109,7 @@ void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, floa
shear += (_frames[frame + SHEAR] - shear) * percent;
}
if (pose == MixPose_Setup) {
if (blend == MixBlend_Setup) {
TransformConstraintData &data = constraint._data;
constraint._rotateMix = data._rotateMix + (rotate - data._rotateMix) * 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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
Bone *boneP = skeleton._bones[_boneIndex];
Bone &bone = *boneP;
if (time < _frames[0]) {
switch (pose) {
case MixPose_Setup:
switch (blend) {
case MixBlend_Setup:
bone._x = bone._data._x;
bone._y = bone._data._y;
return;
case MixPose_Current:
case MixBlend_First:
bone._x += (bone._data._x - bone._x) * alpha;
bone._y += (bone._data._y - bone._y) * alpha;
return;
case MixPose_CurrentLayered:
default:
return;
default: {}
}
return;
}
float x, y;
@ -96,12 +94,19 @@ void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Ve
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;
switch (blend) {
case MixBlend_Setup:
bone._x = bone._data._x + x * alpha;
bone._y = bone._data._y + y * alpha;
break;
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,
MixPose pose, MixDirection direction) {
MixBlend blend, MixDirection direction) {
Slot *slotP = skeleton._slots[_slotIndex];
Slot &slot = *slotP;
if (time < _frames[0]) {
// Time is before first frame.
switch (pose) {
case MixPose_Setup:
switch (blend) {
case MixBlend_Setup:
slot.getColor().set(slot.getData().getColor());
slot.getDarkColor().set(slot.getData().getDarkColor());
return;
case MixPose_Current: {
case MixBlend_First: {
Color &color = slot.getColor();
color.r += (color.r - slot._data.getColor().r) * 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;
return;
}
case MixPose_CurrentLayered:
default:
return;
}
@ -131,48 +130,19 @@ void TwoColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vec
if (alpha == 1) {
Color &color = slot.getColor();
color.r = r;
color.g = g;
color.b = b;
color.a = a;
color.set(r, g, b, a);
Color &darkColor = slot.getDarkColor();
darkColor.r = r2;
darkColor.g = g2;
darkColor.b = b2;
darkColor.set(r2, g2, b2, 1);
} else {
float br, bg, bb, ba, br2, bg2, bb2;
if (pose == MixPose_Setup) {
br = slot._data.getColor().r;
bg = slot._data.getColor().g;
bb = slot._data.getColor().b;
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;
Color &light = slot._color;
Color &dark = slot._darkColor;
if (blend == MixBlend_Setup) {
light.set(slot._data._color);
dark.set(slot._data._darkColor);
}
Color &color = slot.getColor();
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);
light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);
dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0);
}
}

View File

@ -347,19 +347,22 @@ void coin (SkeletonData* skeletonData, Atlas* atlas) {
skeleton->updateWorldTransform();
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);
sf::Event event;
sf::Clock deltaClock;
float swirlTime = 0;
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::MouseButtonPressed) delta += 0.1f;
}
float delta = deltaClock.getElapsedTime().asSeconds();
deltaClock.restart();
// float delta = deltaClock.getElapsedTime().asSeconds();
// deltaClock.restart();
drawable->update(delta);
@ -387,13 +390,13 @@ void owl (SkeletonData* skeletonData, Atlas* atlas) {
TrackEntry* down = drawable->state->setAnimation(5, "down", true);
left->setAlpha(0);
// BOZO left->setMixBlend(SP_MIX_BLEND_ADD);
left->setMixBlend(MixBlend_Add);
right->setAlpha(0);
// BOZO right->mixBlend = SP_MIX_BLEND_ADD;
right->setMixBlend(MixBlend_Add);
up->setAlpha(0);
// BOZO up->mixBlend = SP_MIX_BLEND_ADD;
up->setMixBlend(MixBlend_Add);
down->setAlpha(0);
// BOZO down->mixBlend = SP_MIX_BLEND_ADD;
down->setMixBlend(MixBlend_Add);
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - owl");
window.setFramerateLimit(60);
@ -452,10 +455,10 @@ int main () {
DebugExtension dbgExtension;
SpineExtension::setInstance(&dbgExtension);
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(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(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(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(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(tank, "data/tank-pro.json", "data/tank-pro.skel", "data/tank.atlas", 0.2f);