Procházet zdrojové kódy

Move MergeAnimations to assetContainer
Beautify code

noalak před 5 roky
rodič
revize
a5d84cfb69
3 změnil soubory, kde provedl 85 přidání a 94 odebrání
  1. 5 91
      src/Loading/sceneLoader.ts
  2. 13 0
      src/abstractScene.ts
  3. 67 3
      src/assetContainer.ts

+ 5 - 91
src/Loading/sceneLoader.ts

@@ -18,7 +18,6 @@ import { IFileRequest } from "../Misc/fileRequest";
 import { WebRequest } from "../Misc/webRequest";
 import { RequestFileError, ReadFileError } from '../Misc/fileTools';
 import { Animation } from '../Animations';
-import { AbstractScene } from '..';
 
 /**
  * Class used to represent data loading progression
@@ -1022,10 +1021,8 @@ export class SceneLoader {
             return;
         }
 
-        let _targetConverter = targetConverter ? targetConverter : this._defaultTargetConverter(scene);
-
         let onAssetContainerLoaded = (container: AssetContainer) => {
-            SceneLoader.MergeAnimations(scene, container, _targetConverter);
+            container.MergeAnimationsTo(scene, targetConverter);
 
             container.dispose();
 
@@ -1045,9 +1042,9 @@ export class SceneLoader {
             scene.animationGroups.slice().forEach(animationGroup => {
                 animationGroup.dispose();
             });
-            let animatableObjects = this._getAllAnimatableObjects(scene);
-            animatableObjects.forEach(animatableObject => {
-                animatableObject.animations = new Array<Animation>();
+            let nodes = scene.getNodes();
+            nodes.forEach(node => {
+                node.animations = new Array<Animation>();
             });
         }
         else {
@@ -1069,7 +1066,7 @@ export class SceneLoader {
                     });
                     break;
                 case SceneLoaderAnimationGroupLoadingMode.NOSYNC:
-                    // nothing
+                    // nothing to do
                     break;
                 default:
                     Logger.Error("Unknown animation group loading mode value '" + animationGroupLoadingMode + "'");
@@ -1101,87 +1098,4 @@ export class SceneLoader {
             });
         });
     }
-
-    /**
-     * Merge animations from an asset container into a scene
-     * @param scene is the instance of BABYLON.Scene to append to (default: last created scene)
-     * @param animationAssetContainer is the instance of BABYLON.AssetContainer containing animations
-     * @param targetConverter defines a function used to convert animation targets from the asset container to the scene (default: search node by name)
-     */
-    public static MergeAnimations(scene: Scene, animationAssetContainer: AssetContainer, targetConverter: Nullable<(target: any) => any> = null): void {
-
-        let _targetConverter = targetConverter ? targetConverter : this._defaultTargetConverter(scene);
-
-        // Copy node and bone animations
-        let animatableObjectsInAC = this._getAllAnimatableObjects(animationAssetContainer);
-        animatableObjectsInAC.forEach(animatableObjectInAC => {
-            let objectInScene = _targetConverter(animatableObjectInAC);
-            if (objectInScene != null) {
-                // Remove old animations with same target property as a new one
-                animatableObjectInAC.animations.forEach((animationInAC: Animation) => {
-                    // Doing treatment on an array for safety measure
-                    let animationsWithSameProperty = objectInScene.animations.filter((animationInScene: Animation) => {
-                        return animationInScene.targetProperty === animationInAC.targetProperty
-                    })
-                    animationsWithSameProperty.forEach((animationWithSameProperty: Animation) => {
-                        const index = objectInScene.animations.indexOf(animationWithSameProperty, 0);
-                        if (index > -1) {
-                            objectInScene.animations.splice(index, 1);
-                        }
-                    })
-                });
-
-                // Append new animations
-                objectInScene.animations = objectInScene.animations.concat(animatableObjectInAC.animations);
-            }
-        });
-
-        // Copy animation groups
-        animationAssetContainer.animationGroups.slice().forEach(animationGroupInAC => {
-            // Clone the animation group and all its animatables
-            animationGroupInAC.clone(animationGroupInAC.name, _targetConverter);
-
-            // Remove animatables related to the animation asset container
-            animationGroupInAC.animatables.forEach(animatable => {
-                animatable.stop();
-            })
-        });
-
-        // Copy animatables
-        scene.animatables.slice().forEach(animatable => {
-            let target = _targetConverter(animatable.target);
-
-            // If the animatable has just been loaded
-            if (target && target !== animatable.target) {
-                // Clone the animatable and retarget it
-                scene.beginAnimation(target, animatable.fromFrame, animatable.toFrame, animatable.loopAnimation, animatable.speedRatio, animatable.onAnimationEnd ? animatable.onAnimationEnd : undefined, undefined, true, undefined, animatable.onAnimationLoop ? animatable.onAnimationLoop : undefined);
-
-                // Stop animation for the target in the animation asset container
-                scene.stopAnimation(animatable.target);
-            }
-        });
-    }
-
-    /**
-     * Default target converter is searching bones and nodes by name
-     * @param scene 
-     */
-    private static _defaultTargetConverter(scene: Scene): (target: any) => any {
-        return (target: any) => { return scene.getBoneByName(target.name) || scene.getNodeByName(target.name) };
-    };
-
-    /**
-     * Return all objects that can hold an animations array
-     * @param abstractScene 
-     */
-    private static _getAllAnimatableObjects(abstractScene: AbstractScene) {
-        let animatableObjects = new Array<any>();
-        animatableObjects = animatableObjects.concat(abstractScene.meshes);
-        animatableObjects = animatableObjects.concat(abstractScene.lights);
-        animatableObjects = animatableObjects.concat(abstractScene.cameras);
-        animatableObjects = animatableObjects.concat(abstractScene.transformNodes); // dummies
-        abstractScene.skeletons.forEach(skeleton => animatableObjects = animatableObjects.concat(skeleton.bones));
-        animatableObjects = animatableObjects.filter(animatableObject => animatableObject.animations);
-        return animatableObjects;
-    }
 }

