From 3fc2f08ff64fc21a80bfe2beb24a75f624dc1b20 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 2 Dec 2017 14:46:48 -0500 Subject: [PATCH] Okay, AnimationState is done, on to SkeletonJson and SkeletonBinary --- spine-cpp/spine-cpp/include/spine/Animation.h | 2 +- .../spine-cpp/include/spine/AnimationState.h | 561 +------------ .../include/spine/AnimationStateData.h | 2 + .../include/spine/AttachmentTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Bone.h | 2 + spine-cpp/spine-cpp/include/spine/BoneData.h | 2 + .../spine-cpp/include/spine/ColorTimeline.h | 2 +- .../spine-cpp/include/spine/CurveTimeline.h | 2 +- .../spine-cpp/include/spine/DeformTimeline.h | 2 +- .../include/spine/DrawOrderTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Event.h | 2 + .../spine-cpp/include/spine/EventTimeline.h | 2 +- .../include/spine/IkConstraintTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/MathUtil.h | 6 + .../include/spine/PathConstraintMixTimeline.h | 2 +- .../spine/PathConstraintPositionTimeline.h | 2 +- .../spine/PathConstraintSpacingTimeline.h | 2 +- .../spine-cpp/include/spine/RotateTimeline.h | 4 +- .../spine-cpp/include/spine/ScaleTimeline.h | 2 +- .../spine-cpp/include/spine/ShearTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Skeleton.h | 1 + spine-cpp/spine-cpp/include/spine/Timeline.h | 2 +- .../spine/TransformConstraintTimeline.h | 2 +- .../include/spine/TranslateTimeline.h | 2 +- .../include/spine/TwoColorTimeline.h | 2 +- spine-cpp/spine-cpp/src/spine/Animation.cpp | 4 +- .../spine-cpp/src/spine/AnimationState.cpp | 743 +++++++++++++++++- .../src/spine/AttachmentTimeline.cpp | 2 +- .../spine-cpp/src/spine/ColorTimeline.cpp | 2 +- .../spine-cpp/src/spine/DeformTimeline.cpp | 2 +- .../spine-cpp/src/spine/DrawOrderTimeline.cpp | 2 +- .../spine-cpp/src/spine/EventTimeline.cpp | 11 +- .../src/spine/IkConstraintTimeline.cpp | 2 +- .../src/spine/PathConstraintMixTimeline.cpp | 2 +- .../spine/PathConstraintPositionTimeline.cpp | 2 +- .../spine/PathConstraintSpacingTimeline.cpp | 2 +- .../spine-cpp/src/spine/RotateTimeline.cpp | 2 +- .../spine-cpp/src/spine/ScaleTimeline.cpp | 2 +- .../spine-cpp/src/spine/ShearTimeline.cpp | 2 +- .../src/spine/TransformConstraintTimeline.cpp | 2 +- .../spine-cpp/src/spine/TranslateTimeline.cpp | 2 +- .../spine-cpp/src/spine/TwoColorTimeline.cpp | 2 +- 42 files changed, 832 insertions(+), 568 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h index 061f4d27a..8015c57ea 100644 --- a/spine-cpp/spine-cpp/include/spine/Animation.h +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -70,7 +70,7 @@ namespace Spine /// 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& events, float alpha, MixPose pose, MixDirection direction); + void apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); std::string getName(); diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 16ed3c9ce..2b58862bb 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -297,181 +297,30 @@ namespace Spine ~AnimationState(); - void setOnAnimationEventFunc(OnAnimationEventFunc inValue); - /// /// Increments the track entry times, setting queued animations as current if needed /// @param delta delta time - void update(float delta) - { -// delta *= timeScale; -// var tracksItems = tracks.Items; -// for (int i = 0, n = tracks.Count; i < n; i++) { -// TrackEntry current = tracksItems[i]; -// if (current == NULL) continue; -// -// current.animationLast = current.nextAnimationLast; -// current.trackLast = current.nextTrackLast; -// -// float currentDelta = delta * current.timeScale; -// -// if (current.delay > 0) { -// current.delay -= currentDelta; -// if (current.delay > 0) continue; -// currentDelta = -current.delay; -// current.delay = 0; -// } -// -// TrackEntry next = current.next; -// if (next != NULL) { -// // When the next entry's delay is passed, change to the next entry, preserving leftover time. -// float nextTime = current.trackLast - next.delay; -// if (nextTime >= 0) { -// next.delay = 0; -// next.trackTime = nextTime + (delta * next.timeScale); -// current.trackTime += currentDelta; -// setCurrent(i, next, true); -// while (next.mixingFrom != NULL) { -// next.mixTime += currentDelta; -// next = next.mixingFrom; -// } -// continue; -// } -// } else if (current.trackLast >= current.trackEnd && current.mixingFrom == NULL) { -// // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. -// tracksItems[i] = NULL; -// -// queue.end(current); -// disposeNext(current); -// continue; -// } -// if (current.mixingFrom != NULL && updateMixingFrom(current, delta)) { -// // End mixing from entries once all have completed. -// var from = current.mixingFrom; -// current.mixingFrom = NULL; -// while (from != NULL) { -// queue.end(from); -// from = from.mixingFrom; -// } -// } -// -// current.trackTime += currentDelta; -// } -// -// queue.drain(); - } + void update(float delta); /// /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the /// animation state can be applied to multiple skeletons to pose them identically. - bool apply(Skeleton& skeleton) - { -// if (animationsChanged) animationsChanged(); -// -// var events = _events; -// - bool applied = false; -// var tracksItems = tracks.Items; -// for (int i = 0, m = tracks.Count; i < m; i++) { -// TrackEntry current = tracksItems[i]; -// if (current == NULL || current.delay > 0) continue; -// applied = true; -// MixPose currentPose = i == 0 ? MixPose.Current : MixPose.CurrentLayered; -// -// // apply mixing from entries first. -// float mix = current.alpha; -// if (current.mixingFrom != NULL) -// mix *= applyMixingFrom(current, skeleton, currentPose); -// else if (current.trackTime >= current.trackEnd && current.next == NULL) // -// mix = 0; // Set to setup pose the last time the entry will be applied. -// -// // apply current entry. -// float animationLast = current.animationLast, animationTime = current.AnimationTime; -// int timelineCount = current.animation.timelines.Count; -// var timelines = current.animation.timelines; -// var timelinesItems = timelines.Items; -// if (mix == 1) { -// for (int ii = 0; ii < timelineCount; ii++) -// timelinesItems[ii].apply(skeleton, animationLast, animationTime, events, 1, MixPose.Setup, MixDirection.In); -// } else { -// var timelineData = current.timelineData.Items; -// -// bool firstFrame = current.timelinesRotation.Count == 0; -// if (firstFrame) current.timelinesRotation.EnsureCapacity(timelines.Count << 1); -// var timelinesRotation = current.timelinesRotation.Items; -// -// for (int ii = 0; ii < timelineCount; ii++) { -// Timeline timeline = timelinesItems[ii]; -// MixPose pose = timelineData[ii] >= AnimationState.First ? MixPose.Setup : currentPose; -// var rotateTimeline = timeline as RotateTimeline; -// if (rotateTimeline != NULL) -// applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); -// else -// timeline.apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection.In); -// } -// } -// queueEvents(current, animationTime); -// events.clear(false); -// current.nextAnimationLast = animationTime; -// current.nextTrackLast = current.trackTime; -// } -// -// queue.drain(); - return applied; - } + bool apply(Skeleton& skeleton); /// /// Removes all animations from all tracks, leaving skeletons in their previous pose. /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, /// rather than leaving them in their previous pose. - void clearTracks() - { -// bool olddrainDisabled = queue.drainDisabled; -// queue.drainDisabled = true; -// for (int i = 0, n = tracks.Count; i < n; i++) { -// clearTrack(i); -// } -// tracks.clear(); -// queue.drainDisabled = olddrainDisabled; -// queue.drain(); - } + void clearTracks(); /// /// Removes all animations from the tracks, leaving skeletons in their previous pose. /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, /// rather than leaving them in their previous pose. - void clearTrack(int trackIndex) - { -// if (trackIndex >= tracks.Count) return; -// TrackEntry current = tracks.Items[trackIndex]; -// if (current == NULL) return; -// -// queue.end(current); -// -// disposeNext(current); -// -// TrackEntry entry = current; -// while (true) { -// TrackEntry from = entry.mixingFrom; -// if (from == NULL) break; -// queue.end(from); -// entry.mixingFrom = NULL; -// entry = from; -// } -// -// tracks.Items[current.trackIndex] = NULL; -// -// queue.drain(); - } + void clearTrack(int trackIndex); /// Sets an animation by name. setAnimation(int, Animation, bool) - TrackEntry* setAnimation(int trackIndex, std::string animationName, bool loop) - { -// Animation animation = data.skeletonData.FindAnimation(animationName); -// if (animation == NULL) throw new ArgumentException("Animation not found: " + animationName, "animationName"); -// return setAnimation(trackIndex, animation, loop); - return NULL; - } + TrackEntry* setAnimation(int trackIndex, std::string animationName, bool loop); /// Sets the current animation for a track, discarding any queued animations. /// @param loop If true, the animation will repeat. @@ -480,39 +329,11 @@ namespace Spine /// @return /// A track entry to allow further customization of animation playback. References to the track entry must not be kept /// after AnimationState.Dispose. - TrackEntry* setAnimation(int trackIndex, Animation& animation, bool loop) - { -// bool interrupt = true; -// TrackEntry current = expandToIndex(trackIndex); -// if (current != NULL) { -// if (current.nextTrackLast == -1) { -// // Don't mix from an entry that was never applied. -// tracks.Items[trackIndex] = current.mixingFrom; -// queue.interrupt(current); -// queue.end(current); -// disposeNext(current); -// current = current.mixingFrom; -// interrupt = false; -// } else { -// disposeNext(current); -// } -// } -// TrackEntry entry = newTrackEntry(trackIndex, animation, loop, current); -// setCurrent(trackIndex, entry, interrupt); -// queue.drain(); -// return entry; - return NULL; - } + TrackEntry* setAnimation(int trackIndex, Animation* animation, bool loop); /// Queues an animation by name. /// addAnimation(int, Animation, bool, float) - TrackEntry* addAnimation(int trackIndex, std::string animationName, bool loop, float delay) - { -// Animation animation = data.skeletonData.FindAnimation(animationName); -// if (animation == NULL) throw new ArgumentException("Animation not found: " + animationName, "animationName"); -// return addAnimation(trackIndex, animation, loop, delay); - return NULL; - } + TrackEntry* addAnimation(int trackIndex, std::string animationName, bool loop, float delay); /// Adds an animation to be played delay seconds after the current or last queued animation /// for a track. If the track is empty, it is equivalent to calling setAnimation. @@ -522,44 +343,11 @@ namespace Spine /// /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept /// after AnimationState.Dispose - TrackEntry* addAnimation(int trackIndex, Animation& animation, bool loop, float delay) - { -// TrackEntry last = expandToIndex(trackIndex); -// if (last != NULL) { -// while (last.next != NULL) -// last = last.next; -// } -// -// TrackEntry entry = newTrackEntry(trackIndex, animation, loop, last); -// -// if (last == NULL) { -// setCurrent(trackIndex, entry, true); -// queue.drain(); -// } else { -// last.next = entry; -// if (delay <= 0) { -// float duration = last.animationEnd - last.animationStart; -// if (duration != 0) -// delay += duration * (1 + (int)(last.trackTime / duration)) - data.GetMix(last.animation, animation); -// else -// delay = 0; -// } -// } -// -// entry.delay = delay; -// return entry; - return NULL; - } + TrackEntry* addAnimation(int trackIndex, Animation* animation, bool loop, float delay); /// /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. - TrackEntry* setEmptyAnimation(int trackIndex, float mixDuration) - { - TrackEntry* entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false); - entry->_mixDuration = mixDuration; - entry->_trackEnd = mixDuration; - return entry; - } + TrackEntry* setEmptyAnimation(int trackIndex, float mixDuration); /// /// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the @@ -571,44 +359,22 @@ namespace Spine /// @param mixDuration Mix duration. /// @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation /// duration of the previous track minus any mix duration plus the negative delay. - TrackEntry* addEmptyAnimation(int trackIndex, float mixDuration, float delay) - { - if (delay <= 0) - { - delay -= mixDuration; - } - - TrackEntry* entry = addAnimation(trackIndex, AnimationState::getEmptyAnimation(), false, delay); - entry->_mixDuration = mixDuration; - entry->_trackEnd = mixDuration; - return entry; - } + TrackEntry* addEmptyAnimation(int trackIndex, float mixDuration, float delay); /// /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. - void setEmptyAnimations(float mixDuration) - { -// bool olddrainDisabled = queue.drainDisabled; -// queue.drainDisabled = true; -// for (int i = 0, n = tracks.Count; i < n; i++) -// { -// TrackEntry current = tracks.Items[i]; -// if (current != NULL) setEmptyAnimation(i, mixDuration); -// } -// queue.drainDisabled = olddrainDisabled; -// queue.drain(); - } + void setEmptyAnimations(float mixDuration); /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing. - TrackEntry* getCurrent(int trackIndex) - { - return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; - } + TrackEntry* getCurrent(int trackIndex); -// AnimationStateData Data { get { return data; } } -// /// A list of tracks that have animations, which may contain NULLs. -// Vector Tracks { get { return tracks; } } -// float TimeScale { get { return timeScale; } set { timeScale = value; } } + AnimationStateData& getData(); + + /// A list of tracks that have animations, which may contain NULLs. + Vector getTracks(); + float getTimeScale(); + void setTimeScale(float inValue); + void setOnAnimationEventFunc(OnAnimationEventFunc inValue); private: static const int Subsequent, First, Dip, DipMix; @@ -617,306 +383,41 @@ namespace Spine Pool _trackEntryPool; Vector _tracks; - Vector _events; + Vector _events; EventQueue* _queue; Vector _propertyIDs; - Vector _mixingTo; + Vector _mixingTo; bool _animationsChanged; OnAnimationEventFunc _onAnimationEventFunc; float _timeScale; - static Animation& getEmptyAnimation(); + static Animation* getEmptyAnimation(); - static void applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, - Vector& timelinesRotation, int i, bool firstFrame) - { -// if (firstFrame) timelinesRotation[i] = 0; -// -// if (alpha == 1) { -// rotateTimeline.apply(skeleton, 0, time, NULL, 1, pose, MixDirection.In); -// return; -// } -// -// Bone bone = skeleton.bones.Items[rotateTimeline.boneIndex]; -// float[] frames = rotateTimeline.frames; -// if (time < frames[0]) { -// if (pose == MixPose.Setup) bone.rotation = bone.data.rotation; -// return; -// } -// -// float r2; -// if (time >= frames[frames.Length - RotateTimeline.ENTRIES]) // Time is after last frame. -// r2 = bone.data.rotation + frames[frames.Length + RotateTimeline.PREV_ROTATION]; -// else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, RotateTimeline.ENTRIES); -// float prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; -// float frameTime = frames[frame]; -// float percent = rotateTimeline.GetCurvePercent((frame >> 1) - 1, -// 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); -// -// r2 = frames[frame + RotateTimeline.ROTATION] - prevRotation; -// r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; -// r2 = prevRotation + r2 * percent + bone.data.rotation; -// r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; -// } -// -// // 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 total, diff = r2 - r1; -// if (diff == 0) { -// total = timelinesRotation[i]; -// } else { -// diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; -// float lastTotal, lastDiff; -// if (firstFrame) { -// lastTotal = 0; -// lastDiff = diff; -// } else { -// lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. -// lastDiff = timelinesRotation[i + 1]; // Difference between bones. -// } -// bool current = diff > 0, dir = lastTotal >= 0; -// // Detect cross at 0 (not 180). -// if (Math.Sign(lastDiff) != Math.Sign(diff) && Math.Abs(lastDiff) <= 90) { -// // A cross after a 360 rotation is a loop. -// if (Math.Abs(lastTotal) > 180) lastTotal += 360 * Math.Sign(lastTotal); -// dir = current; -// } -// total = diff + lastTotal - lastTotal % 360; // Store loops as part of lastTotal. -// if (dir != current) total += 360 * Math.Sign(lastTotal); -// timelinesRotation[i] = total; -// } -// timelinesRotation[i + 1] = diff; -// r1 += total * alpha; -// bone.rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; - } + static void applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, Vector& timelinesRotation, int i, bool firstFrame); /// Returns true when all mixing from entries are complete. - bool updateMixingFrom(TrackEntry to, float delta) - { -// TrackEntry from = to.mixingFrom; -// if (from == NULL) return true; -// -// bool finished = updateMixingFrom(from, delta); -// -// // Require mixTime > 0 to ensure the mixing from entry was applied at least once. -// if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) { -// // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). -// if (from.totalAlpha == 0 || to.mixDuration == 0) { -// to.mixingFrom = from.mixingFrom; -// to.interruptAlpha = from.interruptAlpha; -// queue.end(from); -// } -// return finished; -// } -// -// from.animationLast = from.nextAnimationLast; -// from.trackLast = from.nextTrackLast; -// from.trackTime += delta * from.timeScale; -// to.mixTime += delta * to.timeScale; - return false; - } + bool updateMixingFrom(TrackEntry* to, float delta); - float applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose) - { -// TrackEntry from = to.mixingFrom; -// if (from.mixingFrom != NULL) applyMixingFrom(from, skeleton, currentPose); -// -// float mix; -// if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes. -// mix = 1; -// currentPose = MixPose.Setup; -// } else { -// mix = to.mixTime / to.mixDuration; -// if (mix > 1) mix = 1; -// } -// -// var eventBuffer = mix < from.eventThreshold ? _events : NULL; -// bool attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold; -// float animationLast = from.animationLast, animationTime = from.AnimationTime; -// var timelines = from.animation.timelines; -// int timelineCount = timelines.Count; -// var timelinesItems = timelines.Items; -// var timelineData = from.timelineData.Items; -// var timelineDipMix = from.timelineDipMix.Items; -// -// bool firstFrame = from.timelinesRotation.Count == 0; -// if (firstFrame) from.timelinesRotation.Resize(timelines.Count << 1); // from.timelinesRotation.setSize -// var timelinesRotation = from.timelinesRotation.Items; -// -// 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 = timelinesItems[i]; -// switch (timelineData[i]) { -// case Subsequent: -// if (!attachments && timeline is AttachmentTimeline) continue; -// if (!drawOrder && timeline is DrawOrderTimeline) 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 * Math.Max(0, 1 - dipMix.mixTime / dipMix.mixDuration); -// break; -// } -// from.totalAlpha += alpha; -// var rotateTimeline = timeline as RotateTimeline; -// if (rotateTimeline != NULL) { -// applyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); -// } else { -// timeline.apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection.Out); -// } -// } -// -// if (to.mixDuration > 0) queueEvents(from, animationTime); -// _events.clear(false); -// from.nextAnimationLast = animationTime; -// from.nextTrackLast = from.trackTime; -// -// return mix; - return 0; - } + float applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose); - void queueEvents(TrackEntry* entry, float animationTime) - { -// float animationStart = entry.animationStart, animationEnd = entry.animationEnd; -// float duration = animationEnd - animationStart; -// float trackLastWrapped = entry.trackLast % duration; -// -// // Queue events before complete. -// var events = _events; -// var eventsItems = events.Items; -// int i = 0, n = events.Count; -// for (; i < n; i++) { -// var e = eventsItems[i]; -// if (e.time < trackLastWrapped) break; -// if (e.time > animationEnd) continue; // Discard events outside animation start/end. -// queue.event(entry, e); -// } -// -// // Queue complete if completed a loop iteration or the animation. -// if (entry.loop ? (trackLastWrapped > entry.trackTime % duration) -// : (animationTime >= animationEnd && entry.animationLast < animationEnd)) { -// queue.complete(entry); -// } -// -// // Queue events after complete. -// for (; i < n; i++) { -// Event e = eventsItems[i]; -// if (e.time < animationStart) continue; // Discard events outside animation start/end. -// queue.event(entry, eventsItems[i]); -// } - } + void queueEvents(TrackEntry* entry, float animationTime); /// Sets the active TrackEntry for a given track number. - void setCurrent(int index, TrackEntry* current, bool interrupt) - { -// TrackEntry from = expandToIndex(index); -// tracks.Items[index] = current; -// -// if (from != NULL) { -// if (interrupt) queue.interrupt(from); -// current.mixingFrom = from; -// current.mixTime = 0; -// -// // Store interrupted mix percentage. -// if (from.mixingFrom != NULL && from.mixDuration > 0) -// current.interruptAlpha *= Math.Min(1, from.mixTime / from.mixDuration); -// -// from.timelinesRotation.clear(); // Reset rotation for mixing out, in case entry was mixed in. -// } -// -// queue.start(current); // triggers animationsChanged - } + void setCurrent(int index, TrackEntry* current, bool interrupt); - TrackEntry* expandToIndex(int index) - { -// if (index < tracks.Count) return tracks.Items[index]; -// while (index >= tracks.Count) -// { -// tracks.Add(NULL); -// } - return NULL; - } + TrackEntry* expandToIndex(int 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(int trackIndex, Animation* animation, bool loop, TrackEntry* last) - { -// TrackEntry entry = trackEntryPool.Obtain(); // Pooling -// entry.trackIndex = trackIndex; -// entry.animation = animation; -// entry.loop = loop; -// -// entry.eventThreshold = 0; -// entry.attachmentThreshold = 0; -// entry.drawOrderThreshold = 0; -// -// entry.animationStart = 0; -// entry.animationEnd = animation.Duration; -// entry.animationLast = -1; -// entry.nextAnimationLast = -1; -// -// entry.delay = 0; -// entry.trackTime = 0; -// entry.trackLast = -1; -// entry.nextTrackLast = -1; // nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet. -// entry.trackEnd = float.MaxValue; // loop ? float.MaxValue : animation.Duration; -// entry.timeScale = 1; -// -// entry.alpha = 1; -// entry.interruptAlpha = 1; -// entry.mixTime = 0; -// entry.mixDuration = (last == NULL) ? 0 : data.GetMix(last.animation, animation); -// return entry; - return NULL; - } + TrackEntry* newTrackEntry(int trackIndex, Animation* animation, bool loop, TrackEntry* last); /// Dispose all track entries queued after the given TrackEntry. - void disposeNext(TrackEntry* entry) - { -// TrackEntry next = entry.next; -// while (next != NULL) -// { -// queue.dispose(next); -// next = next.next; -// } -// entry.next = NULL; - } + void disposeNext(TrackEntry* entry); - void animationsChanged() - { -// animationsChanged = false; -// -// var propertyIDs = _propertyIDs; -// propertyIDs.clear(); -// var mixingTo = _mixingTo; -// -// var tracksItems = tracks.Items; -// for (int i = 0, n = tracks.Count; i < n; i++) -// { -// var entry = tracksItems[i]; -// if (entry != NULL) -// { -// entry.setTimelineData(NULL, mixingTo, propertyIDs); -// } -// } - } + void animationsChanged(); }; } diff --git a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h index d0b785094..952b33256 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -44,6 +44,8 @@ namespace Spine /// Stores mix (crossfade) durations to be applied when AnimationState animations are changed. class AnimationStateData { + friend class AnimationState; + public: /// The SkeletonData to look up animations when they are specified by name. SkeletonData& getSkeletonData(); diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h index 07460f6d3..91484b2b6 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -51,7 +51,7 @@ namespace Spine public: AttachmentTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index a2bdae9e3..fafbc8f8a 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -49,6 +49,8 @@ namespace Spine { RTTI_DECL; + friend class AnimationState; + friend class RotateTimeline; friend class IkConstraint; friend class TransformConstraint; diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 2d2ce3da6..1a7fcc2e9 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -39,6 +39,8 @@ namespace Spine { class BoneData { + friend class AnimationState; + friend class RotateTimeline; friend class ScaleTimeline; friend class ShearTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h index 178e4f13e..53a33ddd4 100644 --- a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -44,7 +44,7 @@ namespace Spine ColorTimeline (int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h index a5222e31e..45854a7a0 100644 --- a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -46,7 +46,7 @@ namespace Spine public: CurveTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) = 0; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) = 0; virtual int getPropertyId() = 0; diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index 1500b77e5..a23eaca83 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -44,7 +44,7 @@ namespace Spine public: DeformTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index 60ab70a08..29226dd88 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -42,7 +42,7 @@ namespace Spine public: DrawOrderTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/Event.h b/spine-cpp/spine-cpp/include/spine/Event.h index 07d36999c..1f4688d4c 100644 --- a/spine-cpp/spine-cpp/include/spine/Event.h +++ b/spine-cpp/spine-cpp/include/spine/Event.h @@ -40,6 +40,8 @@ namespace Spine /// Stores the current pose values for an Event. class Event { + friend class AnimationState; + public: Event(float time, const EventData& data); diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index b1512327e..c2f880080 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -42,7 +42,7 @@ namespace Spine public: EventTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index fe570146b..3cd4235d9 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -44,7 +44,7 @@ namespace Spine IkConstraintTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h index 24dd4641c..325b95d2a 100644 --- a/spine-cpp/spine-cpp/include/spine/MathUtil.h +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -50,6 +50,12 @@ namespace Spine { + template + int sign(T val) + { + return (T(0) < val) - (val < T(0)); + } + inline bool areFloatsPracticallyEqual(float A, float B, float maxDiff = 0.0000000000000001f, float maxRelDiff = FLT_EPSILON) { // Check if the numbers are really close -- needed diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index 96f0bd1a8..72598ab69 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -44,7 +44,7 @@ namespace Spine PathConstraintMixTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index ab6839e1f..2fc8af6a2 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -44,7 +44,7 @@ namespace Spine PathConstraintPositionTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index fb959a55a..65392639c 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -42,7 +42,7 @@ namespace Spine public: PathConstraintSpacingTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); }; diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h index dcc013b71..c14031d98 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -37,6 +37,8 @@ namespace Spine { class RotateTimeline : public CurveTimeline { + friend class AnimationState; + RTTI_DECL; public: @@ -44,7 +46,7 @@ namespace Spine RotateTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index 12f941f42..81409a50a 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -42,7 +42,7 @@ namespace Spine public: ScaleTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); }; diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index 5618a6529..ae83d7cef 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -42,7 +42,7 @@ namespace Spine public: ShearTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); }; diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index a7bd84ce9..1b39bd793 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -51,6 +51,7 @@ namespace Spine class Skeleton { + friend class AnimationState; friend class SkeletonBounds; friend class SkeletonClipping; diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h index b00db7b28..a33bc4031 100644 --- a/spine-cpp/spine-cpp/include/spine/Timeline.h +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -61,7 +61,7 @@ namespace Spine /// apply animations on top of each other (layered). /// @param pose 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& events, float alpha, MixPose pose, MixDirection direction) = 0; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) = 0; virtual int getPropertyId() = 0; }; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index 6065d4727..c001e82b1 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -44,7 +44,7 @@ namespace Spine TransformConstraintTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index d661f9d3f..37fd21a9e 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -47,7 +47,7 @@ namespace Spine TranslateTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index ceb23848f..fd3f55fd4 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -44,7 +44,7 @@ namespace Spine TwoColorTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/src/spine/Animation.cpp b/spine-cpp/spine-cpp/src/spine/Animation.cpp index 96b625dcb..ac140cbf9 100644 --- a/spine-cpp/spine-cpp/src/spine/Animation.cpp +++ b/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -47,7 +47,7 @@ namespace Spine assert(_name.length() > 0); } - void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector& events, float alpha, MixPose pose, MixDirection direction) + void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { if (loop && _duration != 0) { @@ -60,7 +60,7 @@ namespace Spine for (int i = 0, n = static_cast(_timelines.size()); i < n; ++i) { - _timelines[i]->apply(skeleton, lastTime, time, events, alpha, pose, direction); + _timelines[i]->apply(skeleton, lastTime, time, pEvents, alpha, pose, direction); } } diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 0caa37c60..5c586c11b 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -37,6 +37,11 @@ #include #include +#include +#include +#include +#include +#include #include #include @@ -325,6 +330,7 @@ namespace Spine case EventType_Dispose: trackEntry->_onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL); state._onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL); + trackEntry->reset(); _trackEntryPool.free(trackEntry); break; case EventType_Event: @@ -357,15 +363,748 @@ namespace Spine DESTROY(EventQueue, _queue); } + void AnimationState::update(float delta) + { + delta *= _timeScale; + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) + { + TrackEntry* currentP = _tracks[i]; + if (currentP == NULL) + { + continue; + } + + TrackEntry& current = *currentP; + + current._animationLast = current._nextAnimationLast; + current._trackLast = current._nextTrackLast; + + float currentDelta = delta * current._timeScale; + + if (current._delay > 0) + { + current._delay -= currentDelta; + if (current._delay > 0) + { + continue; + } + currentDelta = -current._delay; + current._delay = 0; + } + + TrackEntry* next = current._next; + if (next != NULL) + { + // When the next entry's delay is passed, change to the next entry, preserving leftover time. + float nextTime = current._trackLast - next->_delay; + if (nextTime >= 0) + { + next->_delay = 0; + next->_trackTime = nextTime + (delta * next->_timeScale); + current._trackTime += currentDelta; + setCurrent(i, next, true); + while (next->_mixingFrom != NULL) + { + next->_mixTime += currentDelta; + next = next->_mixingFrom; + } + continue; + } + } + else if (current._trackLast >= current._trackEnd && current._mixingFrom == NULL) + { + // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. + _tracks[i] = NULL; + + _queue->end(currentP); + disposeNext(currentP); + continue; + } + + if (current._mixingFrom != NULL && updateMixingFrom(currentP, delta)) + { + // End mixing from entries once all have completed. + TrackEntry* from = current._mixingFrom; + current._mixingFrom = NULL; + while (from != NULL) + { + _queue->end(from); + from = from->_mixingFrom; + } + } + + current._trackTime += currentDelta; + } + + _queue->drain(); + } + + bool AnimationState::apply(Skeleton& skeleton) + { + if (_animationsChanged) + { + animationsChanged(); + } + + bool applied = false; + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) + { + TrackEntry* currentP = _tracks[i]; + if (currentP == NULL || currentP->_delay > 0) + { + continue; + } + + TrackEntry& current = *currentP; + + applied = true; + MixPose currentPose = i == 0 ? MixPose_Current : MixPose_CurrentLayered; + + // apply mixing from entries first. + float mix = current._alpha; + if (current._mixingFrom != NULL) + { + mix *= applyMixingFrom(currentP, skeleton, currentPose); + } + else if (current._trackTime >= current._trackEnd && current._next == NULL) // + { + mix = 0; // Set to setup pose the last time the entry will be applied. + } + + // apply current entry. + float animationLast = current._animationLast, animationTime = current.getAnimationTime(); + int timelineCount = static_cast(current._animation->_timelines.size()); + Vector& timelines = current._animation->_timelines; + if (mix == 1) + { + for (int ii = 0; ii < timelineCount; ++ii) + { + timelines[ii]->apply(skeleton, animationLast, animationTime, &_events, 1, MixPose_Setup, MixDirection_In); + } + } + else + { + Vector& timelineData = current._timelineData; + + bool firstFrame = current._timelinesRotation.size() == 0; + if (firstFrame) + { + current._timelinesRotation.reserve(timelines.size() << 1); + } + Vector& timelinesRotation = current._timelinesRotation; + + for (int ii = 0; ii < timelineCount; ++ii) + { + Timeline* timeline = timelines[ii]; + assert(timeline); + + MixPose pose = timelineData[ii] >= AnimationState::First ? MixPose_Setup : currentPose; + + RotateTimeline* rotateTimeline = NULL; + if (timeline->getRTTI().derivesFrom(RotateTimeline::rtti)) + { + rotateTimeline = static_cast(timeline); + } + + if (rotateTimeline != NULL) + { + applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); + } + else + { + timeline->apply(skeleton, animationLast, animationTime, &_events, mix, pose, MixDirection_In); + } + } + } + + queueEvents(currentP, animationTime); + _events.clear(); + current._nextAnimationLast = animationTime; + current._nextTrackLast = current._trackTime; + } + + _queue->drain(); + return applied; + } + + void AnimationState::clearTracks() + { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) + { + clearTrack(i); + } + _tracks.clear(); + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); + } + + void AnimationState::clearTrack(int trackIndex) + { + if (trackIndex >= _tracks.size()) + { + return; + } + + TrackEntry* current = _tracks[trackIndex]; + if (current == NULL) + { + return; + } + + _queue->end(current); + + disposeNext(current); + + TrackEntry* entry = current; + while (true) + { + TrackEntry* from = entry->_mixingFrom; + if (from == NULL) + { + break; + } + + _queue->end(from); + entry->_mixingFrom = NULL; + entry = from; + } + + _tracks[current->_trackIndex] = NULL; + + _queue->drain(); + } + + TrackEntry* AnimationState::setAnimation(int trackIndex, std::string animationName, bool loop) + { + Animation* animation = _data._skeletonData.findAnimation(animationName); + assert(animation != NULL); + + return setAnimation(trackIndex, animation, loop); + } + + TrackEntry* AnimationState::setAnimation(int trackIndex, Animation* animation, bool loop) + { + assert(animation != NULL); + + bool interrupt = true; + TrackEntry* current = expandToIndex(trackIndex); + if (current != NULL) + { + if (current->_nextTrackLast == -1) + { + // Don't mix from an entry that was never applied. + _tracks[trackIndex] = current->_mixingFrom; + _queue->interrupt(current); + _queue->end(current); + disposeNext(current); + current = current->_mixingFrom; + interrupt = false; + } + else + { + disposeNext(current); + } + } + + TrackEntry* entry = newTrackEntry(trackIndex, animation, loop, current); + setCurrent(trackIndex, entry, interrupt); + _queue->drain(); + + return entry; + } + + TrackEntry* AnimationState::addAnimation(int trackIndex, std::string animationName, bool loop, float delay) + { + Animation* animation = _data._skeletonData.findAnimation(animationName); + assert(animation != NULL); + + return addAnimation(trackIndex, animation, loop, delay); + } + + TrackEntry* AnimationState::addAnimation(int trackIndex, Animation* animation, bool loop, float delay) + { + assert(animation != NULL); + + TrackEntry* last = expandToIndex(trackIndex); + if (last != NULL) + { + while (last->_next != NULL) + { + last = last->_next; + } + } + + TrackEntry* entry = newTrackEntry(trackIndex, animation, loop, last); + + if (last == NULL) + { + setCurrent(trackIndex, entry, true); + _queue->drain(); + } + else + { + last->_next = entry; + if (delay <= 0) + { + float duration = last->_animationEnd - last->_animationStart; + if (duration != 0) + { + delay += duration * (1 + (int)(last->_trackTime / duration)) - _data.getMix(last->_animation, animation); + } + else + { + delay = 0; + } + } + } + + entry->_delay = delay; + return entry; + } + + TrackEntry* AnimationState::setEmptyAnimation(int trackIndex, float mixDuration) + { + TrackEntry* entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; + } + + TrackEntry* AnimationState::addEmptyAnimation(int trackIndex, float mixDuration, float delay) + { + if (delay <= 0) + { + delay -= mixDuration; + } + + TrackEntry* entry = addAnimation(trackIndex, AnimationState::getEmptyAnimation(), false, delay); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; + } + + void AnimationState::setEmptyAnimations(float mixDuration) + { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) + { + TrackEntry* current = _tracks[i]; + if (current != NULL) + { + setEmptyAnimation(i, mixDuration); + } + } + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); + } + + TrackEntry* AnimationState::getCurrent(int trackIndex) + { + return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; + } + + AnimationStateData& AnimationState::getData() + { + return _data; + } + + Vector AnimationState::getTracks() + { + return _tracks; + } + + float AnimationState::getTimeScale() + { + return _timeScale; + } + + void AnimationState::setTimeScale(float inValue) + { + _timeScale = inValue; + } + void AnimationState::setOnAnimationEventFunc(OnAnimationEventFunc inValue) { _onAnimationEventFunc = inValue; } - Animation& AnimationState::getEmptyAnimation() + Animation* AnimationState::getEmptyAnimation() { static Vector timelines; static Animation ret(std::string(""), timelines, 0); - return ret; + return &ret; + } + + void AnimationState::applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, Vector& timelinesRotation, int i, bool firstFrame) + { + if (firstFrame) + { + timelinesRotation[i] = 0; + } + + if (alpha == 1) + { + rotateTimeline->apply(skeleton, 0, time, NULL, 1, pose, MixDirection_In); + return; + } + + Bone* bone = skeleton._bones[rotateTimeline->_boneIndex]; + Vector frames = rotateTimeline->_frames; + if (time < frames[0]) + { + if (pose == MixPose_Setup) + { + bone->_rotation = bone->_data._rotation; + } + return; + } + + float r2; + if (time >= frames[frames.size() - RotateTimeline::ENTRIES]) // Time is after last frame. + { + r2 = bone->_data._rotation + frames[frames.size() + RotateTimeline::PREV_ROTATION]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(frames, time, RotateTimeline::ENTRIES); + float prevRotation = frames[frame + RotateTimeline::PREV_ROTATION]; + float frameTime = frames[frame]; + float percent = rotateTimeline->getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + RotateTimeline::PREV_TIME] - frameTime)); + + r2 = frames[frame + RotateTimeline::ROTATION] - prevRotation; + r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; + r2 = prevRotation + r2 * percent + bone->_data._rotation; + r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; + } + + // 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 total, diff = r2 - r1; + if (diff == 0) + { + total = timelinesRotation[i]; + } + else + { + diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; + float lastTotal, lastDiff; + if (firstFrame) + { + lastTotal = 0; + lastDiff = diff; + } + else + { + lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. + lastDiff = timelinesRotation[i + 1]; // Difference between bones. + } + + bool current = diff > 0, dir = lastTotal >= 0; + // Detect cross at 0 (not 180). + if (sign(lastDiff) != sign(diff) && abs(lastDiff) <= 90) + { + // A cross after a 360 rotation is a loop. + if (abs(lastTotal) > 180) + { + lastTotal += 360 * sign(lastTotal); + } + dir = current; + } + + total = diff + lastTotal - fmod(lastTotal, 360); // Store loops as part of lastTotal. + if (dir != current) + { + total += 360 * sign(lastTotal); + } + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + r1 += total * alpha; + bone->_rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; + } + + bool AnimationState::updateMixingFrom(TrackEntry* to, float delta) + { + TrackEntry* from = to->_mixingFrom; + if (from == NULL) + { + return true; + } + + bool finished = updateMixingFrom(from, delta); + + // Require mixTime > 0 to ensure the mixing from entry was applied at least once. + if (to->_mixTime > 0 && (to->_mixTime >= to->_mixDuration || to->_timeScale == 0)) + { + // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). + if (from->_totalAlpha == 0 || to->_mixDuration == 0) + { + to->_mixingFrom = from->_mixingFrom; + to->_interruptAlpha = from->_interruptAlpha; + _queue->end(from); + } + return finished; + } + + from->_animationLast = from->_nextAnimationLast; + from->_trackLast = from->_nextTrackLast; + from->_trackTime += delta * from->_timeScale; + to->_mixTime += delta * to->_timeScale; + + return false; + } + + float AnimationState::applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose) + { + TrackEntry* from = to->_mixingFrom; + if (from->_mixingFrom != NULL) + { + applyMixingFrom(from, skeleton, currentPose); + } + + float mix; + if (to->_mixDuration == 0) + { + // Single frame mix to undo mixingFrom changes. + mix = 1; + currentPose = MixPose_Setup; + } + else + { + mix = to->_mixTime / to->_mixDuration; + if (mix > 1) + { + mix = 1; + } + } + + Vector* eventBuffer = mix < from->_eventThreshold ? &_events : NULL; + bool attachments = mix < from->_attachmentThreshold, drawOrder = mix < from->_drawOrderThreshold; + float animationLast = from->_animationLast, animationTime = from->getAnimationTime(); + Vector& timelines = from->_animation->_timelines; + int timelineCount = static_cast(timelines.size()); + Vector& timelineData = from->_timelineData; + Vector& timelineDipMix = from->_timelineDipMix; + + bool firstFrame = from->_timelinesRotation.size() == 0; + if (firstFrame) + { + // from.timelinesRotation.setSize + from->_timelinesRotation.reserve(timelines.size() << 1); + } + + Vector& 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().derivesFrom(AttachmentTimeline::rtti)) + { + continue; + } + if (!drawOrder && timeline->getRTTI().derivesFrom(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 * MAX(0, 1 - dipMix->_mixTime / dipMix->_mixDuration); + break; + } + from->_totalAlpha += alpha; + + RotateTimeline* rotateTimeline = NULL; + if (timeline->getRTTI().derivesFrom(RotateTimeline::rtti)) + { + rotateTimeline = static_cast(timeline); + } + + if (rotateTimeline != NULL) + { + applyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); + } + else + { + timeline->apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection_Out); + } + } + + if (to->_mixDuration > 0) + { + queueEvents(from, animationTime); + } + + _events.clear(); + from->_nextAnimationLast = animationTime; + from->_nextTrackLast = from->_trackTime; + + return mix; + } + + void AnimationState::queueEvents(TrackEntry* entry, float animationTime) + { + float animationStart = entry->_animationStart, animationEnd = entry->_animationEnd; + float duration = animationEnd - animationStart; + float trackLastWrapped = fmodf(entry->_trackLast, duration); + + // Queue events before complete. + int i = 0, n = static_cast(_events.size()); + for (; i < n; ++i) + { + Event* e = _events[i]; + if (e->_time < trackLastWrapped) + { + break; + } + if (e->_time > animationEnd) + { + // Discard events outside animation start/end. + continue; + } + _queue->event(entry, e); + } + + // Queue complete if completed a loop iteration or the animation. + if (entry->_loop ? (trackLastWrapped > fmod(entry->_trackTime, duration)) : (animationTime >= animationEnd && entry->_animationLast < animationEnd)) + { + _queue->complete(entry); + } + + // Queue events after complete. + for (; i < n; ++i) + { + Event* e = _events[i]; + if (e->_time < animationStart) + { + // Discard events outside animation start/end. + continue; + } + _queue->event(entry, _events[i]); + } + } + + void AnimationState::setCurrent(int index, TrackEntry* current, bool interrupt) + { + TrackEntry* from = expandToIndex(index); + _tracks[index] = current; + + if (from != NULL) + { + if (interrupt) + { + _queue->interrupt(from); + } + + current->_mixingFrom = from; + current->_mixTime = 0; + + // Store interrupted mix percentage. + if (from->_mixingFrom != NULL && from->_mixDuration > 0) + { + current->_interruptAlpha *= MIN(1, from->_mixTime / from->_mixDuration); + } + + from->_timelinesRotation.clear(); // Reset rotation for mixing out, in case entry was mixed in. + } + + _queue->start(current); // triggers animationsChanged + } + + TrackEntry* AnimationState::expandToIndex(int index) + { + if (index < _tracks.size()) + { + return _tracks[index]; + } + + while (index >= _tracks.size()) + { + _tracks.push_back(NULL); + } + + return NULL; + } + + TrackEntry* AnimationState::newTrackEntry(int trackIndex, Animation* animation, bool loop, TrackEntry* last) + { + TrackEntry* entryP = _trackEntryPool.obtain(); // Pooling + TrackEntry& entry = *entryP; + + entry._trackIndex = trackIndex; + entry._animation = animation; + entry._loop = loop; + + entry._eventThreshold = 0; + entry._attachmentThreshold = 0; + entry._drawOrderThreshold = 0; + + entry._animationStart = 0; + entry._animationEnd = animation->getDuration(); + entry._animationLast = -1; + entry._nextAnimationLast = -1; + + entry._delay = 0; + entry._trackTime = 0; + entry._trackLast = -1; + entry._nextTrackLast = -1; // nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet. + entry._trackEnd = std::numeric_limits::max(); // loop ? float.MaxValue : animation.Duration; + entry._timeScale = 1; + + entry._alpha = 1; + entry._interruptAlpha = 1; + entry._mixTime = 0; + entry._mixDuration = (last == NULL) ? 0 : _data.getMix(last->_animation, animation); + + return entryP; + } + + void AnimationState::disposeNext(TrackEntry* entry) + { + TrackEntry* next = entry->_next; + while (next != NULL) + { + _queue->dispose(next); + next = next->_next; + } + entry->_next = NULL; + } + + void AnimationState::animationsChanged() + { + _animationsChanged = false; + + _propertyIDs.clear(); + + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) + { + TrackEntry* entry = _tracks[i]; + if (entry != NULL) + { + entry->setTimelineData(NULL, _mixingTo, _propertyIDs); + } + } } } diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp index c923a4508..53bcaaf72 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -48,7 +48,7 @@ namespace Spine _attachmentNames.reserve(frameCount); } - void AttachmentTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void AttachmentTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { assert(_slotIndex < skeleton._slots.size()); diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp index e7d49f9aa..4d99feb7a 100644 --- a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -58,7 +58,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void ColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void ColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Slot* slotP = skeleton._slots[_slotIndex]; Slot& slot = *slotP; diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index ac2a981fe..bfa1389aa 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -50,7 +50,7 @@ namespace Spine _frameVertices.reserve(frameCount); } - void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Slot* slotP = skeleton._slots[_slotIndex]; Slot& slot = *slotP; diff --git a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp index 6561db060..207715f8e 100644 --- a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -48,7 +48,7 @@ namespace Spine _drawOrders.reserve(frameCount); } - void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Vector& drawOrder = skeleton._drawOrder; Vector& slots = skeleton._slots; diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index 87ab7a814..23a0fccab 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -49,8 +49,15 @@ namespace Spine _events.reserve(frameCount); } - void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { + if (pEvents == NULL) + { + return; + } + + Vector& events = *pEvents; + if (events.size() == 0) { return; @@ -61,7 +68,7 @@ namespace Spine if (lastTime > time) { // Fire events after last time for looped animations. - apply(skeleton, lastTime, std::numeric_limits::max(), events, alpha, pose, direction); + apply(skeleton, lastTime, std::numeric_limits::max(), pEvents, alpha, pose, direction); lastTime = -1.0f; } else if (lastTime >= _frames[frameCount - 1]) // Last time is after last frame. diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index 2b05750e3..483b8c619 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -56,7 +56,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { IkConstraint* constraintP = skeleton._ikConstraints[_ikConstraintIndex]; IkConstraint& constraint = *constraintP; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index 394ecf48e..18c84ece7 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -56,7 +56,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint& constraint = *constraintP; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index 75b423ee9..13363ad45 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -54,7 +54,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint& constraint = *constraintP; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index 7d4713585..44d132596 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -49,7 +49,7 @@ namespace Spine // Empty } - void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint& constraint = *constraintP; diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index acfeb7db1..c57a37b37 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -47,7 +47,7 @@ namespace Spine _frames.reserve(frameCount << 1); } - void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* bone = skeleton.getBones()[_boneIndex]; diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index 0be6f9347..9c110a064 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -49,7 +49,7 @@ namespace Spine // Empty } - void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* boneP = skeleton._bones[_boneIndex]; Bone& bone = *boneP; diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index 4b142eccc..2089e7de4 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -49,7 +49,7 @@ namespace Spine // Empty } - void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* boneP = skeleton._bones[_boneIndex]; Bone& bone = *boneP; diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index bb4769cce..3d7cf2dfd 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -60,7 +60,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { TransformConstraint* constraintP = skeleton._transformConstraints[_transformConstraintIndex]; TransformConstraint& constraint = *constraintP; diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index 1a886f7d1..f241f31a8 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -56,7 +56,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* boneP = skeleton._bones[_boneIndex]; Bone& bone = *boneP; diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 0232711c3..bce0d0bf7 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -64,7 +64,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Slot* slotP = skeleton._slots[_slotIndex]; Slot& slot = *slotP;