diff --git a/packages/core/src/animation/Animator.ts b/packages/core/src/animation/Animator.ts index 1f2f13ae91..c03fedc618 100644 --- a/packages/core/src/animation/Animator.ts +++ b/packages/core/src/animation/Animator.ts @@ -107,7 +107,7 @@ export class Animator extends Component { const { srcPlayData } = animatorLayerData; const { state: curState } = srcPlayData; if (curState && curState !== state) { - this._revertDefaultValue(srcPlayData); + this._revertDefaultValue(srcPlayData.state, srcPlayData.stateData); } //CM: Not consider same stateName, but different animation @@ -119,6 +119,26 @@ export class Animator extends Component { this._saveDefaultValues(animatorStateData); } + /** + * @internal + */ + _reset(): void { + const { _animatorController: animatorController } = this; + if (animatorController) { + const layers = animatorController.layers; + for (let i = 0, n = layers.length; i < n; ++i) { + const { states } = layers[i].stateMachine; + const animatorLayerData = this._getAnimatorLayerData(i); + for (let j = 0, m = states.length; j < m; ++j) { + const state = states[j]; + const animatorStateData = this._getAnimatorStateData(state.name, state, animatorLayerData); + this._revertDefaultValue(state, animatorStateData); + } + } + } + this._clearPlayData(); + } + /** * Create a cross fade from the current state to another state. * @param stateName - The state name @@ -363,6 +383,7 @@ export class Animator extends Component { if (owner.crossCurveMark === crossCurveMark) { crossCurveData[owner.crossCurveIndex].destCurveIndex = i; } else { + owner.saveDefaultValue(); saveFixed && owner.saveFixedPoseValue(); owner.crossCurveMark = crossCurveMark; owner.crossCurveIndex = crossCurveData.length; @@ -498,7 +519,7 @@ export class Animator extends Component { let crossWeight = destPlayData.frameTime / (destState._getDuration() * layerData.crossFadeTransition.duration); crossWeight >= 1.0 && (crossWeight = 1.0); - + srcPlayData.update(); destPlayData.update(); @@ -639,6 +660,12 @@ export class Animator extends Component { break; } } + } else if (owner.type === SkinnedMeshRenderer) { + switch (owner.property) { + case AnimationProperty.BlendShapeWeights: + (owner.component).blendShapeWeights = value; + break; + } } if (additive) { @@ -717,11 +744,11 @@ export class Animator extends Component { } } - private _revertDefaultValue(playData: AnimatorStatePlayData) { - const { clip } = playData.state; + private _revertDefaultValue(state: AnimatorState, stateData: AnimatorStateData) { + const { clip } = state; if (clip) { const curves = clip._curveBindings; - const { curveOwners } = playData.stateData; + const { curveOwners } = stateData; for (let i = curves.length - 1; i >= 0; i--) { const owner = curveOwners[i]; const { transform } = owner.target; @@ -735,6 +762,12 @@ export class Animator extends Component { case AnimationProperty.Scale: transform.scale = owner.defaultValue; break; + case AnimationProperty.BlendShapeWeights: + const { blendShapeWeights } = owner.component; + for (let j = 0, length = blendShapeWeights.length; j < length; ++j) { + (owner.component).blendShapeWeights[j] = owner.defaultValue[j]; + } + break; } } } @@ -756,7 +789,7 @@ export class Animator extends Component { } } - private _crossFadeByTransition(transition: AnimatorStateTransition, layerIndex: number) { + private _crossFadeByTransition(transition: AnimatorStateTransition, layerIndex: number): void { const { name } = transition.destinationState; const animatorStateInfo = this._getAnimatorStateInfo(name, layerIndex, Animator._animatorInfo); const { state: crossState } = animatorStateInfo; @@ -777,8 +810,6 @@ export class Animator extends Component { const offset = duration * transition.offset; destPlayData.reset(crossState, animatorStateData, offset); - this._saveDefaultValues(animatorStateData); - switch (layerState) { // Maybe not play, maybe end. case LayerState.Standby: @@ -870,6 +901,8 @@ export class Animator extends Component { this._animatorLayersData.length = 0; this._crossCurveDataCollection.length = 0; this._animationCurveOwners.length = 0; - this._controllerUpdateFlag.flag = false; + if (this._controllerUpdateFlag) { + this._controllerUpdateFlag.flag = false; + } } } diff --git a/packages/core/src/animation/internal/AnimationCurveOwner.ts b/packages/core/src/animation/internal/AnimationCurveOwner.ts index 0bcaf59a1e..6ac8d401b1 100644 --- a/packages/core/src/animation/internal/AnimationCurveOwner.ts +++ b/packages/core/src/animation/internal/AnimationCurveOwner.ts @@ -58,6 +58,12 @@ export class AnimationCurveOwner { case AnimationProperty.Scale: this.target.transform.scale.cloneTo(this.defaultValue); break; + case AnimationProperty.BlendShapeWeights: + const { blendShapeWeights } = this.component; + for (let i = 0, length = blendShapeWeights.length; i < length; ++i) { + this.defaultValue[i] = (this.component).blendShapeWeights[i]; + } + break; } } @@ -72,6 +78,12 @@ export class AnimationCurveOwner { case AnimationProperty.Scale: this.target.transform.scale.cloneTo(this.fixedPoseValue); break; + case AnimationProperty.BlendShapeWeights: + const { blendShapeWeights } = this.component; + for (let i = 0, length = blendShapeWeights.length; i < length; ++i) { + this.fixedPoseValue[i] = (this.component).blendShapeWeights[i]; + } + break; } } } diff --git a/packages/loader/src/scene-loader/GLTFModel.ts b/packages/loader/src/scene-loader/GLTFModel.ts index 813cc9b498..885076d48b 100644 --- a/packages/loader/src/scene-loader/GLTFModel.ts +++ b/packages/loader/src/scene-loader/GLTFModel.ts @@ -87,9 +87,14 @@ export class GLTFModel extends Component { set clipPreview(value: string) { if (this._animator) { if (value) { - this._animator.play(value, 0); + if (value === "_default") { + this._playDefaultState(); + } else { + this._animator.play(value, 0); + } } else { - this._playDefaultState(); + // @ts-ignore + this._animator._reset(); } } this._clipPreview = value; @@ -104,7 +109,7 @@ export class GLTFModel extends Component { * @param props - Init props */ init(props): void { - const { asset = null, speed, animatorController, clipPreview, isClone } = props; + const { asset = null, speed, animatorController, clipPreview, isClone } = props; if (isClone) { const rootName = (props as any).gltfRootName; if (rootName) { @@ -153,12 +158,17 @@ export class GLTFModel extends Component { _playState() { const playStateName = this._clipPreview; if (playStateName) { - this._animator.play(playStateName, 0); - if (this._controllerUpdateFlag?.flag) { - this._controllerUpdateFlag.flag = false; + if (playStateName === "_default") { + this._playDefaultState(); + } else { + this._animator.play(playStateName, 0); } } else { - this._playDefaultState(); + // @ts-ignore + this._animator._reset(); + } + if (this._controllerUpdateFlag?.flag) { + this._controllerUpdateFlag.flag = false; } } @@ -169,13 +179,16 @@ export class GLTFModel extends Component { const { layers } = animatorController; for (let i = 0, length = layers.length; i < length; ++i) { //@ts-ignore - const defaultState = layers[i]?.stateMachine?._defaultState ?? layers[i]?.stateMachine?.states[0]; + const defaultState = layers[i]?.stateMachine?._defaultState; const defaultStateName = defaultState?.name; if (defaultStateName) { animator.play(defaultStateName, i); - if (this._controllerUpdateFlag?.flag) { - this._controllerUpdateFlag.flag = false; - } + } else { + // @ts-ignore + animator._reset(); + } + if (this._controllerUpdateFlag?.flag) { + this._controllerUpdateFlag.flag = false; } } }