+ 13 - 0
src/abstractScene.ts

@@ -198,4 +198,17 @@ export abstract class AbstractScene {
      * Environment texture for the scene
      */
     public environmentTexture: Nullable<BaseTexture> = null;
+
+    /**
+     * Return all meshes, lights, cameras, transformNodes and bones
+     */
+    public getNodes(): Array<Node> {
+        let nodes = new Array<Node>();
+        nodes = nodes.concat(this.meshes);
+        nodes = nodes.concat(this.lights);
+        nodes = nodes.concat(this.cameras);
+        nodes = nodes.concat(this.transformNodes); // dummies
+        this.skeletons.forEach(skeleton => nodes = nodes.concat(skeleton.bones));
+        return nodes;
+    }
 }

+ 67 - 3
src/assetContainer.ts

@@ -7,6 +7,7 @@ import { AnimationGroup } from './Animations/animationGroup';
 import { AbstractMesh } from './Meshes/abstractMesh';
 import { MultiMaterial } from './Materials/multiMaterial';
 import { Material } from './Materials/material';
+import { Node, Nullable, Logger, EngineStore } from '.';
 
 /**
  * Set of assets to keep when moving a scene into an asset container.
@@ -65,8 +66,8 @@ export class AssetContainer extends AbstractScene {
      * @returns a list of rootNodes, skeletons and aniamtion groups that were duplicated
      */
     public instantiateModelsToScene(nameFunction?: (sourceName: string) => string, cloneMaterials = false): InstantiatedEntries {
-        let convertionMap: {[key: number]: number} = {};
-        let storeMap: {[key: number]: any} = {};
+        let convertionMap: { [key: number]: number } = {};
+        let storeMap: { [key: number]: any } = {};
         let result = new InstantiatedEntries();
         let alreadySwappedSkeletons: Skeleton[] = [];
         let alreadySwappedMaterials: Material[] = [];
@@ -170,7 +171,7 @@ export class AssetContainer extends AbstractScene {
         });
 
         this.skeletons.forEach((s) => {
-            let clone =  s.clone(nameFunction ? nameFunction(s.name) : "Clone of " + s.name);
+            let clone = s.clone(nameFunction ? nameFunction(s.name) : "Clone of " + s.name);
 
             if (s.overrideMesh) {
                 clone.overrideMesh = storeMap[convertionMap[s.overrideMesh.uniqueId]];
@@ -454,4 +455,67 @@ export class AssetContainer extends AbstractScene {
         this.meshes.unshift(rootMesh);
         return rootMesh;
     }
+
+    /**
+     * Merge animations from this asset container into a scene
+     * @param scene is the instance of BABYLON.Scene to append to (default: last created scene)
+     * @param targetConverter defines a function used to convert animation targets from the asset container to the scene (default: search node by name)
+     */
+    public MergeAnimationsTo(scene: Nullable<Scene> = EngineStore.LastCreatedScene, targetConverter: Nullable<(target: any) => Nullable<Node>> = null): void {
+        if (!scene) {
+            Logger.Error("No scene available to merge animations to");
+            return;
+        }
+
+        let _targetConverter = targetConverter ? targetConverter : (target: any) => { return scene.getBoneByName(target.name) || scene.getNodeByName(target.name) };
+
+        // Copy node animations
+        let nodesInAC = this.getNodes();
+        nodesInAC.forEach(nodeInAC => {
+            let nodeInScene = _targetConverter(nodeInAC);
+            if (nodeInScene != null) {
+                // Remove old animations with same target property as a new one
+                for (let animationInAC of nodeInAC.animations) {
+                    // Doing treatment on an array for safety measure
+                    let animationsWithSameProperty = nodeInScene.animations.filter(animationInScene => {
+                        return animationInScene.targetProperty === animationInAC.targetProperty
+                    });
+                    for (let animationWithSameProperty of animationsWithSameProperty) {
+                        const index = nodeInScene.animations.indexOf(animationWithSameProperty, 0);
+                        if (index > -1) {
+                            nodeInScene.animations.splice(index, 1);
+                        }
+                    }
+                }
+
+                // Append new animations
+                nodeInScene.animations = nodeInScene.animations.concat(nodeInAC.animations);
+            }
+        });
+
+        // Copy animation groups
+        this.animationGroups.slice().forEach(animationGroupInAC => {
+            // Clone the animation group and all its animatables
+            animationGroupInAC.clone(animationGroupInAC.name, _targetConverter);
+
+            // Remove animatables related to the asset container
+            animationGroupInAC.animatables.forEach(animatable => {
+                animatable.stop();
+            })
+        });
+
+        // Copy animatables
+        scene.animatables.slice().forEach(animatable => {
+            let target = _targetConverter(animatable.target);
+
+            // If the animatable has just been loaded
+            if (target && target !== animatable.target) {
+                // Clone the animatable and retarget it
+                scene.beginAnimation(target, animatable.fromFrame, animatable.toFrame, animatable.loopAnimation, animatable.speedRatio, animatable.onAnimationEnd ? animatable.onAnimationEnd : undefined, undefined, true, undefined, animatable.onAnimationLoop ? animatable.onAnimationLoop : undefined);
+
+                // Stop animation for the target in the asset container
+                scene.stopAnimation(animatable.target);
+            }
+        });
+    }
 }