11import { Scene } from "@babylonjs/core/scene" ;
2- import { Tools } from "@babylonjs/core/Misc/tools" ;
32import { Sound } from "@babylonjs/core/Audio/sound" ;
43import { Animation } from "@babylonjs/core/Animations/animation" ;
54import { IAnimationKey } from "@babylonjs/core/Animations/animationKey" ;
@@ -19,7 +18,7 @@ import { handleApplyImpulseEvent } from "./events/apply-impulse";
1918import { ICinematic } from "./typings" ;
2019import { Cinematic } from "./cinematic" ;
2120import { isCinematicKey , isCinematicKeyCut } from "./guards" ;
22- import { cloneKey , getPropertyValue , registerAfterAnimationCallback } from "./tools" ;
21+ import { getPropertyValue , registerAfterAnimationCallback } from "./tools" ;
2322
2423export type GenerateCinematicAnimationGroupOptions = {
2524 /**
@@ -42,85 +41,79 @@ export function generateCinematicAnimationGroup(cinematic: ICinematic, scene: Sc
4241 cinematic . tracks . forEach ( ( track ) => {
4342 // Animation groups
4443 const animationGroup = track . animationGroup as AnimationGroup ;
45- if ( animationGroup ) {
46- const groupedAnimations : Animation [ ] = [ ] ;
47-
48- track . animationGroups ?. forEach ( ( configuration ) => {
49- animationGroup . targetedAnimations . forEach ( ( targetedAnimation ) => {
50- let animation : Animation | null = null ;
51-
52- defer: {
53- const existingTargetedAnimations = result . targetedAnimations . filter ( ( ta2 ) => ta2 . target === targetedAnimation . target ) ;
54- if ( existingTargetedAnimations . length ) {
55- const existingTargetedAnimationsPair = existingTargetedAnimations . find (
56- ( et ) => et . animation . targetProperty === targetedAnimation . animation . targetProperty
57- ) ;
58- if ( existingTargetedAnimationsPair ) {
59- animation = existingTargetedAnimationsPair . animation ;
60- break defer;
61- }
62- }
44+ if ( animationGroup && track . animationGroups ?. length ) {
45+ const effectiveAnimationGroup = animationGroup . clone ( `${ animationGroup . name } -cinematic-temp` ) ;
6346
64- animation = targetedAnimation . animation . clone ( ) ;
65- animation . setKeys ( [ ] ) ;
66- animation . name = Tools . RandomId ( ) ;
67- animation . framePerSecond = cinematic . framesPerSecond ;
68- }
47+ const index = scene . animationGroups . indexOf ( effectiveAnimationGroup ) ;
48+ if ( index !== - 1 ) {
49+ scene . animationGroups . splice ( index , 1 ) ;
50+ }
6951
70- const keys = animation . getKeys ( ) ;
71- const sourceKeys = targetedAnimation . animation . getKeys ( ) ;
52+ result . onAnimationEndObservable . add ( ( ) => {
53+ animationGroup . stop ( ) ;
54+ effectiveAnimationGroup . stop ( ) ;
55+ } ) ;
7256
73- const speed = configuration . speed ;
74- const normalizedFps = cinematic . framesPerSecond / targetedAnimation . animation . framePerSecond / speed ;
57+ const minFrame = track . animationGroups . reduce ( ( prev , curr ) => Math . min ( prev , curr . frame ) , Number . MAX_VALUE ) ?? 0 ;
58+ const maxFrame = track . animationGroups . reduce ( ( prev , curr ) => Math . max ( prev , curr . frame + curr . endFrame ) , 0 ) ?? 0 ;
7559
76- sourceKeys . forEach ( ( k ) => {
77- if ( k . frame >= configuration . startFrame && k . frame <= configuration . endFrame ) {
78- keys . push ( {
79- ...cloneKey ( targetedAnimation . animation . dataType , k ) ,
80- frame : configuration . frame + k . frame * normalizedFps ,
81- } ) ;
82- }
83- } ) ;
60+ const dummyObject = {
61+ frame : minFrame ,
62+ } ;
8463
85- animation . setKeys ( keys ) ;
86- result . addTargetedAnimation ( animation , targetedAnimation . target ) ;
64+ const animationGroupsAnimation = new Animation ( effectiveAnimationGroup . name , "frame" , 60 , Animation . ANIMATIONTYPE_FLOAT , Animation . ANIMATIONLOOPMODE_CYCLE , false ) ;
8765
88- groupedAnimations . push ( animation ) ;
89- } ) ;
66+ animationGroupsAnimation . setKeys ( [
67+ { frame : minFrame , value : 0 } ,
68+ { frame : maxFrame , value : maxFrame } ,
69+ ] ) ;
70+
71+ track . animationGroups . forEach ( ( configuration ) => {
72+ animationGroupsAnimation . addEvent (
73+ new AnimationEvent ( configuration . frame , ( ) => {
74+ effectiveAnimationGroup . from = configuration . startFrame ;
75+ effectiveAnimationGroup . to = configuration . endFrame ;
76+ effectiveAnimationGroup . speedRatio = configuration . speed ;
77+ effectiveAnimationGroup . stop ( ) ;
78+ effectiveAnimationGroup . goToFrame ( configuration . startFrame ) ;
79+ effectiveAnimationGroup . play ( false ) ;
80+ } )
81+ ) ;
9082 } ) ;
9183
92- // TODO: fix that
93- // if (groupedAnimations.length && (track.animationGroupWeight?.length ?? 0) >= 2) {
94- // const dummyObject = {
95- // weight: 0,
96- // };
97-
98- // const weightAnimation = new Animation(`${animationGroup.name}-weights`, "weight", 60, Animation.ANIMATIONTYPE_FLOAT, Animation.ANIMATIONLOOPMODE_CYCLE, false);
99- // const weightKeys: IAnimationKey[] = [];
100-
101- // track.animationGroupWeight!.forEach((keyFrame) => {
102- // if (isCinematicKeyCut(keyFrame)) {
103- // weightKeys.push(keyFrame.key1);
104- // weightKeys.push(keyFrame.key2);
105- // } else {
106- // weightKeys.push(keyFrame);
107- // }
108- // });
109-
110- // weightAnimation.setKeys(weightKeys);
111- // result.addTargetedAnimation(weightAnimation, dummyObject);
112-
113- // registerAfterAnimationCallback(result, scene, () => {
114- // result.animatables.forEach((animatable) => {
115- // for (const animation of animatable.getAnimations()) {
116- // if (groupedAnimations.includes(animation.animation)) {
117- // animatable.weight = dummyObject.weight;
118- // break;
119- // }
120- // }
121- // });
122- // });
123- // }
84+ result . addTargetedAnimation ( animationGroupsAnimation , dummyObject ) ;
85+
86+ if ( ( track . animationGroupWeight ?. length ?? 0 ) >= 2 ) {
87+ const dummyObject = {
88+ weight : 0 ,
89+ } ;
90+
91+ const weightAnimation = new Animation (
92+ `${ effectiveAnimationGroup . name } -weights` ,
93+ "weight" ,
94+ 60 ,
95+ Animation . ANIMATIONTYPE_FLOAT ,
96+ Animation . ANIMATIONLOOPMODE_CYCLE ,
97+ false
98+ ) ;
99+ const weightKeys : IAnimationKey [ ] = [ ] ;
100+
101+ track . animationGroupWeight ! . forEach ( ( keyFrame ) => {
102+ if ( isCinematicKeyCut ( keyFrame ) ) {
103+ weightKeys . push ( keyFrame . key1 ) ;
104+ weightKeys . push ( keyFrame . key2 ) ;
105+ } else {
106+ weightKeys . push ( keyFrame ) ;
107+ }
108+ } ) ;
109+
110+ weightAnimation . setKeys ( weightKeys ) ;
111+ result . addTargetedAnimation ( weightAnimation , dummyObject ) ;
112+
113+ registerAfterAnimationCallback ( result , scene , ( ) => {
114+ effectiveAnimationGroup . weight = dummyObject . weight ;
115+ } ) ;
116+ }
124117 }
125118
126119 const sound = track . sound as Sound ;
0 commit comments