mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-07 11:16:53 +08:00
Okay, AnimationState is done, on to SkeletonJson and SkeletonBinary
This commit is contained in:
parent
af43d7cff1
commit
3fc2f08ff6
@ -70,7 +70,7 @@ namespace Spine
|
|||||||
|
|
||||||
/// Applies all the animation's timelines to the specified skeleton.
|
/// Applies all the animation's timelines to the specified skeleton.
|
||||||
/// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection)
|
/// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection)
|
||||||
void apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
void apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
|
|||||||
@ -297,181 +297,30 @@ namespace Spine
|
|||||||
|
|
||||||
~AnimationState();
|
~AnimationState();
|
||||||
|
|
||||||
void setOnAnimationEventFunc(OnAnimationEventFunc inValue);
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Increments the track entry times, setting queued animations as current if needed
|
/// Increments the track entry times, setting queued animations as current if needed
|
||||||
/// @param delta delta time
|
/// @param delta delta time
|
||||||
void update(float delta)
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the
|
/// 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.
|
/// animation state can be applied to multiple skeletons to pose them identically.
|
||||||
bool apply(Skeleton& skeleton)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Removes all animations from all tracks, leaving skeletons in their previous pose.
|
/// 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,
|
/// 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.
|
/// rather than leaving them in their previous pose.
|
||||||
void clearTracks()
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Removes all animations from the tracks, leaving skeletons in their previous pose.
|
/// 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,
|
/// 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.
|
/// rather than leaving them in their previous pose.
|
||||||
void clearTrack(int trackIndex)
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets an animation by name. setAnimation(int, Animation, bool)
|
/// Sets an animation by name. setAnimation(int, Animation, bool)
|
||||||
TrackEntry* setAnimation(int trackIndex, std::string animationName, bool loop)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the current animation for a track, discarding any queued animations.
|
/// Sets the current animation for a track, discarding any queued animations.
|
||||||
/// @param loop If true, the animation will repeat.
|
/// @param loop If true, the animation will repeat.
|
||||||
@ -480,39 +329,11 @@ namespace Spine
|
|||||||
/// @return
|
/// @return
|
||||||
/// A track entry to allow further customization of animation playback. References to the track entry must not be kept
|
/// A track entry to allow further customization of animation playback. References to the track entry must not be kept
|
||||||
/// after AnimationState.Dispose.
|
/// after AnimationState.Dispose.
|
||||||
TrackEntry* setAnimation(int trackIndex, Animation& animation, bool loop)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Queues an animation by name.
|
/// Queues an animation by name.
|
||||||
/// addAnimation(int, Animation, bool, float)
|
/// addAnimation(int, Animation, bool, float)
|
||||||
TrackEntry* addAnimation(int trackIndex, std::string animationName, bool loop, float delay)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds an animation to be played delay seconds after the current or last queued animation
|
/// 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.
|
/// 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
|
/// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
|
||||||
/// after AnimationState.Dispose
|
/// after AnimationState.Dispose
|
||||||
TrackEntry* addAnimation(int trackIndex, Animation& animation, bool loop, float delay)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration.
|
/// 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* setEmptyAnimation(int trackIndex, float mixDuration);
|
||||||
{
|
|
||||||
TrackEntry* entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false);
|
|
||||||
entry->_mixDuration = mixDuration;
|
|
||||||
entry->_trackEnd = mixDuration;
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the
|
/// 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 mixDuration Mix duration.
|
||||||
/// @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation
|
/// @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.
|
/// duration of the previous track minus any mix duration plus the negative delay.
|
||||||
TrackEntry* addEmptyAnimation(int trackIndex, float mixDuration, float 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration.
|
/// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration.
|
||||||
void setEmptyAnimations(float mixDuration)
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing.
|
/// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing.
|
||||||
TrackEntry* getCurrent(int trackIndex)
|
TrackEntry* getCurrent(int trackIndex);
|
||||||
{
|
|
||||||
return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnimationStateData Data { get { return data; } }
|
AnimationStateData& getData();
|
||||||
// /// A list of tracks that have animations, which may contain NULLs.
|
|
||||||
// Vector<TrackEntry> Tracks { get { return tracks; } }
|
/// A list of tracks that have animations, which may contain NULLs.
|
||||||
// float TimeScale { get { return timeScale; } set { timeScale = value; } }
|
Vector<TrackEntry*> getTracks();
|
||||||
|
float getTimeScale();
|
||||||
|
void setTimeScale(float inValue);
|
||||||
|
void setOnAnimationEventFunc(OnAnimationEventFunc inValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int Subsequent, First, Dip, DipMix;
|
static const int Subsequent, First, Dip, DipMix;
|
||||||
@ -617,306 +383,41 @@ namespace Spine
|
|||||||
|
|
||||||
Pool<TrackEntry> _trackEntryPool;
|
Pool<TrackEntry> _trackEntryPool;
|
||||||
Vector<TrackEntry*> _tracks;
|
Vector<TrackEntry*> _tracks;
|
||||||
Vector<Event> _events;
|
Vector<Event*> _events;
|
||||||
EventQueue* _queue;
|
EventQueue* _queue;
|
||||||
|
|
||||||
Vector<int> _propertyIDs;
|
Vector<int> _propertyIDs;
|
||||||
Vector<TrackEntry> _mixingTo;
|
Vector<TrackEntry*> _mixingTo;
|
||||||
bool _animationsChanged;
|
bool _animationsChanged;
|
||||||
|
|
||||||
OnAnimationEventFunc _onAnimationEventFunc;
|
OnAnimationEventFunc _onAnimationEventFunc;
|
||||||
|
|
||||||
float _timeScale;
|
float _timeScale;
|
||||||
|
|
||||||
static Animation& getEmptyAnimation();
|
static Animation* getEmptyAnimation();
|
||||||
|
|
||||||
static void applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose,
|
static void applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, Vector<float>& timelinesRotation, int i, bool firstFrame);
|
||||||
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);
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true when all mixing from entries are complete.
|
/// Returns true when all mixing from entries are complete.
|
||||||
bool updateMixingFrom(TrackEntry to, float delta)
|
bool updateMixingFrom(TrackEntry* to, float delta);
|
||||||
{
|
|
||||||
// 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 applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void queueEvents(TrackEntry* entry, float animationTime)
|
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]);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the active TrackEntry for a given track number.
|
/// Sets the active TrackEntry for a given track number.
|
||||||
void setCurrent(int index, TrackEntry* current, bool interrupt)
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
TrackEntry* expandToIndex(int index)
|
TrackEntry* expandToIndex(int index);
|
||||||
{
|
|
||||||
// if (index < tracks.Count) return tracks.Items[index];
|
|
||||||
// while (index >= tracks.Count)
|
|
||||||
// {
|
|
||||||
// tracks.Add(NULL);
|
|
||||||
// }
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values.
|
/// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values.
|
||||||
/// @param last May be NULL.
|
/// @param last May be NULL.
|
||||||
TrackEntry* newTrackEntry(int trackIndex, Animation* animation, bool loop, TrackEntry* last)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dispose all track entries queued after the given TrackEntry.
|
/// Dispose all track entries queued after the given TrackEntry.
|
||||||
void disposeNext(TrackEntry* entry)
|
void disposeNext(TrackEntry* entry);
|
||||||
{
|
|
||||||
// TrackEntry next = entry.next;
|
|
||||||
// while (next != NULL)
|
|
||||||
// {
|
|
||||||
// queue.dispose(next);
|
|
||||||
// next = next.next;
|
|
||||||
// }
|
|
||||||
// entry.next = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void animationsChanged()
|
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);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,8 @@ namespace Spine
|
|||||||
/// Stores mix (crossfade) durations to be applied when AnimationState animations are changed.
|
/// Stores mix (crossfade) durations to be applied when AnimationState animations are changed.
|
||||||
class AnimationStateData
|
class AnimationStateData
|
||||||
{
|
{
|
||||||
|
friend class AnimationState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// The SkeletonData to look up animations when they are specified by name.
|
/// The SkeletonData to look up animations when they are specified by name.
|
||||||
SkeletonData& getSkeletonData();
|
SkeletonData& getSkeletonData();
|
||||||
|
|||||||
@ -51,7 +51,7 @@ namespace Spine
|
|||||||
public:
|
public:
|
||||||
AttachmentTimeline(int frameCount);
|
AttachmentTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -49,6 +49,8 @@ namespace Spine
|
|||||||
{
|
{
|
||||||
RTTI_DECL;
|
RTTI_DECL;
|
||||||
|
|
||||||
|
friend class AnimationState;
|
||||||
|
|
||||||
friend class RotateTimeline;
|
friend class RotateTimeline;
|
||||||
friend class IkConstraint;
|
friend class IkConstraint;
|
||||||
friend class TransformConstraint;
|
friend class TransformConstraint;
|
||||||
|
|||||||
@ -39,6 +39,8 @@ namespace Spine
|
|||||||
{
|
{
|
||||||
class BoneData
|
class BoneData
|
||||||
{
|
{
|
||||||
|
friend class AnimationState;
|
||||||
|
|
||||||
friend class RotateTimeline;
|
friend class RotateTimeline;
|
||||||
friend class ScaleTimeline;
|
friend class ScaleTimeline;
|
||||||
friend class ShearTimeline;
|
friend class ShearTimeline;
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace Spine
|
|||||||
|
|
||||||
ColorTimeline (int frameCount);
|
ColorTimeline (int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@ namespace Spine
|
|||||||
public:
|
public:
|
||||||
CurveTimeline(int frameCount);
|
CurveTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction) = 0;
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction) = 0;
|
||||||
|
|
||||||
virtual int getPropertyId() = 0;
|
virtual int getPropertyId() = 0;
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace Spine
|
|||||||
public:
|
public:
|
||||||
DeformTimeline(int frameCount);
|
DeformTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ namespace Spine
|
|||||||
public:
|
public:
|
||||||
DrawOrderTimeline(int frameCount);
|
DrawOrderTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,8 @@ namespace Spine
|
|||||||
/// Stores the current pose values for an Event.
|
/// Stores the current pose values for an Event.
|
||||||
class Event
|
class Event
|
||||||
{
|
{
|
||||||
|
friend class AnimationState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Event(float time, const EventData& data);
|
Event(float time, const EventData& data);
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ namespace Spine
|
|||||||
public:
|
public:
|
||||||
EventTimeline(int frameCount);
|
EventTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace Spine
|
|||||||
|
|
||||||
IkConstraintTimeline(int frameCount);
|
IkConstraintTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -50,6 +50,12 @@
|
|||||||
|
|
||||||
namespace Spine
|
namespace Spine
|
||||||
{
|
{
|
||||||
|
template <typename T>
|
||||||
|
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)
|
inline bool areFloatsPracticallyEqual(float A, float B, float maxDiff = 0.0000000000000001f, float maxRelDiff = FLT_EPSILON)
|
||||||
{
|
{
|
||||||
// Check if the numbers are really close -- needed
|
// Check if the numbers are really close -- needed
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace Spine
|
|||||||
|
|
||||||
PathConstraintMixTimeline(int frameCount);
|
PathConstraintMixTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace Spine
|
|||||||
|
|
||||||
PathConstraintPositionTimeline(int frameCount);
|
PathConstraintPositionTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ namespace Spine
|
|||||||
public:
|
public:
|
||||||
PathConstraintSpacingTimeline(int frameCount);
|
PathConstraintSpacingTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -37,6 +37,8 @@ namespace Spine
|
|||||||
{
|
{
|
||||||
class RotateTimeline : public CurveTimeline
|
class RotateTimeline : public CurveTimeline
|
||||||
{
|
{
|
||||||
|
friend class AnimationState;
|
||||||
|
|
||||||
RTTI_DECL;
|
RTTI_DECL;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -44,7 +46,7 @@ namespace Spine
|
|||||||
|
|
||||||
RotateTimeline(int frameCount);
|
RotateTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ namespace Spine
|
|||||||
public:
|
public:
|
||||||
ScaleTimeline(int frameCount);
|
ScaleTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -42,7 +42,7 @@ namespace Spine
|
|||||||
public:
|
public:
|
||||||
ShearTimeline(int frameCount);
|
ShearTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -51,6 +51,7 @@ namespace Spine
|
|||||||
|
|
||||||
class Skeleton
|
class Skeleton
|
||||||
{
|
{
|
||||||
|
friend class AnimationState;
|
||||||
friend class SkeletonBounds;
|
friend class SkeletonBounds;
|
||||||
friend class SkeletonClipping;
|
friend class SkeletonClipping;
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ namespace Spine
|
|||||||
/// apply animations on top of each other (layered).
|
/// apply animations on top of each other (layered).
|
||||||
/// @param pose Controls how mixing is applied when alpha is than 1.
|
/// @param 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.
|
/// @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*>& events, float alpha, MixPose pose, MixDirection direction) = 0;
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction) = 0;
|
||||||
|
|
||||||
virtual int getPropertyId() = 0;
|
virtual int getPropertyId() = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace Spine
|
|||||||
|
|
||||||
TransformConstraintTimeline(int frameCount);
|
TransformConstraintTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace Spine
|
|||||||
|
|
||||||
TranslateTimeline(int frameCount);
|
TranslateTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace Spine
|
|||||||
|
|
||||||
TwoColorTimeline(int frameCount);
|
TwoColorTimeline(int frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
|
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction);
|
||||||
|
|
||||||
virtual int getPropertyId();
|
virtual int getPropertyId();
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace Spine
|
|||||||
assert(_name.length() > 0);
|
assert(_name.length() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
if (loop && _duration != 0)
|
if (loop && _duration != 0)
|
||||||
{
|
{
|
||||||
@ -60,7 +60,7 @@ namespace Spine
|
|||||||
|
|
||||||
for (int i = 0, n = static_cast<int>(_timelines.size()); i < n; ++i)
|
for (int i = 0, n = static_cast<int>(_timelines.size()); i < n; ++i)
|
||||||
{
|
{
|
||||||
_timelines[i]->apply(skeleton, lastTime, time, events, alpha, pose, direction);
|
_timelines[i]->apply(skeleton, lastTime, time, pEvents, alpha, pose, direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,11 @@
|
|||||||
#include <spine/RotateTimeline.h>
|
#include <spine/RotateTimeline.h>
|
||||||
|
|
||||||
#include <spine/Timeline.h>
|
#include <spine/Timeline.h>
|
||||||
|
#include <spine/SkeletonData.h>
|
||||||
|
#include <spine/Bone.h>
|
||||||
|
#include <spine/BoneData.h>
|
||||||
|
#include <spine/AttachmentTimeline.h>
|
||||||
|
#include <spine/DrawOrderTimeline.h>
|
||||||
|
|
||||||
#include <spine/MathUtil.h>
|
#include <spine/MathUtil.h>
|
||||||
#include <spine/ContainerUtil.h>
|
#include <spine/ContainerUtil.h>
|
||||||
@ -325,6 +330,7 @@ namespace Spine
|
|||||||
case EventType_Dispose:
|
case EventType_Dispose:
|
||||||
trackEntry->_onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL);
|
trackEntry->_onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL);
|
||||||
state._onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL);
|
state._onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL);
|
||||||
|
trackEntry->reset();
|
||||||
_trackEntryPool.free(trackEntry);
|
_trackEntryPool.free(trackEntry);
|
||||||
break;
|
break;
|
||||||
case EventType_Event:
|
case EventType_Event:
|
||||||
@ -357,15 +363,748 @@ namespace Spine
|
|||||||
DESTROY(EventQueue, _queue);
|
DESTROY(EventQueue, _queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnimationState::update(float delta)
|
||||||
|
{
|
||||||
|
delta *= _timeScale;
|
||||||
|
for (int i = 0, n = static_cast<int>(_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<int>(_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<int>(current._animation->_timelines.size());
|
||||||
|
Vector<Timeline*>& 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<int>& timelineData = current._timelineData;
|
||||||
|
|
||||||
|
bool firstFrame = current._timelinesRotation.size() == 0;
|
||||||
|
if (firstFrame)
|
||||||
|
{
|
||||||
|
current._timelinesRotation.reserve(timelines.size() << 1);
|
||||||
|
}
|
||||||
|
Vector<float>& 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<RotateTimeline*>(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<int>(_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<int>(_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<TrackEntry*> AnimationState::getTracks()
|
||||||
|
{
|
||||||
|
return _tracks;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AnimationState::getTimeScale()
|
||||||
|
{
|
||||||
|
return _timeScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimationState::setTimeScale(float inValue)
|
||||||
|
{
|
||||||
|
_timeScale = inValue;
|
||||||
|
}
|
||||||
|
|
||||||
void AnimationState::setOnAnimationEventFunc(OnAnimationEventFunc inValue)
|
void AnimationState::setOnAnimationEventFunc(OnAnimationEventFunc inValue)
|
||||||
{
|
{
|
||||||
_onAnimationEventFunc = inValue;
|
_onAnimationEventFunc = inValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation& AnimationState::getEmptyAnimation()
|
Animation* AnimationState::getEmptyAnimation()
|
||||||
{
|
{
|
||||||
static Vector<Timeline*> timelines;
|
static Vector<Timeline*> timelines;
|
||||||
static Animation ret(std::string("<empty>"), timelines, 0);
|
static Animation ret(std::string("<empty>"), timelines, 0);
|
||||||
return ret;
|
return &ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimationState::applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, 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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bone* bone = skeleton._bones[rotateTimeline->_boneIndex];
|
||||||
|
Vector<float> 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<Event*>* eventBuffer = mix < from->_eventThreshold ? &_events : NULL;
|
||||||
|
bool attachments = mix < from->_attachmentThreshold, drawOrder = mix < from->_drawOrderThreshold;
|
||||||
|
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;
|
||||||
|
|
||||||
|
bool firstFrame = from->_timelinesRotation.size() == 0;
|
||||||
|
if (firstFrame)
|
||||||
|
{
|
||||||
|
// from.timelinesRotation.setSize
|
||||||
|
from->_timelinesRotation.reserve(timelines.size() << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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().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<RotateTimeline*>(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<int>(_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<float>::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<int>(_tracks.size()); i < n; ++i)
|
||||||
|
{
|
||||||
|
TrackEntry* entry = _tracks[i];
|
||||||
|
if (entry != NULL)
|
||||||
|
{
|
||||||
|
entry->setTimelineData(NULL, _mixingTo, _propertyIDs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@ namespace Spine
|
|||||||
_attachmentNames.reserve(frameCount);
|
_attachmentNames.reserve(frameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachmentTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void AttachmentTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
assert(_slotIndex < skeleton._slots.size());
|
assert(_slotIndex < skeleton._slots.size());
|
||||||
|
|
||||||
|
|||||||
@ -58,7 +58,7 @@ namespace Spine
|
|||||||
_frames.reserve(frameCount * ENTRIES);
|
_frames.reserve(frameCount * ENTRIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void ColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
Slot* slotP = skeleton._slots[_slotIndex];
|
Slot* slotP = skeleton._slots[_slotIndex];
|
||||||
Slot& slot = *slotP;
|
Slot& slot = *slotP;
|
||||||
|
|||||||
@ -50,7 +50,7 @@ namespace Spine
|
|||||||
_frameVertices.reserve(frameCount);
|
_frameVertices.reserve(frameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
Slot* slotP = skeleton._slots[_slotIndex];
|
Slot* slotP = skeleton._slots[_slotIndex];
|
||||||
Slot& slot = *slotP;
|
Slot& slot = *slotP;
|
||||||
|
|||||||
@ -48,7 +48,7 @@ namespace Spine
|
|||||||
_drawOrders.reserve(frameCount);
|
_drawOrders.reserve(frameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
Vector<Slot*>& drawOrder = skeleton._drawOrder;
|
Vector<Slot*>& drawOrder = skeleton._drawOrder;
|
||||||
Vector<Slot*>& slots = skeleton._slots;
|
Vector<Slot*>& slots = skeleton._slots;
|
||||||
|
|||||||
@ -49,8 +49,15 @@ namespace Spine
|
|||||||
_events.reserve(frameCount);
|
_events.reserve(frameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
|
if (pEvents == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<Event*>& events = *pEvents;
|
||||||
|
|
||||||
if (events.size() == 0)
|
if (events.size() == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -61,7 +68,7 @@ namespace Spine
|
|||||||
if (lastTime > time)
|
if (lastTime > time)
|
||||||
{
|
{
|
||||||
// Fire events after last time for looped animations.
|
// Fire events after last time for looped animations.
|
||||||
apply(skeleton, lastTime, std::numeric_limits<int>::max(), events, alpha, pose, direction);
|
apply(skeleton, lastTime, std::numeric_limits<int>::max(), pEvents, alpha, pose, direction);
|
||||||
lastTime = -1.0f;
|
lastTime = -1.0f;
|
||||||
}
|
}
|
||||||
else if (lastTime >= _frames[frameCount - 1]) // Last time is after last frame.
|
else if (lastTime >= _frames[frameCount - 1]) // Last time is after last frame.
|
||||||
|
|||||||
@ -56,7 +56,7 @@ namespace Spine
|
|||||||
_frames.reserve(frameCount * ENTRIES);
|
_frames.reserve(frameCount * ENTRIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
IkConstraint* constraintP = skeleton._ikConstraints[_ikConstraintIndex];
|
IkConstraint* constraintP = skeleton._ikConstraints[_ikConstraintIndex];
|
||||||
IkConstraint& constraint = *constraintP;
|
IkConstraint& constraint = *constraintP;
|
||||||
|
|||||||
@ -56,7 +56,7 @@ namespace Spine
|
|||||||
_frames.reserve(frameCount * ENTRIES);
|
_frames.reserve(frameCount * ENTRIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex];
|
PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex];
|
||||||
PathConstraint& constraint = *constraintP;
|
PathConstraint& constraint = *constraintP;
|
||||||
|
|||||||
@ -54,7 +54,7 @@ namespace Spine
|
|||||||
_frames.reserve(frameCount * ENTRIES);
|
_frames.reserve(frameCount * ENTRIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex];
|
PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex];
|
||||||
PathConstraint& constraint = *constraintP;
|
PathConstraint& constraint = *constraintP;
|
||||||
|
|||||||
@ -49,7 +49,7 @@ namespace Spine
|
|||||||
// Empty
|
// Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex];
|
PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex];
|
||||||
PathConstraint& constraint = *constraintP;
|
PathConstraint& constraint = *constraintP;
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace Spine
|
|||||||
_frames.reserve(frameCount << 1);
|
_frames.reserve(frameCount << 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
Bone* bone = skeleton.getBones()[_boneIndex];
|
Bone* bone = skeleton.getBones()[_boneIndex];
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@ namespace Spine
|
|||||||
// Empty
|
// Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
Bone* boneP = skeleton._bones[_boneIndex];
|
Bone* boneP = skeleton._bones[_boneIndex];
|
||||||
Bone& bone = *boneP;
|
Bone& bone = *boneP;
|
||||||
|
|||||||
@ -49,7 +49,7 @@ namespace Spine
|
|||||||
// Empty
|
// Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
Bone* boneP = skeleton._bones[_boneIndex];
|
Bone* boneP = skeleton._bones[_boneIndex];
|
||||||
Bone& bone = *boneP;
|
Bone& bone = *boneP;
|
||||||
|
|||||||
@ -60,7 +60,7 @@ namespace Spine
|
|||||||
_frames.reserve(frameCount * ENTRIES);
|
_frames.reserve(frameCount * ENTRIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
TransformConstraint* constraintP = skeleton._transformConstraints[_transformConstraintIndex];
|
TransformConstraint* constraintP = skeleton._transformConstraints[_transformConstraintIndex];
|
||||||
TransformConstraint& constraint = *constraintP;
|
TransformConstraint& constraint = *constraintP;
|
||||||
|
|||||||
@ -56,7 +56,7 @@ namespace Spine
|
|||||||
_frames.reserve(frameCount * ENTRIES);
|
_frames.reserve(frameCount * ENTRIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
Bone* boneP = skeleton._bones[_boneIndex];
|
Bone* boneP = skeleton._bones[_boneIndex];
|
||||||
Bone& bone = *boneP;
|
Bone& bone = *boneP;
|
||||||
|
|||||||
@ -64,7 +64,7 @@ namespace Spine
|
|||||||
_frames.reserve(frameCount * ENTRIES);
|
_frames.reserve(frameCount * ENTRIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
|
void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixPose pose, MixDirection direction)
|
||||||
{
|
{
|
||||||
Slot* slotP = skeleton._slots[_slotIndex];
|
Slot* slotP = skeleton._slots[_slotIndex];
|
||||||
Slot& slot = *slotP;
|
Slot& slot = *slotP;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user