mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-09 16:48:43 +08:00
spine-as3 keyable draw order, events, and new AnimationState.
This commit is contained in:
parent
7bd9eeeee6
commit
26832677cb
@ -35,9 +35,10 @@ package {
|
||||
|
||||
import flash.display.Sprite;
|
||||
|
||||
import spine.AnimationStateData;
|
||||
import spine.Event;
|
||||
import spine.SkeletonData;
|
||||
import spine.SkeletonJson;
|
||||
import spine.animation.AnimationStateData;
|
||||
import spine.atlas.Atlas;
|
||||
import spine.attachments.AtlasAttachmentLoader;
|
||||
import spine.flash.SingleTextureLoader;
|
||||
@ -66,16 +67,30 @@ public class Main extends Sprite {
|
||||
stateData.setMixByName("jump", "walk", 0.4);
|
||||
stateData.setMixByName("jump", "jump", 0.2);
|
||||
|
||||
skeleton = new SkeletonAnimation(skeletonData);
|
||||
skeleton.setAnimationStateData(stateData);
|
||||
skeleton = new SkeletonAnimation(skeletonData, stateData);
|
||||
skeleton.x = 320;
|
||||
skeleton.y = 420;
|
||||
|
||||
skeleton.state.onStart = function (trackIndex:int) : void {
|
||||
trace(trackIndex + " start: " + skeleton.state.getCurrent(trackIndex));
|
||||
};
|
||||
skeleton.state.onEnd = function (trackIndex:int) : void {
|
||||
trace(trackIndex + " end: " + skeleton.state.getCurrent(trackIndex));
|
||||
};
|
||||
skeleton.state.onComplete = function (trackIndex:int, count:int) : void {
|
||||
trace(trackIndex + " complete: " + skeleton.state.getCurrent(trackIndex) + ", " + count);
|
||||
};
|
||||
skeleton.state.onEvent = function (trackIndex:int, event:Event) : void {
|
||||
trace(trackIndex + " event: " + skeleton.state.getCurrent(trackIndex) + ", "
|
||||
+ event.data.name + ": " + event.intValue + ", " + event.floatValue + ", " + event.stringValue);
|
||||
};
|
||||
|
||||
if (true) {
|
||||
skeleton.setAnimation("drawOrder", true);
|
||||
skeleton.state.setAnimationByName(0, "drawOrder", true);
|
||||
} else {
|
||||
skeleton.setAnimation("walk", true);
|
||||
skeleton.addAnimation("jump", false, 3);
|
||||
skeleton.addAnimation("walk", true);
|
||||
skeleton.state.setAnimationByName(0, "walk", true);
|
||||
skeleton.state.addAnimationByName(0, "jump", false, 3);
|
||||
skeleton.state.addAnimationByName(0, "walk", true, 0);
|
||||
}
|
||||
|
||||
addChild(skeleton);
|
||||
|
||||
@ -1,188 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtime Software License - Version 1.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms in whole or in part, with
|
||||
* or without modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. A Spine Essential, Professional, Enterprise, or Education License must
|
||||
* be purchased from Esoteric Software and the license must remain valid:
|
||||
* http://esotericsoftware.com/
|
||||
* 2. Redistributions of source code must retain this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer.
|
||||
* 3. Redistributions in binary form must reproduce this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer, in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine {
|
||||
import spine.animation.Animation;
|
||||
|
||||
public class AnimationState {
|
||||
private var _data:AnimationStateData;
|
||||
private var current:Animation;
|
||||
private var previous:Animation;
|
||||
private var currentTime:Number;
|
||||
private var previousTime:Number;
|
||||
private var currentLoop:Boolean;
|
||||
private var previousLoop:Boolean;
|
||||
private var mixTime:Number;
|
||||
private var mixDuration:Number;
|
||||
private var queue:Vector.<QueueEntry> = new Vector.<QueueEntry>();
|
||||
|
||||
public function AnimationState (data:AnimationStateData) {
|
||||
if (data == null)
|
||||
throw new ArgumentError("data cannot be null.");
|
||||
_data = data;
|
||||
}
|
||||
|
||||
public function update (delta:Number) : void {
|
||||
currentTime += delta;
|
||||
previousTime += delta;
|
||||
mixTime += delta;
|
||||
|
||||
if (queue.length > 0) {
|
||||
var entry:QueueEntry = queue[0];
|
||||
if (currentTime >= entry.delay) {
|
||||
setAnimationInternal(entry.animation, entry.loop);
|
||||
queue.shift();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function apply (skeleton:Skeleton) : void {
|
||||
if (!current)
|
||||
return;
|
||||
if (previous) {
|
||||
previous.apply(skeleton, previousTime, previousLoop);
|
||||
var alpha:Number = mixTime / mixDuration;
|
||||
if (alpha >= 1) {
|
||||
alpha = 1;
|
||||
previous = null;
|
||||
}
|
||||
current.mix(skeleton, currentTime, currentLoop, alpha);
|
||||
} else
|
||||
current.apply(skeleton, currentTime, currentLoop);
|
||||
}
|
||||
|
||||
public function clearAnimation () : void {
|
||||
previous = null;
|
||||
current = null;
|
||||
clearQueue();
|
||||
}
|
||||
|
||||
private function clearQueue () : void {
|
||||
queue.length = 0;
|
||||
}
|
||||
|
||||
private function setAnimationInternal (animation:Animation, loop:Boolean) : void {
|
||||
previous = null;
|
||||
if (animation != null && current != null) {
|
||||
mixDuration = _data.getMix(current, animation);
|
||||
if (mixDuration > 0) {
|
||||
mixTime = 0;
|
||||
previous = current;
|
||||
previousTime = currentTime;
|
||||
previousLoop = currentLoop;
|
||||
}
|
||||
}
|
||||
current = animation;
|
||||
currentLoop = loop;
|
||||
currentTime = 0;
|
||||
}
|
||||
|
||||
/** @see #setAnimation(Animation, Boolean) */
|
||||
public function setAnimationByName (animationName:String, loop:Boolean) : void {
|
||||
var animation:Animation = _data.skeletonData.findAnimation(animationName);
|
||||
if (animation == null)
|
||||
throw new ArgumentError("Animation not found: " + animationName);
|
||||
setAnimation(animation, loop);
|
||||
}
|
||||
|
||||
/** Set the current animation. Any queued animations are cleared and the current animation time is set to 0.
|
||||
* @param animation May be null. */
|
||||
public function setAnimation (animation:Animation, loop:Boolean) : void {
|
||||
clearQueue();
|
||||
setAnimationInternal(animation, loop);
|
||||
}
|
||||
|
||||
/** @see #addAnimation(Animation, Boolean, Number) */
|
||||
public function addAnimationByName (animationName:String, loop:Boolean, delay:Number) : void {
|
||||
var animation:Animation = _data.skeletonData.findAnimation(animationName);
|
||||
if (animation == null)
|
||||
throw new ArgumentError("Animation not found: " + animationName);
|
||||
addAnimation(animation, loop, delay);
|
||||
}
|
||||
|
||||
/** Adds an animation to be played delay seconds after the current or last queued animation.
|
||||
* @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */
|
||||
public function addAnimation (animation:Animation, loop:Boolean, delay:Number) : void {
|
||||
var entry:QueueEntry = new QueueEntry();
|
||||
entry.animation = animation;
|
||||
entry.loop = loop;
|
||||
|
||||
if (delay <= 0) {
|
||||
var previousAnimation:Animation = queue.length == 0 ? current : queue[queue.length - 1].animation;
|
||||
if (previousAnimation != null)
|
||||
delay = previousAnimation.duration - _data.getMix(previousAnimation, animation) + delay;
|
||||
else
|
||||
delay = 0;
|
||||
}
|
||||
entry.delay = delay;
|
||||
|
||||
queue.push(entry);
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public function get animation () : Animation {
|
||||
return current;
|
||||
}
|
||||
|
||||
/** Returns the time within the current animation. */
|
||||
public function get time () : Number {
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
public function set time (time:Number) : void {
|
||||
currentTime = time;
|
||||
}
|
||||
|
||||
/** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */
|
||||
public function get isComplete () : Boolean {
|
||||
return current == null || currentTime >= current.duration;
|
||||
}
|
||||
|
||||
public function get data () : AnimationStateData {
|
||||
return _data;
|
||||
}
|
||||
|
||||
public function toString () : String {
|
||||
return (current != null && current.name != null) ? current.name : super.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
import spine.animation.Animation;
|
||||
|
||||
class QueueEntry {
|
||||
public var animation:Animation;
|
||||
public var loop:Boolean;
|
||||
public var delay:Number;
|
||||
}
|
||||
57
spine-as3/spine-as3/src/spine/Event.as
Normal file
57
spine-as3/spine-as3/src/spine/Event.as
Normal file
@ -0,0 +1,57 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtime Software License - Version 1.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms in whole or in part, with
|
||||
* or without modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. A Spine Essential, Professional, Enterprise, or Education License must
|
||||
* be purchased from Esoteric Software and the license must remain valid:
|
||||
* http://esotericsoftware.com/
|
||||
* 2. Redistributions of source code must retain this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer.
|
||||
* 3. Redistributions in binary form must reproduce this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer, in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine {
|
||||
|
||||
public class Event {
|
||||
internal var _data:EventData;
|
||||
public var intValue:int;;
|
||||
public var floatValue:Number;
|
||||
public var stringValue:String;
|
||||
|
||||
public function Event (data:EventData) {
|
||||
if (data == null)
|
||||
throw new ArgumentError("data cannot be null.");
|
||||
_data = data;
|
||||
}
|
||||
|
||||
public function get data () : EventData {
|
||||
return _data;
|
||||
}
|
||||
|
||||
public function toString () : String {
|
||||
return _data._name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
57
spine-as3/spine-as3/src/spine/EventData.as
Normal file
57
spine-as3/spine-as3/src/spine/EventData.as
Normal file
@ -0,0 +1,57 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtime Software License - Version 1.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms in whole or in part, with
|
||||
* or without modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. A Spine Essential, Professional, Enterprise, or Education License must
|
||||
* be purchased from Esoteric Software and the license must remain valid:
|
||||
* http://esotericsoftware.com/
|
||||
* 2. Redistributions of source code must retain this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer.
|
||||
* 3. Redistributions in binary form must reproduce this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer, in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine {
|
||||
|
||||
public class EventData {
|
||||
internal var _name:String;
|
||||
public var intValue:int;;
|
||||
public var floatValue:Number;
|
||||
public var stringValue:String;
|
||||
|
||||
public function EventData (name:String) {
|
||||
if (name == null)
|
||||
throw new ArgumentError("name cannot be null.");
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public function get name () : String {
|
||||
return _name;
|
||||
}
|
||||
|
||||
public function toString () : String {
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -40,6 +40,7 @@ public class SkeletonData {
|
||||
public var slots:Vector.<SlotData> = new Vector.<SlotData>(); // Setup pose draw order.
|
||||
public var skins:Vector.<Skin> = new Vector.<Skin>();
|
||||
public var defaultSkin:Skin;
|
||||
public var eventDatas:Vector.<EventData> = new Vector.<EventData>();
|
||||
public var animations:Vector.<Animation> = new Vector.<Animation>();
|
||||
|
||||
// --- Bones.
|
||||
@ -119,15 +120,35 @@ public class SkeletonData {
|
||||
return skin;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// --- Events.
|
||||
|
||||
public function addEvent (eventData:EventData) : void {
|
||||
if (eventData == null)
|
||||
throw new ArgumentError("eventData cannot be null.");
|
||||
eventDatas.push(eventData);
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public function findEvent (eventName:String) : EventData {
|
||||
if (eventName == null)
|
||||
throw new ArgumentError("eventName cannot be null.");
|
||||
for (var i:int = 0, n:int = eventDatas.length; i < n; i++) {
|
||||
var eventData:EventData = eventDatas[i];
|
||||
if (eventData.name == eventName)
|
||||
return eventData;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// --- Animations.
|
||||
|
||||
|
||||
public function addAnimation (animation:Animation) : void {
|
||||
if (animation == null)
|
||||
throw new ArgumentError("animation cannot be null.");
|
||||
animations.push(animation);
|
||||
}
|
||||
|
||||
|
||||
/** @return May be null. */
|
||||
public function findAnimation (animationName:String) : Animation {
|
||||
if (animationName == null)
|
||||
|
||||
@ -38,6 +38,8 @@ import spine.animation.Animation;
|
||||
import spine.animation.AttachmentTimeline;
|
||||
import spine.animation.ColorTimeline;
|
||||
import spine.animation.CurveTimeline;
|
||||
import spine.animation.DrawOrderTimeline;
|
||||
import spine.animation.EventTimeline;
|
||||
import spine.animation.RotateTimeline;
|
||||
import spine.animation.ScaleTimeline;
|
||||
import spine.animation.Timeline;
|
||||
@ -142,6 +144,19 @@ public class SkeletonJson {
|
||||
skeletonData.defaultSkin = skin;
|
||||
}
|
||||
|
||||
// Events.
|
||||
var events:Object = root["events"];
|
||||
if (events) {
|
||||
for (var eventName:String in events) {
|
||||
var eventMap:Object = events[eventName];
|
||||
var eventData:EventData = new EventData(eventName);
|
||||
eventData.intValue = eventMap["int"] || 0;
|
||||
eventData.floatValue = eventMap["float"] || 0;
|
||||
eventData.stringValue = eventMap["string"] || null;
|
||||
skeletonData.addEvent(eventData);
|
||||
}
|
||||
}
|
||||
|
||||
// Animations.
|
||||
var animations:Object = root["animations"];
|
||||
for (var animationName:String in animations)
|
||||
@ -265,6 +280,59 @@ public class SkeletonJson {
|
||||
}
|
||||
}
|
||||
|
||||
var eventsMap:Object = map["events"];
|
||||
if (eventsMap) {
|
||||
var timeline4:EventTimeline = new EventTimeline(eventsMap.Count);
|
||||
var frameIndex4:int = 0;
|
||||
for each (var eventMap:Object in eventsMap) {
|
||||
var eventData:EventData = skeletonData.findEvent(eventMap["name"]);
|
||||
if (eventData == null) throw new Error("Event not found: " + eventMap["name"]);
|
||||
var event:Event = new Event(eventData);
|
||||
event.intValue = eventMap.hasOwnProperty("int") ? eventMap["int"] : eventData.intValue;
|
||||
event.floatValue = eventMap.hasOwnProperty("float") ? eventMap["float"] : eventData.floatValue;
|
||||
event.stringValue = eventMap.hasOwnProperty("string") ? eventMap["string"] : eventData.stringValue;
|
||||
timeline4.setFrame(frameIndex4++, eventMap["time"], event);
|
||||
}
|
||||
timelines.push(timeline4);
|
||||
duration = Math.max(duration, timeline.frames[timeline4.frameCount - 1]);
|
||||
}
|
||||
|
||||
var drawOrderValues:Object = map["draworder"];
|
||||
if (drawOrderValues) {
|
||||
var timeline5:DrawOrderTimeline = new DrawOrderTimeline(drawOrderValues.length);
|
||||
var slotCount:int = skeletonData.slots.length;
|
||||
var frameIndex5:int = 0;
|
||||
for each (var drawOrderMap:Object in drawOrderValues) {
|
||||
var drawOrder:Vector.<int> = null;
|
||||
if (drawOrderMap["offsets"]) {
|
||||
drawOrder = new Vector.<int>(slotCount);
|
||||
for (var i:int = slotCount - 1; i >= 0; i--)
|
||||
drawOrder[i] = -1;
|
||||
var offsets:Object = drawOrderMap["offsets"];
|
||||
var unchanged:Vector.<int> = new Vector.<int>(slotCount - offsets.length);
|
||||
var originalIndex:int = 0, unchangedIndex:int = 0;
|
||||
for each (var offsetMap:Object in offsets) {
|
||||
var slotIndex2:int = skeletonData.findSlotIndex(offsetMap["slot"]);
|
||||
if (slotIndex2 == -1) throw new Error("Slot not found: " + offsetMap["slot"]);
|
||||
// Collect unchanged items.
|
||||
while (originalIndex != slotIndex2)
|
||||
unchanged[unchangedIndex++] = originalIndex++;
|
||||
// Set changed items.
|
||||
drawOrder[originalIndex + offsetMap["offset"]] = originalIndex++;
|
||||
}
|
||||
// Collect remaining unchanged items.
|
||||
while (originalIndex < slotCount)
|
||||
unchanged[unchangedIndex++] = originalIndex++;
|
||||
// Fill in unchanged items.
|
||||
for (i = slotCount - 1; i >= 0; i--)
|
||||
if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex];
|
||||
}
|
||||
timeline5.setFrame(frameIndex5++, drawOrderMap["time"], drawOrder);
|
||||
}
|
||||
timelines.push(timeline5);
|
||||
duration = Math.max(duration, timeline5.frames[timeline5.frameCount - 1]);
|
||||
}
|
||||
|
||||
skeletonData.addAnimation(new Animation(name, timelines, duration));
|
||||
}
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
public class Animation {
|
||||
@ -54,28 +55,32 @@ public class Animation {
|
||||
}
|
||||
|
||||
/** Poses the skeleton at the specified time for this animation. */
|
||||
public function apply (skeleton:Skeleton, time:Number, loop:Boolean) : void {
|
||||
public function apply (skeleton:Skeleton, lastTime:Number, time:Number, loop:Boolean, events:Vector.<Event>) : void {
|
||||
if (skeleton == null)
|
||||
throw new ArgumentError("skeleton cannot be null.");
|
||||
|
||||
if (loop && duration != 0)
|
||||
if (loop && duration != 0) {
|
||||
time %= duration;
|
||||
lastTime %= duration;
|
||||
}
|
||||
|
||||
for (var i:int = 0, n:int = timelines.length; i < n; i++)
|
||||
timelines[i].apply(skeleton, time, 1);
|
||||
timelines[i].apply(skeleton, lastTime, time, events, 1);
|
||||
}
|
||||
|
||||
/** Poses the skeleton at the specified time for this animation mixed with the current pose.
|
||||
* @param alpha The amount of this animation that affects the current pose. */
|
||||
public function mix (skeleton:Skeleton, time:Number, loop:Boolean, alpha:Number) : void {
|
||||
public function mix (skeleton:Skeleton, lastTime:Number, time:Number, loop:Boolean, events:Vector.<Event>, alpha:Number) : void {
|
||||
if (skeleton == null)
|
||||
throw new ArgumentError("skeleton cannot be null.");
|
||||
|
||||
if (loop && duration != 0)
|
||||
if (loop && duration != 0) {
|
||||
time %= duration;
|
||||
lastTime %= duration;
|
||||
}
|
||||
|
||||
for (var i:int = 0, n:int = timelines.length; i < n; i++)
|
||||
timelines[i].apply(skeleton, time, alpha);
|
||||
timelines[i].apply(skeleton, lastTime, time, events, alpha);
|
||||
}
|
||||
|
||||
public function get name () : String {
|
||||
|
||||
240
spine-as3/spine-as3/src/spine/animation/AnimationState.as
Normal file
240
spine-as3/spine-as3/src/spine/animation/AnimationState.as
Normal file
@ -0,0 +1,240 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtime Software License - Version 1.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms in whole or in part, with
|
||||
* or without modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. A Spine Essential, Professional, Enterprise, or Education License must
|
||||
* be purchased from Esoteric Software and the license must remain valid:
|
||||
* http://esotericsoftware.com/
|
||||
* 2. Redistributions of source code must retain this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer.
|
||||
* 3. Redistributions in binary form must reproduce this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer, in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
public class AnimationState {
|
||||
private var _data:AnimationStateData;
|
||||
private var _tracks:Vector.<TrackEntry> = new Vector.<TrackEntry>();
|
||||
private var _events:Vector.<Event> = new Vector.<Event>();
|
||||
public var onStart:Function, onEnd:Function, onComplete:Function, onEvent:Function;
|
||||
public var timeScale:Number = 1;
|
||||
|
||||
public function AnimationState (data:AnimationStateData) {
|
||||
if (!data) throw new ArgumentError("data cannot be null.");
|
||||
_data = data;
|
||||
}
|
||||
|
||||
public function update (delta:Number) : void {
|
||||
delta *= timeScale;
|
||||
for (var i:int = 0; i < _tracks.length; i++) {
|
||||
var current:TrackEntry = _tracks[i];
|
||||
if (!current) continue;
|
||||
|
||||
var trackDelta:Number = delta * current.timeScale;
|
||||
var time:Number = current.time + trackDelta;
|
||||
var endTime:Number = current.endTime;
|
||||
|
||||
current.time = time;
|
||||
if (current.previous) {
|
||||
current.previous.time += trackDelta;
|
||||
current.mixTime += trackDelta;
|
||||
}
|
||||
|
||||
// Check if completed the animation or a loop iteration.
|
||||
if (current.loop ? (current.lastTime % endTime > time % endTime) : (current.lastTime < endTime && time >= endTime)) {
|
||||
var count:int = (int)(time / endTime);
|
||||
if (current.onComplete != null) current.onComplete(i, count);
|
||||
if (onComplete != null) onComplete(i, count);
|
||||
}
|
||||
|
||||
var next:TrackEntry = current.next;
|
||||
if (next) {
|
||||
if (time - trackDelta > next.delay) setCurrent(i, next);
|
||||
} else {
|
||||
// End non-looping animation when it reaches its end time and there is no next entry.
|
||||
if (!current.loop && current.lastTime >= current.endTime) clearTrack(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function apply (skeleton:Skeleton) : void {
|
||||
for (var i:int = 0; i < _tracks.length; i++) {
|
||||
var current:TrackEntry = _tracks[i];
|
||||
if (!current) continue;
|
||||
|
||||
_events.length = 0;
|
||||
|
||||
var time:Number = current.time;
|
||||
var loop:Boolean = current.loop;
|
||||
if (!loop && time > current.endTime) time = current.endTime;
|
||||
|
||||
var previous:TrackEntry = current.previous;
|
||||
if (!previous)
|
||||
current.animation.apply(skeleton, current.lastTime, time, loop, _events);
|
||||
else {
|
||||
var previousTime:Number = previous.time;
|
||||
if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
|
||||
previous.animation.apply(skeleton, previousTime, previousTime, previous.loop, null);
|
||||
|
||||
var alpha:Number = current.mixTime / current.mixDuration;
|
||||
if (alpha >= 1) {
|
||||
alpha = 1;
|
||||
current.previous = null;
|
||||
}
|
||||
current.animation.mix(skeleton, current.lastTime, time, loop, _events, alpha);
|
||||
}
|
||||
|
||||
for each (var event:Event in _events) {
|
||||
if (current.onEvent != null) current.onEvent(i, event);
|
||||
if (onEvent != null) onEvent(i, event);
|
||||
}
|
||||
|
||||
current.lastTime = current.time;
|
||||
}
|
||||
}
|
||||
|
||||
public function clearTracks () : void {
|
||||
for (var i:int = 0, n:int = _tracks.length; i < n; i++)
|
||||
clearTrack(i);
|
||||
_tracks.length = 0;
|
||||
}
|
||||
|
||||
public function clearTrack (trackIndex:int) : void {
|
||||
if (trackIndex >= _tracks.length) return;
|
||||
var current:TrackEntry = _tracks[trackIndex];
|
||||
if (!current) return;
|
||||
|
||||
if (current.onEnd != null) current.onEnd(trackIndex);
|
||||
if (onEnd != null) onEnd(trackIndex);
|
||||
|
||||
_tracks[trackIndex] = null;
|
||||
}
|
||||
|
||||
private function expandToIndex (index:int) : TrackEntry {
|
||||
if (index < _tracks.length) return _tracks[index];
|
||||
while (index >= _tracks.length)
|
||||
_tracks.push(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
private function setCurrent (index:int, entry:TrackEntry) : void {
|
||||
var current:TrackEntry = expandToIndex(index);
|
||||
if (current) {
|
||||
current.previous = null;
|
||||
|
||||
if (current.onEnd != null) current.onEnd(index);
|
||||
if (onEnd != null) onEnd(index);
|
||||
|
||||
entry.mixDuration = _data.getMix(current.animation, entry.animation);
|
||||
if (entry.mixDuration > 0) {
|
||||
entry.mixTime = 0;
|
||||
entry.previous = current;
|
||||
}
|
||||
}
|
||||
|
||||
_tracks[index] = entry;
|
||||
|
||||
if (entry.onStart != null) entry.onStart(index);
|
||||
if (onStart != null) onStart(index);
|
||||
}
|
||||
|
||||
public function setAnimationByName (trackIndex:int, animationName:String, loop:Boolean) : TrackEntry {
|
||||
var animation:Animation = _data._skeletonData.findAnimation(animationName);
|
||||
if (!animation) throw new ArgumentError("Animation not found: " + animationName);
|
||||
return setAnimation(trackIndex, animation, loop);
|
||||
}
|
||||
|
||||
/** Set the current animation. Any queued animations are cleared. */
|
||||
public function setAnimation (trackIndex:int, animation:Animation, loop:Boolean) : TrackEntry {
|
||||
var entry:TrackEntry = new TrackEntry();
|
||||
entry.animation = animation;
|
||||
entry.loop = loop;
|
||||
entry.endTime = animation.duration;
|
||||
setCurrent(trackIndex, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
public function addAnimationByName (trackIndex:int, animationName:String, loop:Boolean, delay:Number) : TrackEntry {
|
||||
var animation:Animation = _data._skeletonData.findAnimation(animationName);
|
||||
if (!animation) throw new ArgumentError("Animation not found: " + animationName);
|
||||
return addAnimation(trackIndex, animation, loop, delay);
|
||||
}
|
||||
|
||||
/** Adds an animation to be played delay seconds after the current or last queued animation.
|
||||
* @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */
|
||||
public function addAnimation (trackIndex:int, animation:Animation, loop:Boolean, delay:Number) : TrackEntry {
|
||||
var entry:TrackEntry = new TrackEntry();
|
||||
entry.animation = animation;
|
||||
entry.loop = loop;
|
||||
entry.endTime = animation.duration;
|
||||
|
||||
var last:TrackEntry = expandToIndex(trackIndex);
|
||||
if (last) {
|
||||
while (last.next)
|
||||
last = last.next;
|
||||
last.next = entry;
|
||||
} else
|
||||
_tracks[trackIndex] = entry;
|
||||
|
||||
if (delay <= 0) {
|
||||
if (last)
|
||||
delay += last.endTime - _data.getMix(last.animation, animation);
|
||||
else
|
||||
delay = 0;
|
||||
}
|
||||
entry.delay = delay;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/** May be null. */
|
||||
public function getCurrent (trackIndex:int) : TrackEntry {
|
||||
if (trackIndex >= _tracks.length) return null;
|
||||
return _tracks[trackIndex];
|
||||
}
|
||||
|
||||
public function toString () : String {
|
||||
var buffer:String = "";
|
||||
for each (var entry:TrackEntry in _tracks) {
|
||||
if (!entry) continue;
|
||||
if (buffer.length > 0) buffer += ", ";
|
||||
buffer += entry.toString();
|
||||
}
|
||||
if (buffer.length == 0) return "<none>";
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
import spine.animation.Animation;
|
||||
|
||||
class QueueEntry {
|
||||
public var animation:Animation;
|
||||
public var loop:Boolean;
|
||||
public var delay:Number;
|
||||
}
|
||||
@ -31,11 +31,11 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine {
|
||||
import spine.animation.Animation;
|
||||
package spine.animation {
|
||||
import spine.SkeletonData;
|
||||
|
||||
public class AnimationStateData {
|
||||
private var _skeletonData:SkeletonData;
|
||||
internal var _skeletonData:SkeletonData;
|
||||
private var animationToMixTime:Object = new Object();
|
||||
public var defaultMix:Number = 0;
|
||||
|
||||
@ -32,22 +32,21 @@
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
public class AttachmentTimeline implements Timeline {
|
||||
public var slotIndex:int;
|
||||
private var _frameCount:int;
|
||||
public var frames:Vector.<Number> = new Vector.<Number>(); // time, ...
|
||||
public var attachmentNames:Vector.<String> = new Vector.<String>();
|
||||
|
||||
public function AttachmentTimeline (frameCount:int) {
|
||||
_frameCount = frameCount;
|
||||
frames.length = frameCount;
|
||||
attachmentNames.length = frameCount;
|
||||
}
|
||||
|
||||
public function get frameCount () : int {
|
||||
return _frameCount;
|
||||
return frames.length;
|
||||
}
|
||||
|
||||
/** Sets the time and value of the specified keyframe. */
|
||||
@ -56,7 +55,7 @@ public class AttachmentTimeline implements Timeline {
|
||||
attachmentNames[frameIndex] = attachmentName;
|
||||
}
|
||||
|
||||
public function apply (skeleton:Skeleton, time:Number, alpha:Number) : void {
|
||||
public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
|
||||
if (time < frames[0])
|
||||
return; // Time is before first frame.
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
import spine.Slot;
|
||||
|
||||
@ -60,7 +61,7 @@ public class ColorTimeline extends CurveTimeline {
|
||||
frames[frameIndex + 4] = a;
|
||||
}
|
||||
|
||||
override public function apply (skeleton:Skeleton, time:Number, alpha:Number) : void {
|
||||
override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
|
||||
if (time < frames[0])
|
||||
return; // Time is before first frame.
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
/** Base class for frames that use an interpolation bezier curve. */
|
||||
@ -41,18 +42,16 @@ public class CurveTimeline implements Timeline {
|
||||
static private const BEZIER_SEGMENTS:int = 10;
|
||||
|
||||
private var curves:Vector.<Number> = new Vector.<Number>(); // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ...
|
||||
private var _frameCount:int;
|
||||
|
||||
public function CurveTimeline (frameCount:int) {
|
||||
_frameCount = frameCount;
|
||||
curves.length = frameCount * 6;
|
||||
}
|
||||
|
||||
public function apply (skeleton:Skeleton, time:Number, alpha:Number) : void {
|
||||
public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
|
||||
}
|
||||
|
||||
public function get frameCount () : int {
|
||||
return _frameCount;
|
||||
return curves.length / 6;
|
||||
}
|
||||
|
||||
public function setLinear (frameIndex:int) : void {
|
||||
|
||||
82
spine-as3/spine-as3/src/spine/animation/DrawOrderTimeline.as
Normal file
82
spine-as3/spine-as3/src/spine/animation/DrawOrderTimeline.as
Normal file
@ -0,0 +1,82 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtime Software License - Version 1.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms in whole or in part, with
|
||||
* or without modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. A Spine Essential, Professional, Enterprise, or Education License must
|
||||
* be purchased from Esoteric Software and the license must remain valid:
|
||||
* http://esotericsoftware.com/
|
||||
* 2. Redistributions of source code must retain this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer.
|
||||
* 3. Redistributions in binary form must reproduce this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer, in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
import spine.Slot;
|
||||
|
||||
public class DrawOrderTimeline implements Timeline {
|
||||
public var frames:Vector.<Number> = new Vector.<Number>(); // time, ...
|
||||
public var drawOrders:Vector.<Vector.<int>> = new Vector.<Vector.<int>>();
|
||||
|
||||
public function DrawOrderTimeline (frameCount:int) {
|
||||
frames.length = frameCount;
|
||||
drawOrders.length = frameCount;
|
||||
}
|
||||
|
||||
public function get frameCount () : int {
|
||||
return frames.length;
|
||||
}
|
||||
|
||||
/** Sets the time and value of the specified keyframe. */
|
||||
public function setFrame (frameIndex:int, time:Number, drawOrder:Vector.<int>) : void {
|
||||
frames[frameIndex] = time;
|
||||
drawOrders[frameIndex] = drawOrder;
|
||||
}
|
||||
|
||||
public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
|
||||
if (time < frames[0])
|
||||
return; // Time is before first frame.
|
||||
|
||||
var frameIndex:int;
|
||||
if (time >= frames[frames.length - 1]) // Time is after last frame.
|
||||
frameIndex = frames.length - 1;
|
||||
else
|
||||
frameIndex = Animation.binarySearch(frames, time, 1) - 1;
|
||||
|
||||
var drawOrder:Vector.<Slot> = skeleton.drawOrder;
|
||||
var slots:Vector.<Slot> = skeleton.slots;
|
||||
var drawOrderToSetupIndex:Vector.<int> = drawOrders[frameIndex];
|
||||
var i:int = 0;
|
||||
if (drawOrderToSetupIndex == null) {
|
||||
for each (var slot:Slot in skeleton.slots)
|
||||
drawOrder[i++] = slot;
|
||||
} else {
|
||||
for each (var setupIndex:int in drawOrderToSetupIndex)
|
||||
drawOrder[i++] = skeleton.slots[setupIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
84
spine-as3/spine-as3/src/spine/animation/EventTimeline.as
Normal file
84
spine-as3/spine-as3/src/spine/animation/EventTimeline.as
Normal file
@ -0,0 +1,84 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtime Software License - Version 1.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms in whole or in part, with
|
||||
* or without modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. A Spine Essential, Professional, Enterprise, or Education License must
|
||||
* be purchased from Esoteric Software and the license must remain valid:
|
||||
* http://esotericsoftware.com/
|
||||
* 2. Redistributions of source code must retain this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer.
|
||||
* 3. Redistributions in binary form must reproduce this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer, in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
import spine.Slot;
|
||||
|
||||
public class EventTimeline implements Timeline {
|
||||
public var frames:Vector.<Number> = new Vector.<Number>(); // time, ...
|
||||
public var events:Vector.<Event> = new Vector.<Event>();
|
||||
|
||||
public function EventTimeline (frameCount:int) {
|
||||
frames.length = frameCount;
|
||||
events.length = frameCount;
|
||||
}
|
||||
|
||||
public function get frameCount () : int {
|
||||
return frames.length;
|
||||
}
|
||||
|
||||
/** Sets the time and value of the specified keyframe. */
|
||||
public function setFrame (frameIndex:int, time:Number, event:Event) : void {
|
||||
frames[frameIndex] = time;
|
||||
events[frameIndex] = event;
|
||||
}
|
||||
|
||||
public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
|
||||
if (!firedEvents) return;
|
||||
|
||||
if (lastTime >= frames[frameCount - 1]) return; // Last time is after last frame.
|
||||
|
||||
if (lastTime > time) { // Fire events after last time for looped animations.
|
||||
apply(skeleton, lastTime, int.MAX_VALUE, firedEvents, alpha);
|
||||
lastTime = 0;
|
||||
}
|
||||
|
||||
var frameIndex:int;
|
||||
if (lastTime <= frames[0] || frameCount == 1)
|
||||
frameIndex = 0;
|
||||
else {
|
||||
frameIndex = Animation.binarySearch(frames, lastTime, 1);
|
||||
var frame:Number = frames[frameIndex];
|
||||
while (frameIndex > 0) { // Fire multiple events with the same frame.
|
||||
if (frames[frameIndex - 1] != frame) break;
|
||||
frameIndex--;
|
||||
}
|
||||
}
|
||||
for (; frameIndex < frameCount && time >= frames[frameIndex]; frameIndex++)
|
||||
firedEvents.push(events[frameIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -33,6 +33,7 @@
|
||||
|
||||
package spine.animation {
|
||||
import spine.Bone;
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
public class RotateTimeline extends CurveTimeline {
|
||||
@ -54,7 +55,7 @@ public class RotateTimeline extends CurveTimeline {
|
||||
frames[frameIndex + 1] = angle;
|
||||
}
|
||||
|
||||
override public function apply (skeleton:Skeleton, time:Number, alpha:Number) : void {
|
||||
override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
|
||||
if (time < frames[0])
|
||||
return; // Time is before first frame.
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
|
||||
package spine.animation {
|
||||
import spine.Bone;
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
public class ScaleTimeline extends TranslateTimeline {
|
||||
@ -40,7 +41,7 @@ public class ScaleTimeline extends TranslateTimeline {
|
||||
super(frameCount);
|
||||
}
|
||||
|
||||
override public function apply (skeleton:Skeleton, time:Number, alpha:Number) : void {
|
||||
override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
|
||||
if (time < frames[0])
|
||||
return; // Time is before first frame.
|
||||
|
||||
|
||||
@ -32,11 +32,12 @@
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
public interface Timeline {
|
||||
/** Sets the value(s) for the specified time. */
|
||||
function apply (skeleton:Skeleton, time:Number, alpha:Number) : void;
|
||||
function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
52
spine-as3/spine-as3/src/spine/animation/TrackEntry.as
Normal file
52
spine-as3/spine-as3/src/spine/animation/TrackEntry.as
Normal file
@ -0,0 +1,52 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtime Software License - Version 1.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms in whole or in part, with
|
||||
* or without modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. A Spine Essential, Professional, Enterprise, or Education License must
|
||||
* be purchased from Esoteric Software and the license must remain valid:
|
||||
* http://esotericsoftware.com/
|
||||
* 2. Redistributions of source code must retain this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer.
|
||||
* 3. Redistributions in binary form must reproduce this license, which is the
|
||||
* above copyright notice, this declaration of conditions and the following
|
||||
* disclaimer, in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
public class TrackEntry {
|
||||
public var next:TrackEntry;
|
||||
internal var previous:TrackEntry;
|
||||
public var animation:Animation;
|
||||
public var loop:Boolean;
|
||||
public var delay:Number, time:Number = 0, lastTime:Number = 0, endTime:Number, timeScale:Number = 1;
|
||||
internal var mixTime:Number, mixDuration:Number;
|
||||
public var onStart:Function, onEnd:Function, onComplete:Function, onEvent:Function;
|
||||
|
||||
public function toString () : String {
|
||||
return animation == null ? "<none>" : animation.name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -33,6 +33,7 @@
|
||||
|
||||
package spine.animation {
|
||||
import spine.Bone;
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
public class TranslateTimeline extends CurveTimeline {
|
||||
@ -56,7 +57,7 @@ public class TranslateTimeline extends CurveTimeline {
|
||||
frames[frameIndex + 2] = y;
|
||||
}
|
||||
|
||||
override public function apply (skeleton:Skeleton, time:Number, alpha:Number) : void {
|
||||
override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
|
||||
if (time < frames[0])
|
||||
return; // Time is before first frame.
|
||||
|
||||
|
||||
@ -32,64 +32,24 @@
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.flash {
|
||||
import spine.AnimationState;
|
||||
import spine.AnimationStateData;
|
||||
import spine.SkeletonData;
|
||||
import spine.animation.AnimationState;
|
||||
import spine.animation.AnimationStateData;
|
||||
|
||||
public class SkeletonAnimation extends SkeletonSprite {
|
||||
public var states:Vector.<AnimationState> = new Vector.<AnimationState>();
|
||||
public var state:AnimationState;
|
||||
|
||||
public function SkeletonAnimation (skeletonData:SkeletonData) {
|
||||
public function SkeletonAnimation (skeletonData:SkeletonData, stateData:AnimationStateData = null) {
|
||||
super(skeletonData);
|
||||
addAnimationState();
|
||||
state = new AnimationState(stateData ? stateData : new AnimationStateData(skeletonData));
|
||||
}
|
||||
|
||||
override public function advanceTime (time:Number) : void {
|
||||
for each (var state:AnimationState in states) {
|
||||
state.update(time);
|
||||
state.apply(skeleton);
|
||||
}
|
||||
state.update(time);
|
||||
state.apply(skeleton);
|
||||
skeleton.updateWorldTransform();
|
||||
super.advanceTime(time);
|
||||
}
|
||||
|
||||
public function addAnimationState (stateData:AnimationStateData = null) : void {
|
||||
if (!stateData)
|
||||
stateData = new AnimationStateData(skeleton.data);
|
||||
states.push(new AnimationState(stateData));
|
||||
}
|
||||
|
||||
public function setAnimationStateData (stateData:AnimationStateData, stateIndex:int = 0) : void {
|
||||
if (stateIndex < 0 || stateIndex >= states.length)
|
||||
throw new ArgumentError("stateIndex out of range.");
|
||||
if (!stateData)
|
||||
throw new ArgumentError("stateData cannot be null.");
|
||||
states[stateIndex] = new AnimationState(stateData);
|
||||
}
|
||||
|
||||
public function setMix (fromAnimation:String, toAnimation:String, duration:Number, stateIndex:int = 0) : void {
|
||||
if (stateIndex < 0 || stateIndex >= states.length)
|
||||
throw new ArgumentError("stateIndex out of range.");
|
||||
states[stateIndex].data.setMixByName(fromAnimation, toAnimation, duration);
|
||||
}
|
||||
|
||||
public function setAnimation (name:String, loop:Boolean, stateIndex:int = 0) : void {
|
||||
if (stateIndex < 0 || stateIndex >= states.length)
|
||||
throw new ArgumentError("stateIndex out of range.");
|
||||
states[stateIndex].setAnimationByName(name, loop);
|
||||
}
|
||||
|
||||
public function addAnimation (name:String, loop:Boolean, delay:Number = 0, stateIndex:int = 0) : void {
|
||||
if (stateIndex < 0 || stateIndex >= states.length)
|
||||
throw new ArgumentError("stateIndex out of range.");
|
||||
states[stateIndex].addAnimationByName(name, loop, delay);
|
||||
}
|
||||
|
||||
public function clearAnimation (stateIndex:int = 0) : void {
|
||||
if (stateIndex < 0 || stateIndex >= states.length)
|
||||
throw new ArgumentError("stateIndex out of range.");
|
||||
states[stateIndex].clearAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
package {
|
||||
|
||||
import spine.AnimationStateData;
|
||||
import spine.Event;
|
||||
import spine.SkeletonData;
|
||||
import spine.SkeletonJson;
|
||||
import spine.animation.AnimationStateData;
|
||||
import spine.starling.SkeletonAnimation;
|
||||
import spine.starling.StarlingAtlasAttachmentLoader;
|
||||
|
||||
@ -39,13 +40,27 @@ public class Game extends Sprite {
|
||||
stateData.setMixByName("jump", "walk", 0.4);
|
||||
stateData.setMixByName("jump", "jump", 0.2);
|
||||
|
||||
skeleton = new SkeletonAnimation(skeletonData);
|
||||
skeleton.setAnimationStateData(stateData);
|
||||
skeleton = new SkeletonAnimation(skeletonData, stateData);
|
||||
skeleton.x = 320;
|
||||
skeleton.y = 420;
|
||||
skeleton.setAnimation("walk", true);
|
||||
skeleton.addAnimation("jump", false, 3);
|
||||
skeleton.addAnimation("walk", true);
|
||||
|
||||
skeleton.state.onStart = function (trackIndex:int) : void {
|
||||
trace(trackIndex + " start: " + skeleton.state.getCurrent(trackIndex));
|
||||
};
|
||||
skeleton.state.onEnd = function (trackIndex:int) : void {
|
||||
trace(trackIndex + " end: " + skeleton.state.getCurrent(trackIndex));
|
||||
};
|
||||
skeleton.state.onComplete = function (trackIndex:int, count:int) : void {
|
||||
trace(trackIndex + " complete: " + skeleton.state.getCurrent(trackIndex) + ", " + count);
|
||||
};
|
||||
skeleton.state.onEvent = function (trackIndex:int, event:Event) : void {
|
||||
trace(trackIndex + " event: " + skeleton.state.getCurrent(trackIndex) + ", "
|
||||
+ event.data.name + ": " + event.intValue + ", " + event.floatValue + ", " + event.stringValue);
|
||||
};
|
||||
|
||||
skeleton.state.setAnimationByName(0, "walk", true);
|
||||
skeleton.state.addAnimationByName(0, "jump", false, 3);
|
||||
skeleton.state.addAnimationByName(0, "walk", true, 0);
|
||||
|
||||
addChild(skeleton);
|
||||
Starling.juggler.add(skeleton);
|
||||
@ -56,8 +71,8 @@ public class Game extends Sprite {
|
||||
private function onClick (event:TouchEvent) : void {
|
||||
var touch:Touch = event.getTouch(this);
|
||||
if (touch && touch.phase == TouchPhase.BEGAN) {
|
||||
skeleton.setAnimation("jump", false);
|
||||
skeleton.addAnimation("walk", true);
|
||||
skeleton.state.setAnimationByName(0, "jump", false);
|
||||
skeleton.state.addAnimationByName(0, "walk", true, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,64 +32,23 @@
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.starling {
|
||||
import spine.AnimationState;
|
||||
import spine.AnimationStateData;
|
||||
import spine.SkeletonData;
|
||||
import spine.animation.AnimationState;
|
||||
import spine.animation.AnimationStateData;
|
||||
import spine.SkeletonData;
|
||||
|
||||
public class SkeletonAnimation extends SkeletonSprite {
|
||||
public var states:Vector.<AnimationState> = new Vector.<AnimationState>();
|
||||
|
||||
public function SkeletonAnimation (skeletonData:SkeletonData) {
|
||||
public var state:AnimationState;
|
||||
|
||||
public function SkeletonAnimation (skeletonData:SkeletonData, stateData:AnimationStateData = null) {
|
||||
super(skeletonData);
|
||||
addAnimationState();
|
||||
state = new AnimationState(stateData ? stateData : new AnimationStateData(skeletonData));
|
||||
}
|
||||
|
||||
|
||||
override public function advanceTime (time:Number) : void {
|
||||
super.advanceTime(time);
|
||||
|
||||
for each (var state:AnimationState in states) {
|
||||
state.update(time);
|
||||
state.apply(skeleton);
|
||||
}
|
||||
state.update(time);
|
||||
state.apply(skeleton);
|
||||
skeleton.updateWorldTransform();
|
||||
}
|
||||
|
||||
public function addAnimationState (stateData:AnimationStateData = null) : void {
|
||||
if (!stateData)
|
||||
stateData = new AnimationStateData(skeleton.data);
|
||||
states.push(new AnimationState(stateData));
|
||||
}
|
||||
|
||||
public function setAnimationStateData (stateData:AnimationStateData, stateIndex:int = 0) : void {
|
||||
if (stateIndex < 0 || stateIndex >= states.length)
|
||||
throw new ArgumentError("stateIndex out of range.");
|
||||
if (!stateData)
|
||||
throw new ArgumentError("stateData cannot be null.");
|
||||
states[stateIndex] = new AnimationState(stateData);
|
||||
}
|
||||
|
||||
public function setMix (fromAnimation:String, toAnimation:String, duration:Number, stateIndex:int = 0) : void {
|
||||
if (stateIndex < 0 || stateIndex >= states.length)
|
||||
throw new ArgumentError("stateIndex out of range.");
|
||||
states[stateIndex].data.setMixByName(fromAnimation, toAnimation, duration);
|
||||
}
|
||||
|
||||
public function setAnimation (name:String, loop:Boolean, stateIndex:int = 0) : void {
|
||||
if (stateIndex < 0 || stateIndex >= states.length)
|
||||
throw new ArgumentError("stateIndex out of range.");
|
||||
states[stateIndex].setAnimationByName(name, loop);
|
||||
}
|
||||
|
||||
public function addAnimation (name:String, loop:Boolean, delay:Number = 0, stateIndex:int = 0) : void {
|
||||
if (stateIndex < 0 || stateIndex >= states.length)
|
||||
throw new ArgumentError("stateIndex out of range.");
|
||||
states[stateIndex].addAnimationByName(name, loop, delay);
|
||||
}
|
||||
|
||||
public function clearAnimation (stateIndex:int = 0) : void {
|
||||
if (stateIndex < 0 || stateIndex >= states.length)
|
||||
throw new ArgumentError("stateIndex out of range.");
|
||||
states[stateIndex].clearAnimation();
|
||||
super.advanceTime(time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user