Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fix: animation in normal wrap mode won't stop their blend state writers #6808

Merged
merged 2 commits into from Jun 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions cocos/core/animation/animation-state.ts
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down
8 changes: 8 additions & 0 deletions cocos/core/animation/skeletal-animation-blending.ts
Expand Up @@ -78,6 +78,7 @@ export class BlendStateBuffer {
export type IBlendStateWriter = IValueProxyFactory & {
initialize: () => void;
destroy: () => void;
enable: (enabled: boolean) => void;
};

export function createBlendStateWriter<P extends BlendingProperty> (
Expand All @@ -97,6 +98,7 @@ export function createBlendStateWriter<P extends BlendingProperty> (
let propertyBlendState: PropertyBlendState<BlendingPropertyValue<P>> | null = null;
let isConstCacheValid = false;
let lastWeight = -1;
let isEnabled = true;
return {
initialize () {
if (!propertyBlendState) {
Expand All @@ -109,9 +111,15 @@ export function createBlendStateWriter<P extends BlendingProperty> (
propertyBlendState = null;
}
},
enable (enabled: boolean) {
isEnabled = enabled;
},
forTarget: () => {
return {
set: (value: BlendingPropertyValue<P>) => {
if (!isEnabled) {
return;
}
if (!propertyBlendState) {
return;
}
Expand Down
49 changes: 48 additions & 1 deletion 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';

Expand Down Expand Up @@ -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();
});
4 changes: 3 additions & 1 deletion 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: () => { },
Expand Down Expand Up @@ -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)', () => {
Expand Down