From 714b8b579b368fb70ffd35a3295e2ab82192baf1 Mon Sep 17 00:00:00 2001 From: SB Date: Tue, 2 Jun 2020 18:47:00 +0800 Subject: [PATCH 1/2] Bug fix: animation in normal wrap mode won't stop their blend state writers --- cocos/core/animation/animation-state.ts | 6 ++++++ cocos/core/animation/skeletal-animation-blending.ts | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/cocos/core/animation/animation-state.ts b/cocos/core/animation/animation-state.ts index 33c4a0fe3ed..d4e63cd3231 100644 --- a/cocos/core/animation/animation-state.ts +++ b/cocos/core/animation/animation-state.ts @@ -680,6 +680,9 @@ export class AnimationState extends Playable { if (!this.isPaused) { this._onPauseOrStop(); } + for (let iBlendStateWriter = 0; iBlendStateWriter < this._blendStateWriters.length; ++iBlendStateWriter) { + this._blendStateWriters[iBlendStateWriter].enable(false); + } this.emit(EventType.STOP, this); } @@ -867,6 +870,9 @@ export class AnimationState extends Playable { } this._isBlendStateWriterInitialized = true; } + for (let iBlendStateWriter = 0; iBlendStateWriter < this._blendStateWriters.length; ++iBlendStateWriter) { + this._blendStateWriters[iBlendStateWriter].enable(true); + } cc.director.getAnimationManager().addAnimation(this); } diff --git a/cocos/core/animation/skeletal-animation-blending.ts b/cocos/core/animation/skeletal-animation-blending.ts index c160ec6c8f6..97c03454a65 100644 --- a/cocos/core/animation/skeletal-animation-blending.ts +++ b/cocos/core/animation/skeletal-animation-blending.ts @@ -78,6 +78,7 @@ export class BlendStateBuffer { export type IBlendStateWriter = IValueProxyFactory & { initialize: () => void; destroy: () => void; + enable: (enabled: boolean) => void; }; export function createBlendStateWriter

( @@ -97,6 +98,7 @@ export function createBlendStateWriter

( let propertyBlendState: PropertyBlendState> | null = null; let isConstCacheValid = false; let lastWeight = -1; + let isEnabled = true; return { initialize () { if (!propertyBlendState) { @@ -109,9 +111,15 @@ export function createBlendStateWriter

( propertyBlendState = null; } }, + enable (enabled: boolean) { + isEnabled = enabled; + }, forTarget: () => { return { set: (value: BlendingPropertyValue

) => { + if (!isEnabled) { + return; + } if (!propertyBlendState) { return; } From 39e4925bbecb6fb67f497aec71215f63a6b1cc9f Mon Sep 17 00:00:00 2001 From: SB Date: Tue, 2 Jun 2020 19:11:08 +0800 Subject: [PATCH 2/2] Add test --- tests/animation/animation-clip.test.ts | 49 +++++++++++++++++++++++- tests/animation/animation-events.test.ts | 4 +- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/tests/animation/animation-clip.test.ts b/tests/animation/animation-clip.test.ts index f5a93573f04..9ee95d5da42 100644 --- a/tests/animation/animation-clip.test.ts +++ b/tests/animation/animation-clip.test.ts @@ -1,4 +1,4 @@ -import { AnimationClip, js, AnimationState, Node, Component, Vec3 } from '../../cocos/core'; +import { AnimationClip, js, AnimationState, Node, Component, Vec3, AnimationManager } from '../../cocos/core'; import { ComponentPath } from '../../cocos/core/animation/animation'; import { ccclass } from '../../cocos/core/data/class-decorator'; @@ -65,3 +65,50 @@ test('Common target', () => { expect(testComponent.c).toEqual(c); } }); + +test('animation state', () => { + const animationManager = new AnimationManager(); + const mockInstance = jest.spyOn((global as any).cc.director, 'getAnimationManager').mockImplementation(() => { + return animationManager; + }); + + const clip = new AnimationClip('default'); + clip.duration = 2.0; + const keys = [ + 0, + 0.1, + 0.2, + ]; + const values = [ + new Vec3(), + new Vec3(1), + new Vec3(2), + ]; + clip.keys = [keys]; + clip.curves = [{ + modifiers: [ + 'position', + ], + data: { + keys: 0, + values, + }, + }]; + + const state = new AnimationState(clip, clip.name); + state.weight = 1.0; + + const node = new Node(); + state.initialize(node); + + animationManager.update(0); + state.play(); + state.pause(); + + state.setTime(keys[1]); + state.update(0); + animationManager.update(0); + expect(node.getPosition()).toEqual(values[1]); + + mockInstance.mockRestore(); +}); diff --git a/tests/animation/animation-events.test.ts b/tests/animation/animation-events.test.ts index ce36e32b706..b85355ad5c6 100644 --- a/tests/animation/animation-events.test.ts +++ b/tests/animation/animation-events.test.ts @@ -1,7 +1,7 @@ import { Node, AnimationComponent, director, AnimationClip, math, AnimationState } from '../../cocos/core'; test('Animation events(general)', () => { - jest.spyOn((global as any).cc.director, 'getAnimationManager').mockImplementation(() => { + const mockInstance = jest.spyOn((global as any).cc.director, 'getAnimationManager').mockImplementation(() => { return { addAnimation: () => { }, removeAnimation: () => { }, @@ -100,6 +100,8 @@ test('Animation events(general)', () => { testMagic.clear(); state.update(clip.duration / 2 + clip.duration / 4); testMagic.expectAndClear(AnimationComponent.EventType.LASTFRAME); + + mockInstance.mockRestore(); }); test('Animation event(last-frame event optimization)', () => {