From fff715d94ddf24819becd797e7d5d08d091250e6 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 18 Mar 2026 16:58:41 +0100 Subject: [PATCH] [cpp] Port 29bf262d0: Fix track 0 dip mixing to animation with key > frame 0. --- spine-cpp/include/spine/AnimationState.h | 2 +- spine-cpp/src/spine/AnimationState.cpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/spine-cpp/include/spine/AnimationState.h b/spine-cpp/include/spine/AnimationState.h index b29eecf66..ff7835b4b 100644 --- a/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/include/spine/AnimationState.h @@ -597,7 +597,7 @@ namespace spine { /// Returns true when all mixing from entries are complete. bool updateMixingFrom(TrackEntry *to, float delta); - float applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend currentPose); + float applyMixingFrom(TrackEntry *to, Skeleton &skeleton); void queueEvents(TrackEntry *entry, float animationTime); diff --git a/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/src/spine/AnimationState.cpp index 36a058049..c302e0ff6 100644 --- a/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/src/spine/AnimationState.cpp @@ -568,12 +568,14 @@ bool AnimationState::apply(Skeleton &skeleton) { TrackEntry ¤t = *currentP; applied = true; + + // Track 0 animations aren't for layering, so never use current values before the first key. MixBlend blend = i == 0 ? MixBlend_First : current._mixBlend; // apply mixing from entries first. float alpha = current._alpha; if (current._mixingFrom != NULL) { - alpha *= applyMixingFrom(currentP, skeleton, blend); + alpha *= applyMixingFrom(currentP, skeleton); } else if (current._trackTime >= current._trackEnd && current._next == NULL) { alpha = 0;// Set to setup pose the last time the entry will be applied. } @@ -611,7 +613,7 @@ bool AnimationState::apply(Skeleton &skeleton) { Timeline *timeline = timelines[ii]; assert(timeline); - MixBlend timelineBlend = timelineMode[ii] == Subsequent ? blend : MixBlend_Setup; + MixBlend timelineBlend = timelineMode[ii] == Subsequent ? current._mixBlend : MixBlend_Setup; if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti)) applyRotateTimeline(static_cast(timeline), skeleton, applyTime, alpha, timelineBlend, timelinesRotation, @@ -944,21 +946,18 @@ bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) { return false; } -float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBlend blend) { +float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton) { TrackEntry *from = to->_mixingFrom; - if (from->_mixingFrom != NULL) applyMixingFrom(from, skeleton, blend); + if (from->_mixingFrom != NULL) applyMixingFrom(from, skeleton); float mix; - if (to->_mixDuration == 0) { - // Single frame mix to undo mixingFrom changes. + if (to->_mixDuration == 0) // Single frame mix to undo mixingFrom changes. mix = 1; - if (blend == MixBlend_First) blend = MixBlend_Setup; - } else { + else { mix = to->_mixTime / to->_mixDuration; if (mix > 1) { mix = 1; } - if (blend != MixBlend_First) blend = from->_mixBlend; } bool attachments = mix < from->_mixAttachmentThreshold, drawOrder = mix < from->_mixDrawOrderThreshold; @@ -974,6 +973,7 @@ float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBle if (mix < from->_eventThreshold) events = &_events; } + MixBlend blend = from->_mixBlend; if (blend == MixBlend_Add) { for (size_t i = 0; i < timelineCount; i++) timelines[i]->apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection_Out, false);