|
@@ -1,20 +1,20 @@
|
|
|
package h3d.anim;
|
|
|
|
|
|
class AnimatedObject {
|
|
|
-
|
|
|
+
|
|
|
public var objectName : String;
|
|
|
public var targetObject : h3d.scene.Object;
|
|
|
public var targetSkin : h3d.scene.Skin;
|
|
|
public var targetJoint : Int;
|
|
|
-
|
|
|
+
|
|
|
public function new(name) {
|
|
|
this.objectName = name;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public function clone() {
|
|
|
return new AnimatedObject(objectName);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
|
|
|
private class AnimWait {
|
|
@@ -29,24 +29,24 @@ private class AnimWait {
|
|
|
}
|
|
|
|
|
|
class Animation {
|
|
|
-
|
|
|
+
|
|
|
static inline var EPSILON = 0.000001;
|
|
|
-
|
|
|
+
|
|
|
public var name : String;
|
|
|
public var frameCount(default, null) : Int;
|
|
|
public var sampling(default,null) : Float;
|
|
|
public var frame(default, null) : Float;
|
|
|
-
|
|
|
+
|
|
|
public var speed : Float;
|
|
|
public var onAnimEnd : Void -> Void;
|
|
|
-
|
|
|
+
|
|
|
public var pause : Bool;
|
|
|
public var loop : Bool;
|
|
|
-
|
|
|
+
|
|
|
var waits : AnimWait;
|
|
|
var isInstance : Bool;
|
|
|
var objects : Array<AnimatedObject>;
|
|
|
-
|
|
|
+
|
|
|
function new(name, frameCount, sampling) {
|
|
|
this.name = name;
|
|
|
this.frameCount = frameCount;
|
|
@@ -57,7 +57,14 @@ class Animation {
|
|
|
loop = true;
|
|
|
pause = false;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ inline function getIFrame() {
|
|
|
+ var f = Std.int(frame);
|
|
|
+ var max = endFrame();
|
|
|
+ if( f == max ) f--;
|
|
|
+ return f;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
Register a callback function that will be called once when a frame is reached.
|
|
|
**/
|
|
@@ -76,19 +83,19 @@ class Animation {
|
|
|
else
|
|
|
prev.next = new AnimWait(f, callb, prev.next);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
Remove all frame listeners
|
|
|
**/
|
|
|
public function clearWaits() {
|
|
|
waits = null;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public function setFrame( f : Float ) {
|
|
|
frame = f % frameCount;
|
|
|
if( frame < 0 ) frame += frameCount;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
function clone( ?a : Animation ) : Animation {
|
|
|
if( a == null )
|
|
|
a = new Animation(name, frameCount, sampling);
|
|
@@ -98,11 +105,11 @@ class Animation {
|
|
|
a.pause = pause;
|
|
|
return a;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
function initInstance() {
|
|
|
isInstance = true;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public function createInstance( base : h3d.scene.Object ) {
|
|
|
var currentSkin : h3d.scene.Skin = null;
|
|
|
var objects = [for( a in this.objects ) a.clone()];
|
|
@@ -112,7 +119,7 @@ class Animation {
|
|
|
a.initInstance();
|
|
|
return a;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
If one of the animated object has been changed, it is necessary to call bind() so the animation can keep with the change.
|
|
|
**/
|
|
@@ -141,7 +148,7 @@ class Animation {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
Synchronize the target object matrix.
|
|
|
If decompose is true, then the rotation quaternion is stored in [m12,m13,m21,m23] instead of mixed with the scale.
|
|
@@ -150,7 +157,7 @@ class Animation {
|
|
|
// should be overridden in subclass
|
|
|
throw "assert";
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
function isPlaying() {
|
|
|
return !pause && (speed < 0 ? -speed : speed) > EPSILON;
|
|
|
}
|
|
@@ -158,14 +165,14 @@ class Animation {
|
|
|
function endFrame() {
|
|
|
return frameCount;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public function update(dt:Float) : Float {
|
|
|
if( !isInstance )
|
|
|
throw "You must instanciate this animation first";
|
|
|
-
|
|
|
+
|
|
|
if( !isPlaying() )
|
|
|
return 0;
|
|
|
-
|
|
|
+
|
|
|
// check waits
|
|
|
var w = waits;
|
|
|
var prev = null;
|
|
@@ -188,18 +195,17 @@ class Animation {
|
|
|
w.callb();
|
|
|
return dt;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// check on anim end
|
|
|
if( onAnimEnd != null ) {
|
|
|
var end = endFrame();
|
|
|
var et = (end - frame) / (speed * sampling);
|
|
|
- if( et <= dt ) {
|
|
|
- var f = end - EPSILON;
|
|
|
- frame = f;
|
|
|
+ if( et <= dt && et > 0 ) {
|
|
|
+ frame = end;
|
|
|
dt -= et;
|
|
|
onAnimEnd();
|
|
|
// if we didn't change the frame or paused the animation, let's end it
|
|
|
- if( frame == f && isPlaying() ) {
|
|
|
+ if( frame == end && isPlaying() ) {
|
|
|
if( loop ) {
|
|
|
frame = 0;
|
|
|
} else {
|
|
@@ -210,16 +216,16 @@ class Animation {
|
|
|
return dt;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// update frame
|
|
|
frame += dt * speed * sampling;
|
|
|
if( frame >= frameCount ) {
|
|
|
if( loop )
|
|
|
frame %= frameCount;
|
|
|
else
|
|
|
- frame = frameCount - EPSILON;
|
|
|
+ frame = frameCount;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
}
|