"lastframe" not happening anymore in 1.7

The event “lastframe” is not called anymore for animation in cocos 1.7

For what I seen, these are never true in process() and simpleProcess() in file animation-state.js

(info.iterations | 0) > (lastInfo.iterations | 0) and (this.time | 0) > (lastIterations | 0)

They end up always equal…

I fixed them on my side, but can’t be 100% sure if this is the proper fix.

I will ask our engineering team to take a look at this. Do you have a small test project, just in case?

Thanks, we will fix it in 1.7.2

LastFrameTest.zip (214.6 KB)

Here is a small test if need be. You’ll see the callback in HelloWorld.js is never called by the animation.

It was still not fixed in 1.7.2

Was it fixed in 1.8.1

Edit: Still not fixed in 1.8.1 @jare @slackmoehrle do you plan to fix it or this is not an important thing, because I already fixed it on our side and it took half a day… I can send you the fix

@muribundi send me your fix and I will put it in front of the team for review.

Inside the animation\animation-state.js

The process() function become this:

function process () {
	// sample
	var info = this.sample();

	var cache = this._hasListenerCache;
	if (cache && cache['lastframe']) {
		var lastInfo;
		if (!this._lastWrappedInfo) {
			lastInfo = this._lastWrappedInfo = new WrappedInfo(info);
		} else {
			lastInfo = this._lastWrappedInfo;
		}

		if (this.repeatCount > 1 && ((info.iterations | 0) > (lastInfo.iterations | 0))) {
			if ((this.wrapMode & WrapModeMask.Reverse) === WrapModeMask.Reverse) {
				if (lastInfo.direction < 0) {
					this.emit('lastframe', this);
				}
			}
			else {
				if (lastInfo.direction > 0) {
					this.emit('lastframe', this);
				}
			}
		}

		lastInfo.set(info);
	}

	if (info.stopped) {
		this.stop();
		this.emit('finished', this);
	}
};

And the simpleProcess() become this:

function simpleProcess () {
	var time = this.time;
	var duration = this.duration;

	if (time > duration) {
		time = time % duration;
		if (time === 0) time = duration;
	}
	else if (time < 0) {
		time = time % duration;
		if (time !== 0 ) time += duration;
	}

	var ratio = time / duration;

	var curves = this.curves;
	for (var i = 0, len = curves.length; i < len; i++) {
		var curve = curves[i];
		curve.sample(time, ratio, this);
	}

	var cache = this._hasListenerCache;
	if (cache && cache['lastframe']) {
		var lastIterations = this._lastIterations;
		if (lastIterations === undefined) {
			lastIterations = this._lastIterations = this.time;
		}

		if ((this.time | 0) > (lastIterations | 0)) {
			this.emit('lastframe', this);
		}

		this._lastIterations = this.time;
	}
}
2 Likes

If they compare to the original function they will see the change, there is a couple thing distributed around in each function…

Thanks, I will pass this along to the team.

Thanks for your code,And i have changed my “animation-state.js”,but it still does not work,is there anything else should i do?

Recompile the engine, see http://docs.cocos.com/creator/manual/en/advanced-topics/engine-customization.html

Sorry, I tweeked the function to make them even better. The other version had weird corner case behavior:

function process () {
	// sample
	var info = this.sample();

	var cache = this._hasListenerCache;
	if (cache && cache['lastframe']) {
		var lastInfo;
		if (!this._lastWrappedInfo) {
			lastInfo = this._lastWrappedInfo = new WrappedInfo(info);
		} else {
			lastInfo = this._lastWrappedInfo;
		}

		if (this.repeatCount > 1 && ((info.iterations | 0) > (lastInfo.iterations | 0))) {
			this.emit('lastframe', this);
		}

		lastInfo.set(info);
	}

	if (info.stopped) {
		this.stop();
		this.emit('finished', this);
	}
}

function simpleProcess () {
	var time = this.time;
	var duration = this.duration;

	if (time > duration) {
		time = time % duration;
		if (time === 0) time = duration;
	}
	else if (time < 0) {
		time = time % duration;
		if (time !== 0 ) time += duration;
	}

	var ratio = time / duration;

	var curves = this.curves;
	for (var i = 0, len = curves.length; i < len; i++) {
		var curve = curves[i];
		curve.sample(time, ratio, this);
	}

	var cache = this._hasListenerCache;
	if (cache && cache['lastframe']) {

		if (this._lastIterations === undefined) {
			this._lastIterations = ratio;
		}

		if ((this.time > 0 && this._lastIterations > ratio) || (this.time < 0 && this._lastIterations < ratio)) {
			this.emit('lastframe', this);
		}

		this._lastIterations = ratio;
	}
}

@jare @slackmoehrle

OK, thanks!

fixed in https://github.com/cocos-creator/engine/pull/2371
thanks again!

Your welcome, so it should be in next cocos release :slight_smile: