mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 07:14:55 +08:00
wip
This commit is contained in:
parent
9bed800466
commit
0ca6803030
@ -33,6 +33,7 @@
|
||||
|
||||
#include <spine/Vector.h>
|
||||
#include <spine/Pool.h>
|
||||
#include <spine/MixPose.h>
|
||||
|
||||
namespace Spine
|
||||
{
|
||||
@ -51,6 +52,9 @@ namespace Spine
|
||||
|
||||
class Animation;
|
||||
class Event;
|
||||
class AnimationStateData;
|
||||
class Skeleton;
|
||||
class RotateTimeline;
|
||||
|
||||
typedef void (*OnAnimationEventFunc) (AnimationState& state, EventType type, TrackEntry* entry, Event* event);
|
||||
|
||||
@ -58,6 +62,7 @@ namespace Spine
|
||||
class TrackEntry
|
||||
{
|
||||
friend class EventQueue;
|
||||
friend class AnimationState;
|
||||
|
||||
public:
|
||||
TrackEntry();
|
||||
@ -245,12 +250,7 @@ namespace Spine
|
||||
TrackEntry* _entry;
|
||||
Event* _event;
|
||||
|
||||
EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event = NULL)
|
||||
{
|
||||
_type = eventType;
|
||||
_entry = trackEntry;
|
||||
_event = event;
|
||||
}
|
||||
EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event = NULL);
|
||||
};
|
||||
|
||||
class EventQueue
|
||||
@ -259,13 +259,18 @@ namespace Spine
|
||||
|
||||
private:
|
||||
Vector<EventQueueEntry*> _eventQueueEntries;
|
||||
bool _drainDisabled;
|
||||
|
||||
AnimationState& _state;
|
||||
Pool<TrackEntry>& _trackEntryPool;
|
||||
bool _drainDisabled;
|
||||
|
||||
static EventQueue* newEventQueue(AnimationState& state, Pool<TrackEntry>& trackEntryPool);
|
||||
|
||||
static EventQueueEntry* newEventQueueEntry(EventType eventType, TrackEntry* entry, Event* event = NULL);
|
||||
|
||||
EventQueue(AnimationState& state, Pool<TrackEntry>& trackEntryPool);
|
||||
|
||||
|
||||
~EventQueue();
|
||||
|
||||
void start(TrackEntry* entry);
|
||||
|
||||
void interrupt(TrackEntry* entry);
|
||||
@ -276,12 +281,10 @@ namespace Spine
|
||||
|
||||
void complete(TrackEntry* entry);
|
||||
|
||||
void event(TrackEntry* entry, Event* e);
|
||||
void event(TrackEntry* entry, Event* event);
|
||||
|
||||
/// Raises all events in the queue and drains the queue.
|
||||
void drain();
|
||||
|
||||
void clear();
|
||||
};
|
||||
|
||||
class AnimationState
|
||||
@ -290,49 +293,17 @@ namespace Spine
|
||||
friend class EventQueue;
|
||||
|
||||
public:
|
||||
AnimationState();
|
||||
AnimationState(AnimationStateData& data);
|
||||
|
||||
~AnimationState();
|
||||
|
||||
void setOnAnimationEventFunc(OnAnimationEventFunc inValue);
|
||||
|
||||
private:
|
||||
static const int Subsequent, First, Dip, DipMix;
|
||||
// static readonly Animation EmptyAnimation = new Animation("<empty>", new Vector<Timeline>(), 0);
|
||||
|
||||
//
|
||||
// private AnimationStateData data;
|
||||
//
|
||||
// Pool<TrackEntry> trackEntryPool = new Pool<TrackEntry>();
|
||||
// private readonly Vector<TrackEntry> tracks = new Vector<TrackEntry>();
|
||||
// private readonly Vector<Event> events = new Vector<Event>();
|
||||
// private readonly EventQueue queue; // Initialized by constructor.
|
||||
//
|
||||
// private readonly HashSet<int> propertyIDs = new HashSet<int>();
|
||||
// private readonly Vector<TrackEntry> mixingTo = new Vector<TrackEntry>();
|
||||
bool _animationsChanged;
|
||||
//
|
||||
// private float timeScale = 1;
|
||||
//
|
||||
// public AnimationStateData Data { get { return data; } }
|
||||
// /// A list of tracks that have animations, which may contain NULLs.
|
||||
// public Vector<TrackEntry> Tracks { get { return tracks; } }
|
||||
// public float TimeScale { get { return timeScale; } set { timeScale = value; } }
|
||||
//
|
||||
OnAnimationEventFunc _onAnimationEventFunc;
|
||||
//
|
||||
// public AnimationState(AnimationStateData data) {
|
||||
// if (data == NULL) throw new ArgumentNULLException("data", "data cannot be NULL.");
|
||||
// _data = data;
|
||||
// _queue = new EventQueue(
|
||||
// this,
|
||||
// delegate { _animationsChanged = true; },
|
||||
// trackEntryPool
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// ///
|
||||
// /// Increments the track entry times, setting queued animations as current if needed
|
||||
// /// @param delta delta time
|
||||
// public void update(float delta) {
|
||||
///
|
||||
/// 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++) {
|
||||
@ -388,43 +359,18 @@ namespace Spine
|
||||
// }
|
||||
//
|
||||
// queue.drain();
|
||||
// }
|
||||
//
|
||||
// /// Returns true when all mixing from entries are complete.
|
||||
// private 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;
|
||||
// }
|
||||
//
|
||||
// ///
|
||||
// /// 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.
|
||||
// public bool apply(Skeleton skeleton) {
|
||||
// if (skeleton == NULL) throw new ArgumentNULLException("skeleton", "skeleton cannot be NULL.");
|
||||
}
|
||||
|
||||
///
|
||||
/// 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;
|
||||
bool applied = false;
|
||||
// var tracksItems = tracks.Items;
|
||||
// for (int i = 0, m = tracks.Count; i < m; i++) {
|
||||
// TrackEntry current = tracksItems[i];
|
||||
@ -471,10 +417,312 @@ namespace Spine
|
||||
// }
|
||||
//
|
||||
// queue.drain();
|
||||
// return applied;
|
||||
// }
|
||||
return applied;
|
||||
}
|
||||
|
||||
///
|
||||
/// 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();
|
||||
}
|
||||
|
||||
///
|
||||
/// 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;
|
||||
//
|
||||
// private float applyMixingFrom(TrackEntry to, Skeleton skeleton, MixPose currentPose) {
|
||||
// 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)
|
||||
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.
|
||||
/// @param loop If true, the animation will repeat.
|
||||
/// If false, it will not, instead its last frame is applied if played beyond its duration.
|
||||
/// In either case TrackEntry.TrackEnd determines when the track is cleared.
|
||||
/// @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;
|
||||
}
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// @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.
|
||||
///
|
||||
/// @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;
|
||||
}
|
||||
|
||||
///
|
||||
/// 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;
|
||||
}
|
||||
|
||||
///
|
||||
/// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the
|
||||
/// specified mix duration.
|
||||
/// @return
|
||||
/// A track entry to allow further customization of animation playback. References to the track entry must not be kept after AnimationState.Dispose.
|
||||
///
|
||||
/// @param trackIndex Track number.
|
||||
/// @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;
|
||||
}
|
||||
|
||||
///
|
||||
/// 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();
|
||||
}
|
||||
|
||||
/// @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];
|
||||
}
|
||||
|
||||
// AnimationStateData Data { get { return data; } }
|
||||
// /// A list of tracks that have animations, which may contain NULLs.
|
||||
// Vector<TrackEntry> Tracks { get { return tracks; } }
|
||||
// float TimeScale { get { return timeScale; } set { timeScale = value; } }
|
||||
|
||||
private:
|
||||
static const int Subsequent, First, Dip, DipMix;
|
||||
|
||||
AnimationStateData& _data;
|
||||
|
||||
Pool<TrackEntry> _trackEntryPool;
|
||||
Vector<TrackEntry*> _tracks;
|
||||
Vector<Event> _events;
|
||||
EventQueue* _queue;
|
||||
|
||||
Vector<int> _propertyIDs;
|
||||
Vector<TrackEntry> _mixingTo;
|
||||
bool _animationsChanged;
|
||||
|
||||
OnAnimationEventFunc _onAnimationEventFunc;
|
||||
|
||||
float _timeScale;
|
||||
|
||||
static Animation& getEmptyAnimation();
|
||||
|
||||
static void 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.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.
|
||||
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)
|
||||
{
|
||||
// TrackEntry from = to.mixingFrom;
|
||||
// if (from.mixingFrom != NULL) applyMixingFrom(from, skeleton, currentPose);
|
||||
//
|
||||
@ -541,74 +789,11 @@ namespace Spine
|
||||
// from.nextTrackLast = from.trackTime;
|
||||
//
|
||||
// return mix;
|
||||
// }
|
||||
//
|
||||
// static private void applyRotateTimeline(RotateTimeline rotateTimeline, Skeleton skeleton, float time, float alpha, MixPose pose,
|
||||
// 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;
|
||||
// }
|
||||
//
|
||||
// private void queueEvents(TrackEntry entry, float animationTime) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void queueEvents(TrackEntry* entry, float animationTime)
|
||||
{
|
||||
// float animationStart = entry.animationStart, animationEnd = entry.animationEnd;
|
||||
// float duration = animationEnd - animationStart;
|
||||
// float trackLastWrapped = entry.trackLast % duration;
|
||||
@ -636,52 +821,11 @@ namespace Spine
|
||||
// if (e.time < animationStart) continue; // Discard events outside animation start/end.
|
||||
// queue.event(entry, eventsItems[i]);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ///
|
||||
// /// 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.
|
||||
// public 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.
|
||||
// /// 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.
|
||||
// public 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 the active TrackEntry for a given track number.
|
||||
// private void setCurrent(int index, TrackEntry current, bool interrupt) {
|
||||
}
|
||||
|
||||
/// 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;
|
||||
//
|
||||
@ -698,141 +842,22 @@ namespace Spine
|
||||
// }
|
||||
//
|
||||
// queue.start(current); // triggers animationsChanged
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /// Sets an animation by name. setAnimation(int, Animation, bool)
|
||||
// public TrackEntry setAnimation(int trackIndex, 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);
|
||||
// }
|
||||
//
|
||||
// /// Sets the current animation for a track, discarding any queued animations.
|
||||
// /// @param loop If true, the animation will repeat.
|
||||
// /// If false, it will not, instead its last frame is applied if played beyond its duration.
|
||||
// /// In either case TrackEntry.TrackEnd determines when the track is cleared.
|
||||
// /// @return
|
||||
// /// A track entry to allow further customization of animation playback. References to the track entry must not be kept
|
||||
// /// after AnimationState.Dispose.
|
||||
// public TrackEntry setAnimation(int trackIndex, Animation animation, bool loop) {
|
||||
// if (animation == NULL) throw new ArgumentNULLException("animation", "animation cannot be 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.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;
|
||||
// }
|
||||
//
|
||||
// /// Queues an animation by name.
|
||||
// /// addAnimation(int, Animation, bool, float)
|
||||
// public TrackEntry addAnimation(int trackIndex, 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);
|
||||
// }
|
||||
//
|
||||
// /// 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.
|
||||
// /// @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.
|
||||
// ///
|
||||
// /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
|
||||
// /// after AnimationState.Dispose
|
||||
// public TrackEntry addAnimation(int trackIndex, Animation animation, bool loop, float delay) {
|
||||
// if (animation == NULL) throw new ArgumentNULLException("animation", "animation cannot be 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;
|
||||
// }
|
||||
//
|
||||
// ///
|
||||
// /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration.
|
||||
// public TrackEntry setEmptyAnimation(int trackIndex, float mixDuration) {
|
||||
// TrackEntry entry = setAnimation(trackIndex, AnimationState.EmptyAnimation, 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
|
||||
// /// specified mix duration.
|
||||
// /// @return
|
||||
// /// A track entry to allow further customization of animation playback. References to the track entry must not be kept after AnimationState.Dispose.
|
||||
// ///
|
||||
// /// @param trackIndex Track number.
|
||||
// /// @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.
|
||||
// public TrackEntry addEmptyAnimation(int trackIndex, float mixDuration, float delay) {
|
||||
// if (delay <= 0) delay -= mixDuration;
|
||||
// TrackEntry entry = addAnimation(trackIndex, AnimationState.EmptyAnimation, 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.
|
||||
// public 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();
|
||||
// }
|
||||
//
|
||||
// private 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.
|
||||
// /// @param last May be NULL.
|
||||
// private TrackEntry newTrackEntry(int trackIndex, Animation animation, bool loop, TrackEntry last) {
|
||||
// }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// 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;
|
||||
@ -859,19 +884,23 @@ namespace Spine
|
||||
// entry.mixTime = 0;
|
||||
// entry.mixDuration = (last == NULL) ? 0 : data.GetMix(last.animation, animation);
|
||||
// return entry;
|
||||
// }
|
||||
//
|
||||
// /// Dispose all track entries queued after the given TrackEntry.
|
||||
// private void disposeNext(TrackEntry entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Dispose all track entries queued after the given TrackEntry.
|
||||
void disposeNext(TrackEntry* entry)
|
||||
{
|
||||
// TrackEntry next = entry.next;
|
||||
// while (next != NULL) {
|
||||
// while (next != NULL)
|
||||
// {
|
||||
// queue.dispose(next);
|
||||
// next = next.next;
|
||||
// }
|
||||
// entry.next = NULL;
|
||||
// }
|
||||
//
|
||||
// private void animationsChanged() {
|
||||
}
|
||||
|
||||
void animationsChanged()
|
||||
{
|
||||
// animationsChanged = false;
|
||||
//
|
||||
// var propertyIDs = _propertyIDs;
|
||||
@ -879,23 +908,15 @@ namespace Spine
|
||||
// var mixingTo = _mixingTo;
|
||||
//
|
||||
// var tracksItems = tracks.Items;
|
||||
// for (int i = 0, n = tracks.Count; i < n; i++) {
|
||||
// for (int i = 0, n = tracks.Count; i < n; i++)
|
||||
// {
|
||||
// var entry = tracksItems[i];
|
||||
// if (entry != NULL) entry.setTimelineData(NULL, mixingTo, propertyIDs);
|
||||
// if (entry != NULL)
|
||||
// {
|
||||
// entry.setTimelineData(NULL, mixingTo, propertyIDs);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing.
|
||||
// public TrackEntry getCurrent(int trackIndex) {
|
||||
// return (trackIndex >= tracks.Count) ? NULL : tracks.Items[trackIndex];
|
||||
// }
|
||||
//
|
||||
// internal void onStart(TrackEntry entry) { if (Start != NULL) Start(entry); }
|
||||
// internal void onInterrupt(TrackEntry entry) { if (Interrupt != NULL) Interrupt(entry); }
|
||||
// internal void onEnd(TrackEntry entry) { if (End != NULL) End(entry); }
|
||||
// internal void onDispose(TrackEntry entry) { if (Dispose != NULL) Dispose(entry); }
|
||||
// internal void onComplete(TrackEntry entry) { if (Complete != NULL) Complete(entry); }
|
||||
// internal void onEvent(TrackEntry entry, Event e) { if (Event != NULL) Event(entry, e); }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
|
||||
/* All allocation uses these. */
|
||||
#define MALLOC(TYPE,COUNT) ((TYPE*)spineAlloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__))
|
||||
#define NEW(TYPE) ((TYPE*)spineAlloc(sizeof(TYPE), __FILE__, __LINE__))
|
||||
#define REALLOC(PTR,TYPE,COUNT) ((TYPE*)spineRealloc(PTR, sizeof(TYPE) * (COUNT), __FILE__, __LINE__))
|
||||
|
||||
/* Frees memory. Can be used on const types. */
|
||||
|
||||
@ -149,7 +149,7 @@ namespace Spine
|
||||
|
||||
size_t index = hash(key);
|
||||
|
||||
Entry* entry = MALLOC(Entry, 1);
|
||||
Entry* entry = NEW(Entry);
|
||||
new (entry) Entry();
|
||||
entry->_key = key;
|
||||
entry->_value = value;
|
||||
|
||||
@ -62,7 +62,7 @@ namespace Spine
|
||||
}
|
||||
else
|
||||
{
|
||||
T* ret = MALLOC(T, 1);
|
||||
T* ret = NEW(T);
|
||||
new (ret) T();
|
||||
|
||||
return ret;
|
||||
|
||||
@ -32,10 +32,14 @@
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Event.h>
|
||||
#include <spine/AnimationStateData.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/RotateTimeline.h>
|
||||
|
||||
#include <spine/Timeline.h>
|
||||
|
||||
#include <spine/MathUtil.h>
|
||||
#include <spine/ContainerUtil.h>
|
||||
|
||||
namespace Spine
|
||||
{
|
||||
@ -163,27 +167,32 @@ namespace Spine
|
||||
{
|
||||
_timelineData[i] = AnimationState::Subsequent;
|
||||
}
|
||||
else if (to == NULL || !to->hasTimeline(id))
|
||||
{
|
||||
_timelineData[i] = AnimationState::First;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int ii = mixingToLast; ii >= 0; --ii)
|
||||
propertyIDs.push_back(id);
|
||||
|
||||
if (to == NULL || !to->hasTimeline(id))
|
||||
{
|
||||
TrackEntry* entry = mixingToArray[ii];
|
||||
if (!entry->hasTimeline(id))
|
||||
{
|
||||
if (entry->_mixDuration > 0)
|
||||
{
|
||||
_timelineData[i] = AnimationState::DipMix;
|
||||
_timelineDipMix[i] = entry;
|
||||
goto continue_outer; // continue outer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
_timelineData[i] = AnimationState::First;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int ii = mixingToLast; ii >= 0; --ii)
|
||||
{
|
||||
TrackEntry* entry = mixingToArray[ii];
|
||||
if (!entry->hasTimeline(id))
|
||||
{
|
||||
if (entry->_mixDuration > 0)
|
||||
{
|
||||
_timelineData[i] = AnimationState::DipMix;
|
||||
_timelineDipMix[i] = entry;
|
||||
goto continue_outer; // continue outer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
_timelineData[i] = AnimationState::Dip;
|
||||
}
|
||||
_timelineData[i] = AnimationState::Dip;
|
||||
}
|
||||
continue_outer: {}
|
||||
}
|
||||
@ -217,41 +226,70 @@ namespace Spine
|
||||
_onAnimationEventFunc = NULL;
|
||||
}
|
||||
|
||||
EventQueue::EventQueue(AnimationState& state, Pool<TrackEntry>& trackEntryPool) : _state(state), _trackEntryPool(trackEntryPool)
|
||||
EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event) :
|
||||
_type(eventType),
|
||||
_entry(trackEntry),
|
||||
_event(event)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
EventQueue* EventQueue::newEventQueue(AnimationState& state, Pool<TrackEntry>& trackEntryPool)
|
||||
{
|
||||
EventQueue* ret = NEW(EventQueue);
|
||||
new (ret) EventQueue(state, trackEntryPool);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EventQueueEntry* EventQueue::newEventQueueEntry(EventType eventType, TrackEntry* entry, Event* event)
|
||||
{
|
||||
EventQueueEntry* ret = NEW(EventQueueEntry);
|
||||
new (ret) EventQueueEntry(eventType, entry, event);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EventQueue::EventQueue(AnimationState& state, Pool<TrackEntry>& trackEntryPool) : _state(state), _trackEntryPool(trackEntryPool), _drainDisabled(false)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
EventQueue::~EventQueue()
|
||||
{
|
||||
ContainerUtil::cleanUpVectorOfPointers(_eventQueueEntries);
|
||||
}
|
||||
|
||||
void EventQueue::start(TrackEntry* entry)
|
||||
{
|
||||
_eventQueueEntries.push_back(new EventQueueEntry(EventType_Start, entry));
|
||||
_eventQueueEntries.push_back(newEventQueueEntry(EventType_Start, entry));
|
||||
_state._animationsChanged = true;
|
||||
}
|
||||
|
||||
void EventQueue::interrupt(TrackEntry* entry)
|
||||
{
|
||||
_eventQueueEntries.push_back(new EventQueueEntry(EventType_Interrupt, entry));
|
||||
_eventQueueEntries.push_back(newEventQueueEntry(EventType_Interrupt, entry));
|
||||
}
|
||||
|
||||
void EventQueue::end(TrackEntry* entry)
|
||||
{
|
||||
_eventQueueEntries.push_back(new EventQueueEntry(EventType_End, entry));
|
||||
_eventQueueEntries.push_back(newEventQueueEntry(EventType_End, entry));
|
||||
_state._animationsChanged = true;
|
||||
}
|
||||
|
||||
void EventQueue::dispose(TrackEntry* entry)
|
||||
{
|
||||
_eventQueueEntries.push_back(new EventQueueEntry(EventType_Dispose, entry));
|
||||
_eventQueueEntries.push_back(newEventQueueEntry(EventType_Dispose, entry));
|
||||
}
|
||||
|
||||
void EventQueue::complete(TrackEntry* entry)
|
||||
{
|
||||
_eventQueueEntries.push_back(new EventQueueEntry(EventType_Complete, entry));
|
||||
_eventQueueEntries.push_back(newEventQueueEntry(EventType_Complete, entry));
|
||||
}
|
||||
|
||||
void EventQueue::event(TrackEntry* entry, Event* e)
|
||||
void EventQueue::event(TrackEntry* entry, Event* event)
|
||||
{
|
||||
_eventQueueEntries.push_back(new EventQueueEntry(EventType_Event, entry, e));
|
||||
_eventQueueEntries.push_back(newEventQueueEntry(EventType_Event, entry, event));
|
||||
}
|
||||
|
||||
/// Raises all events in the queue and drains the queue.
|
||||
@ -266,7 +304,7 @@ namespace Spine
|
||||
|
||||
AnimationState& state = _state;
|
||||
|
||||
// Don't cache entries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete).
|
||||
// Don't cache _eventQueueEntries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete).
|
||||
for (int i = 0; i < _eventQueueEntries.size(); ++i)
|
||||
{
|
||||
EventQueueEntry* queueEntry = _eventQueueEntries[i];
|
||||
@ -300,23 +338,34 @@ namespace Spine
|
||||
_drainDisabled = false;
|
||||
}
|
||||
|
||||
void EventQueue::clear()
|
||||
{
|
||||
_eventQueueEntries.clear();
|
||||
}
|
||||
|
||||
const int AnimationState::Subsequent = 0;
|
||||
const int AnimationState::First = 1;
|
||||
const int AnimationState::Dip = 2;
|
||||
const int AnimationState::DipMix = 3;
|
||||
|
||||
AnimationState::AnimationState() : _onAnimationEventFunc(dummyOnAnimationEventFunc)
|
||||
AnimationState::AnimationState(AnimationStateData& data) :
|
||||
_data(data),
|
||||
_queue(EventQueue::newEventQueue(*this, _trackEntryPool)),
|
||||
_onAnimationEventFunc(dummyOnAnimationEventFunc),
|
||||
_timeScale(1)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
AnimationState::~AnimationState()
|
||||
{
|
||||
DESTROY(EventQueue, _queue);
|
||||
}
|
||||
|
||||
void AnimationState::setOnAnimationEventFunc(OnAnimationEventFunc inValue)
|
||||
{
|
||||
_onAnimationEventFunc = inValue;
|
||||
}
|
||||
|
||||
Animation& AnimationState::getEmptyAnimation()
|
||||
{
|
||||
static Vector<Timeline*> timelines;
|
||||
static Animation ret(std::string("<empty>"), timelines, 0);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ namespace Spine
|
||||
}
|
||||
strcpy(path + dirLength + needsSlash, name);
|
||||
|
||||
AtlasPage* page = MALLOC(AtlasPage, 1);
|
||||
AtlasPage* page = NEW(AtlasPage);
|
||||
new (page) AtlasPage(std::string(name));
|
||||
|
||||
FREE(name);
|
||||
@ -188,7 +188,7 @@ namespace Spine
|
||||
}
|
||||
else
|
||||
{
|
||||
AtlasRegion* region = MALLOC(AtlasRegion, 1);
|
||||
AtlasRegion* region = NEW(AtlasRegion);
|
||||
new (region) AtlasRegion();
|
||||
|
||||
region->page = page;
|
||||
|
||||
@ -56,7 +56,7 @@ namespace Spine
|
||||
|
||||
AtlasRegion& region = *regionP;
|
||||
|
||||
RegionAttachment* attachmentP = MALLOC(RegionAttachment, 1);
|
||||
RegionAttachment* attachmentP = NEW(RegionAttachment);
|
||||
new (attachmentP) RegionAttachment(name);
|
||||
|
||||
RegionAttachment& attachment = *attachmentP;
|
||||
@ -79,7 +79,7 @@ namespace Spine
|
||||
|
||||
AtlasRegion& region = *regionP;
|
||||
|
||||
MeshAttachment* attachmentP = MALLOC(MeshAttachment, 1);
|
||||
MeshAttachment* attachmentP = NEW(MeshAttachment);
|
||||
new (attachmentP) MeshAttachment(name);
|
||||
|
||||
MeshAttachment& attachment = *attachmentP;
|
||||
@ -101,7 +101,7 @@ namespace Spine
|
||||
|
||||
BoundingBoxAttachment* AtlasAttachmentLoader::newBoundingBoxAttachment(Skin& skin, std::string name)
|
||||
{
|
||||
BoundingBoxAttachment* attachmentP = MALLOC(BoundingBoxAttachment, 1);
|
||||
BoundingBoxAttachment* attachmentP = NEW(BoundingBoxAttachment);
|
||||
new (attachmentP) BoundingBoxAttachment(name);
|
||||
|
||||
return attachmentP;
|
||||
@ -109,7 +109,7 @@ namespace Spine
|
||||
|
||||
PathAttachment* AtlasAttachmentLoader::newPathAttachment(Skin& skin, std::string name)
|
||||
{
|
||||
PathAttachment* attachmentP = MALLOC(PathAttachment, 1);
|
||||
PathAttachment* attachmentP = NEW(PathAttachment);
|
||||
new (attachmentP) PathAttachment(name);
|
||||
|
||||
return attachmentP;
|
||||
@ -117,7 +117,7 @@ namespace Spine
|
||||
|
||||
PointAttachment* AtlasAttachmentLoader::newPointAttachment(Skin& skin, std::string name)
|
||||
{
|
||||
PointAttachment* attachmentP = MALLOC(PointAttachment, 1);
|
||||
PointAttachment* attachmentP = NEW(PointAttachment);
|
||||
new (attachmentP) PointAttachment(name);
|
||||
|
||||
return attachmentP;
|
||||
@ -125,7 +125,7 @@ namespace Spine
|
||||
|
||||
ClippingAttachment* AtlasAttachmentLoader::newClippingAttachment(Skin& skin, std::string name)
|
||||
{
|
||||
ClippingAttachment* attachmentP = MALLOC(ClippingAttachment, 1);
|
||||
ClippingAttachment* attachmentP = NEW(ClippingAttachment);
|
||||
new (attachmentP) ClippingAttachment(name);
|
||||
|
||||
return attachmentP;
|
||||
|
||||
@ -75,13 +75,13 @@ namespace Spine
|
||||
Bone* bone;
|
||||
if (data->getParent() == NULL)
|
||||
{
|
||||
bone = MALLOC(Bone, 1);
|
||||
bone = NEW(Bone);
|
||||
new (bone) Bone(*data, *this, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Bone* parent = _bones[data->getParent()->getIndex()];
|
||||
bone = MALLOC(Bone, 1);
|
||||
bone = NEW(Bone);
|
||||
new (bone) Bone(*data, *this, parent);
|
||||
parent->getChildren().push_back(bone);
|
||||
}
|
||||
@ -96,7 +96,7 @@ namespace Spine
|
||||
SlotData* data = (*i);
|
||||
|
||||
Bone* bone = _bones[data->getBoneData().getIndex()];
|
||||
Slot* slot = MALLOC(Slot, 1);
|
||||
Slot* slot = NEW(Slot);
|
||||
new (slot) Slot(*data, *bone);
|
||||
|
||||
_slots.push_back(slot);
|
||||
@ -108,7 +108,7 @@ namespace Spine
|
||||
{
|
||||
IkConstraintData* data = (*i);
|
||||
|
||||
IkConstraint* constraint = MALLOC(IkConstraint, 1);
|
||||
IkConstraint* constraint = NEW(IkConstraint);
|
||||
new (constraint) IkConstraint(*data, *this);
|
||||
|
||||
_ikConstraints.push_back(constraint);
|
||||
@ -119,7 +119,7 @@ namespace Spine
|
||||
{
|
||||
TransformConstraintData* data = (*i);
|
||||
|
||||
TransformConstraint* constraint = MALLOC(TransformConstraint, 1);
|
||||
TransformConstraint* constraint = NEW(TransformConstraint);
|
||||
new (constraint) TransformConstraint(*data, *this);
|
||||
|
||||
_transformConstraints.push_back(constraint);
|
||||
@ -130,7 +130,7 @@ namespace Spine
|
||||
{
|
||||
PathConstraintData* data = (*i);
|
||||
|
||||
PathConstraint* constraint = MALLOC(PathConstraint, 1);
|
||||
PathConstraint* constraint = NEW(PathConstraint);
|
||||
new (constraint) PathConstraint(*data, *this);
|
||||
|
||||
_pathConstraints.push_back(constraint);
|
||||
|
||||
@ -76,7 +76,7 @@ namespace Spine
|
||||
}
|
||||
else
|
||||
{
|
||||
Polygon* polygonP = MALLOC(Polygon, 1);
|
||||
Polygon* polygonP = NEW(Polygon);
|
||||
new (polygonP) Polygon();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user