diff --git a/spine-c/spine-c/src/spine/AnimationState.c b/spine-c/spine-c/src/spine/AnimationState.c index 756fb3a26..9387d95e8 100644 --- a/spine-c/spine-c/src/spine/AnimationState.c +++ b/spine-c/spine-c/src/spine/AnimationState.c @@ -877,6 +877,7 @@ void _spAnimationState_animationsChanged (spAnimationState* self) { i = self->tracksCount - 1; for (; i >= 0; i--) { entry = self->tracks[i]; + if (!entry) continue; while (entry != 0) { _spTrackEntry_computeNotLast(entry, self); entry = entry->mixingFrom; diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 92d577815..901991f87 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -428,22 +428,24 @@ namespace spine { void queueEvents(TrackEntry* entry, float animationTime); /// Sets the active TrackEntry for a given track number. - void setCurrent(size_t index, TrackEntry* current, bool interrupt); + void setCurrent(size_t index, TrackEntry *current, bool interrupt); TrackEntry* expandToIndex(size_t index); /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. /// @param last May be NULL. - TrackEntry* newTrackEntry(size_t trackIndex, Animation* animation, bool loop, TrackEntry* last); + TrackEntry* newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last); /// Dispose all track entries queued after the given TrackEntry. void disposeNext(TrackEntry* entry); void animationsChanged(); - void setTimelineModes(TrackEntry* entry); + void computeHold(TrackEntry *entry); - bool hasTimeline(TrackEntry* entry, int inId); + void computeNotLast(TrackEntry *entry); + + bool hasTimeline(TrackEntry *entry, int inId); }; } diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h index b1f83c869..fa415bc90 100644 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -109,7 +109,7 @@ public: void setAttachmentTime(float inValue); - Vector &getAttachmentVertices(); + Vector &getDeform(); private: SlotData &_data; @@ -120,7 +120,7 @@ private: bool _hasDarkColor; Attachment *_attachment; float _attachmentTime; - Vector _attachmentVertices; + Vector _deform; }; } diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index c3cdcc172..67d1e717e 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -43,6 +43,7 @@ #include #include #include +#include using namespace spine; @@ -275,6 +276,7 @@ const int Subsequent = 0; const int First = 1; const int Hold = 2; const int HoldMix = 3; +const int NotLast = 4; AnimationState::AnimationState(AnimationStateData *data) : _data(data), @@ -418,7 +420,7 @@ bool AnimationState::apply(Skeleton &skeleton) { Timeline *timeline = timelines[ii]; assert(timeline); - MixBlend timelineBlend = timelineMode[ii] == Subsequent ? blend : MixBlend_Setup; + MixBlend timelineBlend = (timelineMode[ii] & (NotLast - 1)) == Subsequent ? blend : MixBlend_Setup; RotateTimeline *rotateTimeline = NULL; if (timeline->getRTTI().isExactly(RotateTimeline::rtti)) { @@ -787,7 +789,7 @@ float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBle MixDirection direction = MixDirection_Out; MixBlend timelineBlend; float alpha; - switch (timelineMode[i]) { + switch (timelineMode[i] & (NotLast - 1)) { case Subsequent: if (!attachments && (timeline->getRTTI().isExactly(AttachmentTimeline::rtti))) continue; if (!drawOrder && (timeline->getRTTI().isExactly(DrawOrderTimeline::rtti))) continue; @@ -815,7 +817,7 @@ float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBle } else { if (timelineBlend == MixBlend_Setup) { if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) { - if (attachments) direction = MixDirection_In; + if (attachments || (timelineMode[i] & NotLast) == NotLast) direction = MixDirection_In; } else if (timeline->getRTTI().isExactly(DrawOrderTimeline::rtti)) { if (drawOrder) direction = MixDirection_In; } @@ -967,13 +969,22 @@ void AnimationState::animationsChanged() { entry = entry->_mixingFrom; do { - if (entry->_mixingTo == NULL || entry->_mixBlend != MixBlend_Add) setTimelineModes(entry); + if (entry->_mixingTo == NULL || entry->_mixBlend != MixBlend_Add) computeHold(entry); entry = entry->_mixingTo; } while (entry != NULL); } + + _propertyIDs.clear(); + for (int i = (int)_tracks.size() - 1; i >= 0; i--) { + TrackEntry *entry = _tracks[i]; + while (entry) { + computeNotLast(entry); + entry = entry->_mixingFrom; + } + } } -void AnimationState::setTimelineModes(TrackEntry *entry) { +void AnimationState::computeHold(TrackEntry *entry) { TrackEntry* to = entry->_mixingTo; Vector &timelines = entry->_animation->_timelines; size_t timelinesCount = timelines.size(); @@ -995,13 +1006,16 @@ void AnimationState::setTimelineModes(TrackEntry *entry) { size_t i = 0; continue_outer: for (; i < timelinesCount; ++i) { - int id = timelines[i]->getPropertyId(); + Timeline *timeline = timelines[i]; + int id = timeline->getPropertyId(); if (_propertyIDs.contains(id)) { timelineMode[i] = Subsequent; } else { _propertyIDs.add(id); - if (to == NULL || !hasTimeline(to, id)) { + if (to == NULL || timeline->getRTTI().isExactly(AttachmentTimeline::rtti) || + timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) || + timeline->getRTTI().isExactly(EventTimeline::rtti) || !hasTimeline(to, id)) { timelineMode[i] = First; } else { for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) { @@ -1020,6 +1034,22 @@ void AnimationState::setTimelineModes(TrackEntry *entry) { } } +void AnimationState::computeNotLast(TrackEntry *entry) { + Vector &timelines = entry->_animation->_timelines; + size_t timelinesCount = timelines.size(); + Vector &timelineMode = entry->_timelineMode; + + for (size_t i = 0; i < timelinesCount; i++) { + if (timelines[i]->getRTTI().isExactly(AttachmentTimeline::rtti)) { + AttachmentTimeline *timeline = static_cast(timelines[i]); + if (!_propertyIDs.contains(timeline->getSlotIndex())) { + _propertyIDs.add(timeline->getSlotIndex()); + timelineMode[i] |= NotLast; + } + } + } +} + bool AnimationState::hasTimeline(TrackEntry* entry, int inId) { Vector &timelines = entry->_animation->_timelines; for (size_t i = 0, n = timelines.size(); i < n; ++i) { diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index de62f9e65..c6b435e1b 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -79,8 +79,8 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto return; } - Vector &verticesArray = slot._attachmentVertices; - if (verticesArray.size() == 0) { + Vector &deformArray = slot._deform; + if (deformArray.size() == 0) { blend = MixBlend_Setup; } @@ -91,25 +91,25 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto if (time < _frames[0]) { switch (blend) { case MixBlend_Setup: - verticesArray.clear(); + deformArray.clear(); return; case MixBlend_First: { if (alpha == 1) { - verticesArray.clear(); + deformArray.clear(); return; } - verticesArray.setSize(vertexCount, 0); - Vector &vertices = verticesArray; + deformArray.setSize(vertexCount, 0); + Vector &deformInner = deformArray; if (attachment->getBones().size() == 0) { // Unweighted vertex positions. Vector &setupVertices = attachment->getVertices(); for (size_t i = 0; i < vertexCount; i++) - vertices[i] += (setupVertices[i] - vertices[i]) * alpha; + deformInner[i] += (setupVertices[i] - deformInner[i]) * alpha; } else { // Weighted deform offsets. alpha = 1 - alpha; for (size_t i = 0; i < vertexCount; i++) - vertices[i] *= alpha; + deformInner[i] *= alpha; } } case MixBlend_Replace: @@ -118,8 +118,8 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto } } - verticesArray.setSize(vertexCount, 0); - Vector &vertices = verticesArray; + deformArray.setSize(vertexCount, 0); + Vector &deform = deformArray; if (time >= frames[frames.size() - 1]) { // Time is after last frame. Vector &lastVertices = frameVertices[frames.size() - 1]; @@ -130,15 +130,15 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto // Unweighted vertex positions, no alpha. Vector &setupVertices = vertexAttachment->getVertices(); for (size_t i = 0; i < vertexCount; i++) - vertices[i] += lastVertices[i] - setupVertices[i]; + deform[i] += lastVertices[i] - setupVertices[i]; } else { // Weighted deform offsets, no alpha. for (size_t i = 0; i < vertexCount; i++) - vertices[i] += lastVertices[i]; + deform[i] += lastVertices[i]; } } else { // Vertex positions or deform offsets, no alpha. - memcpy(vertices.buffer(), lastVertices.buffer(), vertexCount * sizeof(float)); + memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float)); } } else { switch (blend) { @@ -149,12 +149,12 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto Vector &setupVertices = vertexAttachment->getVertices(); for (size_t i = 0; i < vertexCount; i++) { float setup = setupVertices[i]; - vertices[i] = setup + (lastVertices[i] - setup) * alpha; + deform[i] = setup + (lastVertices[i] - setup) * alpha; } } else { // Weighted deform offsets, with alpha. for (size_t i = 0; i < vertexCount; i++) - vertices[i] = lastVertices[i] * alpha; + deform[i] = lastVertices[i] * alpha; } break; } @@ -162,7 +162,7 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto case MixBlend_Replace: // Vertex positions or deform offsets, with alpha. for (size_t i = 0; i < vertexCount; i++) - vertices[i] += (lastVertices[i] - vertices[i]) * alpha; + deform[i] += (lastVertices[i] - deform[i]) * alpha; break; case MixBlend_Add: VertexAttachment *vertexAttachment = static_cast(slotAttachment); @@ -170,11 +170,11 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto // Unweighted vertex positions, no alpha. Vector &setupVertices = vertexAttachment->getVertices(); for (size_t i = 0; i < vertexCount; i++) - vertices[i] += (lastVertices[i] - setupVertices[i]) * alpha; + deform[i] += (lastVertices[i] - setupVertices[i]) * alpha; } else { // Weighted deform offsets, alpha. for (size_t i = 0; i < vertexCount; i++) - vertices[i] += lastVertices[i] * alpha; + deform[i] += lastVertices[i] * alpha; } } } @@ -196,20 +196,20 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto Vector &setupVertices = vertexAttachment->getVertices(); for (size_t i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; - vertices[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i]; + deform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i]; } } else { // Weighted deform offsets, no alpha. for (size_t i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; - vertices[i] += prev + (nextVertices[i] - prev) * percent; + deform[i] += prev + (nextVertices[i] - prev) * percent; } } } else { // Vertex positions or deform offsets, no alpha. for (size_t i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; - vertices[i] = prev + (nextVertices[i] - prev) * percent; + deform[i] = prev + (nextVertices[i] - prev) * percent; } } } else { @@ -221,13 +221,13 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto Vector &setupVertices = vertexAttachment->getVertices(); for (size_t i = 0; i < vertexCount; i++) { float prev = prevVertices[i], setup = setupVertices[i]; - vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; } } else { // Weighted deform offsets, with alpha. for (size_t i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; - vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; } } break; @@ -237,7 +237,7 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto // Vertex positions or deform offsets, with alpha. for (size_t i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; - vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; + deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha; } break; case MixBlend_Add: @@ -247,13 +247,13 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto Vector &setupVertices = vertexAttachment->getVertices(); for (size_t i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; - vertices[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha; + deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha; } } else { // Weighted deform offsets, with alpha. for (size_t i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; - vertices[i] += (prev + (nextVertices[i] - prev) * percent) * alpha; + deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha; } } } diff --git a/spine-cpp/spine-cpp/src/spine/Slot.cpp b/spine-cpp/spine-cpp/src/spine/Slot.cpp index 35051b59a..f9e74cef0 100644 --- a/spine-cpp/spine-cpp/src/spine/Slot.cpp +++ b/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -100,7 +100,7 @@ void Slot::setAttachment(Attachment *inValue) { _attachment = inValue; _attachmentTime = _skeleton.getTime(); - _attachmentVertices.clear(); + _deform.clear(); } float Slot::getAttachmentTime() { @@ -111,6 +111,6 @@ void Slot::setAttachmentTime(float inValue) { _attachmentTime = _skeleton.getTime() - inValue; } -Vector &Slot::getAttachmentVertices() { - return _attachmentVertices; +Vector &Slot::getDeform() { + return _deform; } diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp index a5d0cea02..0955029e4 100644 --- a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -66,7 +66,7 @@ void VertexAttachment::computeWorldVertices(Slot &slot, size_t start, size_t cou size_t stride) { count = offset + (count >> 1) * stride; Skeleton &skeleton = slot._bone._skeleton; - Vector *deformArray = &slot.getAttachmentVertices(); + Vector *deformArray = &slot.getDeform(); Vector *vertices = &_vertices; Vector &bones = _bones; if (bones.size() == 0) {