Parcourir la source

fix : when not looping, don't call multiple onAnimEnd + currentFrame will be set to maxFrames.

ncannasse il y a 11 ans
Parent
commit
c23009139e
3 fichiers modifiés avec 63 ajouts et 52 suppressions
  1. 10 5
      h2d/Anim.hx
  2. 36 30
      h3d/anim/Animation.hx
  3. 17 17
      h3d/anim/LinearAnimation.hx

+ 10 - 5
h2d/Anim.hx

@@ -30,18 +30,23 @@ class Anim extends Drawable {
 
 
 	override function sync( ctx : RenderContext ) {
 	override function sync( ctx : RenderContext ) {
 		super.sync(ctx);
 		super.sync(ctx);
+		var prev = currentFrame;
 		currentFrame += speed * ctx.elapsedTime;
 		currentFrame += speed * ctx.elapsedTime;
 		if( currentFrame < frames.length )
 		if( currentFrame < frames.length )
 			return;
 			return;
-		if( loop )
+		if( loop ) {
 			currentFrame %= frames.length;
 			currentFrame %= frames.length;
-		else if( currentFrame >= frames.length )
-			currentFrame = frames.length - 0.00001;
-		onAnimEnd();
+			onAnimEnd();
+		} else if( currentFrame >= frames.length ) {
+			currentFrame = frames.length;
+			if( currentFrame != prev ) onAnimEnd();
+		}
 	}
 	}
 
 
 	public function getFrame() {
 	public function getFrame() {
-		return frames[Std.int(currentFrame)];
+		var i = Std.int(currentFrame);
+		if( i == frames.length ) i--;
+		return frames[i];
 	}
 	}
 
 
 	override function draw( ctx : RenderContext ) {
 	override function draw( ctx : RenderContext ) {

+ 36 - 30
h3d/anim/Animation.hx

@@ -1,20 +1,20 @@
 package h3d.anim;
 package h3d.anim;
 
 
 class AnimatedObject {
 class AnimatedObject {
-	
+
 	public var objectName : String;
 	public var objectName : String;
 	public var targetObject : h3d.scene.Object;
 	public var targetObject : h3d.scene.Object;
 	public var targetSkin : h3d.scene.Skin;
 	public var targetSkin : h3d.scene.Skin;
 	public var targetJoint : Int;
 	public var targetJoint : Int;
-	
+
 	public function new(name) {
 	public function new(name) {
 		this.objectName = name;
 		this.objectName = name;
 	}
 	}
-	
+
 	public function clone() {
 	public function clone() {
 		return new AnimatedObject(objectName);
 		return new AnimatedObject(objectName);
 	}
 	}
-	
+
 }
 }
 
 
 private class AnimWait {
 private class AnimWait {
@@ -29,24 +29,24 @@ private class AnimWait {
 }
 }
 
 
 class Animation {
 class Animation {
-	
+
 	static inline var EPSILON = 0.000001;
 	static inline var EPSILON = 0.000001;
-	
+
 	public var name : String;
 	public var name : String;
 	public var frameCount(default, null) : Int;
 	public var frameCount(default, null) : Int;
 	public var sampling(default,null) : Float;
 	public var sampling(default,null) : Float;
 	public var frame(default, null) : Float;
 	public var frame(default, null) : Float;
-	
+
 	public var speed : Float;
 	public var speed : Float;
 	public var onAnimEnd : Void -> Void;
 	public var onAnimEnd : Void -> Void;
-	
+
 	public var pause : Bool;
 	public var pause : Bool;
 	public var loop : Bool;
 	public var loop : Bool;
-	
+
 	var waits : AnimWait;
 	var waits : AnimWait;
 	var isInstance : Bool;
 	var isInstance : Bool;
 	var objects : Array<AnimatedObject>;
 	var objects : Array<AnimatedObject>;
-	
+
 	function new(name, frameCount, sampling) {
 	function new(name, frameCount, sampling) {
 		this.name = name;
 		this.name = name;
 		this.frameCount = frameCount;
 		this.frameCount = frameCount;
@@ -57,7 +57,14 @@ class Animation {
 		loop = true;
 		loop = true;
 		pause = false;
 		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.
 		Register a callback function that will be called once when a frame is reached.
 	**/
 	**/
@@ -76,19 +83,19 @@ class Animation {
 		else
 		else
 			prev.next = new AnimWait(f, callb, prev.next);
 			prev.next = new AnimWait(f, callb, prev.next);
 	}
 	}
-	
+
 	/**
 	/**
 		Remove all frame listeners
 		Remove all frame listeners
 	**/
 	**/
 	public function clearWaits() {
 	public function clearWaits() {
 		waits = null;
 		waits = null;
 	}
 	}
-	
+
 	public function setFrame( f : Float ) {
 	public function setFrame( f : Float ) {
 		frame = f % frameCount;
 		frame = f % frameCount;
 		if( frame < 0 ) frame += frameCount;
 		if( frame < 0 ) frame += frameCount;
 	}
 	}
-	
+
 	function clone( ?a : Animation ) : Animation {
 	function clone( ?a : Animation ) : Animation {
 		if( a == null )
 		if( a == null )
 			a = new Animation(name, frameCount, sampling);
 			a = new Animation(name, frameCount, sampling);
@@ -98,11 +105,11 @@ class Animation {
 		a.pause = pause;
 		a.pause = pause;
 		return a;
 		return a;
 	}
 	}
-	
+
 	function initInstance() {
 	function initInstance() {
 		isInstance = true;
 		isInstance = true;
 	}
 	}
-	
+
 	public function createInstance( base : h3d.scene.Object ) {
 	public function createInstance( base : h3d.scene.Object ) {
 		var currentSkin : h3d.scene.Skin = null;
 		var currentSkin : h3d.scene.Skin = null;
 		var objects = [for( a in this.objects ) a.clone()];
 		var objects = [for( a in this.objects ) a.clone()];
@@ -112,7 +119,7 @@ class Animation {
 		a.initInstance();
 		a.initInstance();
 		return a;
 		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.
 		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.
 		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.
 		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
 		// should be overridden in subclass
 		throw "assert";
 		throw "assert";
 	}
 	}
-	
+
 	function isPlaying() {
 	function isPlaying() {
 		return !pause && (speed < 0 ? -speed : speed) > EPSILON;
 		return !pause && (speed < 0 ? -speed : speed) > EPSILON;
 	}
 	}
@@ -158,14 +165,14 @@ class Animation {
 	function endFrame() {
 	function endFrame() {
 		return frameCount;
 		return frameCount;
 	}
 	}
-	
+
 	public function update(dt:Float) : Float {
 	public function update(dt:Float) : Float {
 		if( !isInstance )
 		if( !isInstance )
 			throw "You must instanciate this animation first";
 			throw "You must instanciate this animation first";
-		
+
 		if( !isPlaying() )
 		if( !isPlaying() )
 			return 0;
 			return 0;
-		
+
 		// check waits
 		// check waits
 		var w = waits;
 		var w = waits;
 		var prev = null;
 		var prev = null;
@@ -188,18 +195,17 @@ class Animation {
 			w.callb();
 			w.callb();
 			return dt;
 			return dt;
 		}
 		}
-		
+
 		// check on anim end
 		// check on anim end
 		if( onAnimEnd != null ) {
 		if( onAnimEnd != null ) {
 			var end = endFrame();
 			var end = endFrame();
 			var et = (end - frame) / (speed * sampling);
 			var et = (end - frame) / (speed * sampling);
-			if( et <= dt ) {
-				var f = end - EPSILON;
-				frame = f;
+			if( et <= dt && et > 0 ) {
+				frame = end;
 				dt -= et;
 				dt -= et;
 				onAnimEnd();
 				onAnimEnd();
 				// if we didn't change the frame or paused the animation, let's end it
 				// 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 ) {
 					if( loop ) {
 						frame = 0;
 						frame = 0;
 					} else {
 					} else {
@@ -210,16 +216,16 @@ class Animation {
 				return dt;
 				return dt;
 			}
 			}
 		}
 		}
-		
+
 		// update frame
 		// update frame
 		frame += dt * speed * sampling;
 		frame += dt * speed * sampling;
 		if( frame >= frameCount ) {
 		if( frame >= frameCount ) {
 			if( loop )
 			if( loop )
 				frame %= frameCount;
 				frame %= frameCount;
 			else
 			else
-				frame = frameCount - EPSILON;
+				frame = frameCount;
 		}
 		}
 		return 0;
 		return 0;
 	}
 	}
-	
+
 }
 }

+ 17 - 17
h3d/anim/LinearAnimation.hx

@@ -33,7 +33,7 @@ class LinearObject extends AnimatedObject {
 		return o;
 		return o;
 	}
 	}
 }
 }
-	
+
 class LinearAnimation extends Animation {
 class LinearAnimation extends Animation {
 
 
 	var syncFrame : Float;
 	var syncFrame : Float;
@@ -42,7 +42,7 @@ class LinearAnimation extends Animation {
 		super(name,frame,sampling);
 		super(name,frame,sampling);
 		syncFrame = -1;
 		syncFrame = -1;
 	}
 	}
-	
+
 	public function addCurve( objName, frames, hasRot, hasScale ) {
 	public function addCurve( objName, frames, hasRot, hasScale ) {
 		var f = new LinearObject(objName);
 		var f = new LinearObject(objName);
 		f.frames = frames;
 		f.frames = frames;
@@ -50,7 +50,7 @@ class LinearAnimation extends Animation {
 		f.hasScale = hasScale;
 		f.hasScale = hasScale;
 		objects.push(f);
 		objects.push(f);
 	}
 	}
-	
+
 	public function addAlphaCurve( objName, alphas ) {
 	public function addAlphaCurve( objName, alphas ) {
 		var f = new LinearObject(objName);
 		var f = new LinearObject(objName);
 		f.alphas = alphas;
 		f.alphas = alphas;
@@ -62,11 +62,11 @@ class LinearAnimation extends Animation {
 		f.uvs = uvs;
 		f.uvs = uvs;
 		objects.push(f);
 		objects.push(f);
 	}
 	}
-	
+
 	inline function getFrames() : Array<LinearObject> {
 	inline function getFrames() : Array<LinearObject> {
 		return cast objects;
 		return cast objects;
 	}
 	}
-	
+
 	override function initInstance() {
 	override function initInstance() {
 		super.initInstance();
 		super.initInstance();
 		for( a in getFrames() ) {
 		for( a in getFrames() ) {
@@ -76,23 +76,23 @@ class LinearAnimation extends Animation {
 				throw a.objectName + " should be a mesh";
 				throw a.objectName + " should be a mesh";
 		}
 		}
 	}
 	}
-	
+
 	override function clone(?a:Animation) {
 	override function clone(?a:Animation) {
 		if( a == null )
 		if( a == null )
 			a = new LinearAnimation(name, frameCount, sampling);
 			a = new LinearAnimation(name, frameCount, sampling);
 		super.clone(a);
 		super.clone(a);
 		return a;
 		return a;
 	}
 	}
-	
+
 	override function endFrame() {
 	override function endFrame() {
 		return loop ? frameCount : frameCount - 1;
 		return loop ? frameCount : frameCount - 1;
 	}
 	}
-	
+
 	@:access(h3d.scene.Skin)
 	@:access(h3d.scene.Skin)
 	override function sync( decompose = false ) {
 	override function sync( decompose = false ) {
 		if( frame == syncFrame && !decompose )
 		if( frame == syncFrame && !decompose )
 			return;
 			return;
-		var frame1 = Std.int(frame);
+		var frame1 = getIFrame();
 		var frame2 = (frame1 + 1) % frameCount;
 		var frame2 = (frame1 + 1) % frameCount;
 		var k2 = frame - frame1;
 		var k2 = frame - frame1;
 		var k1 = 1 - k2;
 		var k1 = 1 - k2;
@@ -120,13 +120,13 @@ class LinearAnimation extends Animation {
 				continue;
 				continue;
 			}
 			}
 			var f1 = o.frames[frame1], f2 = o.frames[frame2];
 			var f1 = o.frames[frame1], f2 = o.frames[frame2];
-			
+
 			var m = o.matrix;
 			var m = o.matrix;
-			
+
 			m._41 = f1.tx * k1 + f2.tx * k2;
 			m._41 = f1.tx * k1 + f2.tx * k2;
 			m._42 = f1.ty * k1 + f2.ty * k2;
 			m._42 = f1.ty * k1 + f2.ty * k2;
 			m._43 = f1.tz * k1 + f2.tz * k2;
 			m._43 = f1.tz * k1 + f2.tz * k2;
-			
+
 			if( o.hasRotation ) {
 			if( o.hasRotation ) {
 				// qlerp nearest
 				// qlerp nearest
 				var dot = f1.qx * f2.qx + f1.qy * f2.qy + f1.qz * f2.qz + f1.qw * f2.qw;
 				var dot = f1.qx * f2.qx + f1.qy * f2.qy + f1.qz * f2.qz + f1.qw * f2.qw;
@@ -141,7 +141,7 @@ class LinearAnimation extends Animation {
 				qy *= ql;
 				qy *= ql;
 				qz *= ql;
 				qz *= ql;
 				qw *= ql;
 				qw *= ql;
-				
+
 				if( decompose ) {
 				if( decompose ) {
 					m._12 = qx;
 					m._12 = qx;
 					m._13 = qy;
 					m._13 = qy;
@@ -187,14 +187,14 @@ class LinearAnimation extends Animation {
 						m._33 *= sz;
 						m._33 *= sz;
 					}
 					}
 				}
 				}
-				
+
 			} else if( o.hasScale ) {
 			} else if( o.hasScale ) {
 				m._11 = f1.sx * k1 + f2.sx * k2;
 				m._11 = f1.sx * k1 + f2.sx * k2;
 				m._22 = f1.sy * k1 + f2.sy * k2;
 				m._22 = f1.sy * k1 + f2.sy * k2;
 				m._33 = f1.sz * k1 + f2.sz * k2;
 				m._33 = f1.sz * k1 + f2.sz * k2;
 			}
 			}
-			
-			
+
+
 			if( o.targetSkin != null ) {
 			if( o.targetSkin != null ) {
 				o.targetSkin.currentRelPose[o.targetJoint] = o.matrix;
 				o.targetSkin.currentRelPose[o.targetJoint] = o.matrix;
 				o.targetSkin.jointsUpdated = true;
 				o.targetSkin.jointsUpdated = true;
@@ -202,5 +202,5 @@ class LinearAnimation extends Animation {
 				o.targetObject.defaultTransform = o.matrix;
 				o.targetObject.defaultTransform = o.matrix;
 		}
 		}
 	}
 	}
-	
+
 }
 }