Sfoglia il codice sorgente

Merge remote-tracking branch 'BabylonJS/master' into viewer-tests

Raanan Weber 7 anni fa
parent
commit
48bd3a48b3

File diff suppressed because it is too large
+ 28 - 20
.travis.yml


File diff suppressed because it is too large
+ 10230 - 11809
Playground/babylon.d.txt


+ 14 - 2
Tools/Publisher/index.js

@@ -84,8 +84,13 @@ function processPackages(version) {
             if (packageJson.peerDependencies) packageJson.peerDependencies.babylonjs = minimumDependency;
             fs.writeFileSync(package.path + 'package.json', JSON.stringify(packageJson, null, 4));
             console.log('Publishing ' + package.name + " from " + package.path);
+            let tagDef = "";
+            // check for alpha or beta
+            if (version.indexOf('alpha') !== -1 || version.indexOf('beta') !== -1) {
+                tagDef = '--tag preview';
+            }
             //publish the respected package
-            shelljs.exec('npm publish \"' + package.path + "\"");
+            shelljs.exec('npm publish \"' + package.path + "\"" + ' ' + tagDef);
         }
 
     });
@@ -185,8 +190,15 @@ function processCore(package, version) {
     fs.writeFileSync(basePath + '/package/' + 'package.json', JSON.stringify(packageJson, null, 4));
 
     console.log('Publishing ' + package.name + " from " + basePath + '/package/');
+
+    let tagDef = "";
+    // check for alpha or beta
+    if (version.indexOf('alpha') !== -1 || version.indexOf('beta') !== -1) {
+        tagDef = '--tag preview';
+    }
+
     //publish the respected package
-    shelljs.exec('npm publish \"' + basePath + '/package/' + "\"");
+    shelljs.exec('npm publish \"' + basePath + '/package/' + "\"" + ' ' + tagDef);
 
     // remove package directory
     fs.removeSync(basePath + '/package/');

+ 3 - 8
Viewer/dist/domExample.html

@@ -15,20 +15,15 @@
     </head>
 
     <body>
-        <babylon extends="minimal" scene.default-camera="false">
-            <model url="https://playground.babylonjs.com/scenes/BoomBox.glb" title="GLB Model" subtitle="BabylonJS">
+        <babylon extends="minimal">
+            <model url="https://playground.babylonjs.com/scenes/BoomBox.glb">
+                <scaling x="10" y="10" z="10"></scaling>
             </model>
             <camera>
                 <behaviors>
                     <auto-rotate type="0"></auto-rotate>
                 </behaviors>
             </camera>
-            <lights>
-                <light1 type="1" shadow-enabled="true" position.y="0.5" direction.y="-1" intensity="4.5">
-                    <shadow-config use-blur-exponential-shadow-map="true" use-kernel-blur="true" blur-kernel="64" blur-scale="4">
-                    </shadow-config>
-                </light1>
-            </lights>
         </babylon>
         <script src="viewer.js"></script>
     </body>

+ 3 - 4
Viewer/src/configuration/loader.ts

@@ -36,8 +36,6 @@ export class ConfigurationLoader {
 
         let extendedConfiguration = getConfigurationType(loadedConfig.extends || "");
 
-        loadedConfig = deepmerge(extendedConfiguration, loadedConfig);
-
         if (loadedConfig.configuration) {
 
             let mapperType = "json";
@@ -72,13 +70,14 @@ export class ConfigurationLoader {
                 }
             }).then((data: any) => {
                 let mapper = mapperManager.getMapper(mapperType);
-                let parsed = mapper.map(data);
-                let merged = deepmerge(loadedConfig, parsed);
+                let parsed = deepmerge(mapper.map(data), loadedConfig);
+                let merged = deepmerge(extendedConfiguration, parsed);
                 processConfigurationCompatibility(merged);
                 if (callback) callback(merged);
                 return merged;
             });
         } else {
+            loadedConfig = deepmerge(extendedConfiguration, loadedConfig);
             processConfigurationCompatibility(loadedConfig);
             if (callback) callback(loadedConfig);
             return Promise.resolve(loadedConfig);

+ 6 - 0
Viewer/src/configuration/types/minimal.ts

@@ -10,6 +10,12 @@ export let minimalConfiguration: ViewerConfiguration = {
         main: {
             html: require("../../../assets/templates/default/defaultTemplate.html")
         },
+        fillContainer: {
+            html: require("../../../assets/templates/default/fillContainer.html"),
+            params: {
+                disable: false
+            }
+        },
         loadingScreen: {
             html: require("../../../assets/templates/default/loadingScreen.html"),
             params: {

+ 1 - 1
Viewer/src/loader/plugins/index.ts

@@ -22,7 +22,7 @@ export function getLoaderPluginByName(name: string) {
                 pluginCache[name] = new MSFTLodLoaderPlugin();
                 break;
             case 'applyMaterialConfig':
-                pluginCache[name] = new MSFTLodLoaderPlugin();
+                pluginCache[name] = new ApplyMaterialConfigPlugin();
                 break;
             case 'extendedMaterial':
                 pluginCache[name] = new ExtendedMaterialLoaderPlugin();

+ 6 - 0
Viewer/src/model/viewerModel.ts

@@ -125,6 +125,11 @@ export class ViewerModel implements IDisposable {
 
         this._viewer.sceneManager.models.push(this);
         this._viewer.onModelAddedObservable.notifyObservers(this);
+
+        if (this._modelConfiguration.entryAnimation) {
+            this.rootMesh.setEnabled(false);
+        }
+
         this.onLoadedObservable.add(() => {
             this.updateConfiguration(this._modelConfiguration);
             this._viewer.onModelLoadedObservable.notifyObservers(this);
@@ -273,6 +278,7 @@ export class ViewerModel implements IDisposable {
             callback();
             return;
         }
+        this.rootMesh.setEnabled(true);
         // disable blending for the sake of the entry animation;
         this._viewer.sceneManager.animationBlendingEnabled = false;
         this._applyAnimation(this._entryAnimation, true, callback);

+ 17 - 12
Viewer/src/viewer/sceneManager.ts

@@ -123,21 +123,26 @@ export class SceneManager {
         this.labs = new ViewerLabs(this);
 
         this.onSceneInitObservable.add((scene) => {
-            scene.registerBeforeRender(() => {
-                if (this.models.length && scene.animatables && scene.animatables.length > 0) {
-                    // make sure all models are loaded
-                    if (this.models.every((model) => model.state === ModelState.COMPLETE && !model.currentAnimation)) return;
-                    for (let light of this.scene.lights) {
-                        let generator = light.getShadowGenerator();
-                        if (generator) {
-                            // Processing shadows if animates
-                            let shadowMap = generator.getShadowMap();
-                            if (shadowMap) {
-                                shadowMap.refreshRate = RenderTargetTexture.REFRESHRATE_RENDER_ONCE;
-                            }
+
+            let updateShadows = () => {
+                for (let light of this.scene.lights) {
+                    let generator = light.getShadowGenerator();
+                    if (generator) {
+                        // Processing shadows if animates
+                        let shadowMap = generator.getShadowMap();
+                        if (shadowMap) {
+                            shadowMap.refreshRate = RenderTargetTexture.REFRESHRATE_RENDER_ONCE;
                         }
                     }
                 }
+            }
+            scene.registerBeforeRender(() => {
+                if (scene.animatables && scene.animatables.length > 0) {
+                    // make sure all models are loaded
+                    updateShadows();
+                } else if (!(this.models.every((model) => model.state === ModelState.COMPLETE && !model.currentAnimation))) {
+                    updateShadows();
+                }
             });
             return this._viewer.onSceneInitObservable.notifyObserversWithPromise(this.scene);
         });

+ 3 - 2
Viewer/src/viewer/viewer.ts

@@ -533,7 +533,7 @@ export abstract class AbstractViewer {
             throw new Error("no model url provided");
         }
         if (clearScene) {
-
+            this.sceneManager.clearScene(true, false);
         }
         let configuration: IModelConfiguration;
         if (typeof modelConfig === 'string') {
@@ -546,7 +546,8 @@ export abstract class AbstractViewer {
 
         //merge the configuration for future models:
         if (this._configuration.model && typeof this._configuration.model === 'object') {
-            deepmerge(this._configuration.model, configuration)
+            let globalConfig = deepmerge({}, this._configuration.model)
+            configuration = deepmerge(globalConfig, configuration);
         } else {
             this._configuration.model = configuration;
         }

File diff suppressed because it is too large
+ 10459 - 10251
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 35 - 35
dist/preview release/babylon.js


+ 229 - 24
dist/preview release/babylon.max.js

@@ -15211,6 +15211,7 @@ var BABYLON;
             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
             gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(fullOptions.type, fullOptions.format), width, height, 0, this._getInternalFormat(fullOptions.format), this._getWebGLTextureType(fullOptions.type), null);
             // Create the framebuffer
+            var currentFrameBuffer = this._currentFramebuffer;
             var framebuffer = gl.createFramebuffer();
             this.bindUnboundFramebuffer(framebuffer);
             gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture._webGLTexture, 0);
@@ -15221,7 +15222,7 @@ var BABYLON;
             // Unbind
             this._bindTextureDirectly(gl.TEXTURE_2D, null);
             gl.bindRenderbuffer(gl.RENDERBUFFER, null);
-            this.bindUnboundFramebuffer(null);
+            this.bindUnboundFramebuffer(currentFrameBuffer);
             texture._framebuffer = framebuffer;
             texture.baseWidth = width;
             texture.baseHeight = height;
@@ -26249,8 +26250,11 @@ var BABYLON;
         /**
          * Add a mesh to the list of scene's meshes
          * @param newMesh defines the mesh to add
+         * @param recursive if all child meshes should also be added to the scene
          */
-        Scene.prototype.addMesh = function (newMesh) {
+        Scene.prototype.addMesh = function (newMesh, recursive) {
+            var _this = this;
+            if (recursive === void 0) { recursive = false; }
             this.meshes.push(newMesh);
             //notify the collision coordinator
             if (this.collisionCoordinator) {
@@ -26258,6 +26262,11 @@ var BABYLON;
             }
             newMesh._resyncLightSources();
             this.onNewMeshAddedObservable.notifyObservers(newMesh);
+            if (recursive) {
+                newMesh.getChildMeshes().forEach(function (m) {
+                    _this.addMesh(m);
+                });
+            }
         };
         /**
            * Remove a mesh for the list of scene's meshes
@@ -29337,6 +29346,20 @@ var BABYLON;
             this._moveAssets(this.scene.effectLayers, this.effectLayers, keepAssets.effectLayers);
             this.removeAllFromScene();
         };
+        /**
+         * Adds all meshes in the asset container to a root mesh that can be used to position all the contained meshes. The root mesh is then added to the front of the meshes in the assetContainer.
+         * @returns the root mesh
+         */
+        AssetContainer.prototype.createRootMesh = function () {
+            var rootMesh = new BABYLON.Mesh("assetContainerRootMesh", this.scene);
+            this.meshes.forEach(function (m) {
+                if (!m.parent) {
+                    rootMesh.addChild(m);
+                }
+            });
+            this.meshes.unshift(rootMesh);
+            return rootMesh;
+        };
         return AssetContainer;
     }());
     BABYLON.AssetContainer = AssetContainer;
@@ -50940,7 +50963,7 @@ var BABYLON;
             return node.getScene().beginAnimation(node, 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
         };
         /**
-         * Transition property of the Camera to the target Value
+         * Transition property of an host to the target Value
          * @param property The property to transition
          * @param targetValue The target Value of the property
          * @param host The object where the property to animate belongs
@@ -62321,6 +62344,41 @@ var BABYLON;
 (function (BABYLON) {
     /**
      * Draco compression (https://google.github.io/draco/)
+     *
+     * This class wraps the Draco module.
+     *
+     * **Encoder**
+     *
+     * The encoder is not currently implemented.
+     *
+     * **Decoder**
+     *
+     * By default, the configuration points to a copy of the Draco decoder files for glTF from https://preview.babylonjs.com.
+     *
+     * To update the configuration, use the following code:
+     * ```javascript
+     *     BABYLON.DracoCompression.Configuration = {
+     *         decoder: {
+     *             wasmUrl: "<url to the WebAssembly library>",
+     *             wasmBinaryUrl: "<url to the WebAssembly binary>",
+     *             fallbackUrl: "<url to the fallback JavaScript library>",
+     *         }
+     *     };
+     * ```
+     *
+     * Draco has two versions, one for WebAssembly and one for JavaScript. The decoder configuration can be set to only support Webssembly or only support the JavaScript version.
+     * Decoding will automatically fallback to the JavaScript version if WebAssembly version is not configured or if WebAssembly is not supported by the browser.
+     * Use `BABYLON.DracoCompression.DecoderAvailable` to determine if the decoder is available for the current session.
+     *
+     * To decode Draco compressed data, create a DracoCompression object and call decodeMeshAsync:
+     * ```javascript
+     *     var dracoCompression = new BABYLON.DracoCompression();
+     *     var vertexData = await dracoCompression.decodeMeshAsync(data, {
+     *         [BABYLON.VertexBuffer.PositionKind]: 0
+     *     });
+     * ```
+     *
+     * @see https://www.babylonjs-playground.com/#N3EK4B#0
      */
     var DracoCompression = /** @class */ (function () {
         /**
@@ -62357,16 +62415,17 @@ var BABYLON;
         };
         /**
          * Decode Draco compressed mesh data to vertex data.
-         * @param data The array buffer view for the Draco compression data
+         * @param data The ArrayBuffer or ArrayBufferView for the Draco compression data
          * @param attributes A map of attributes from vertex buffer kinds to Draco unique ids
          * @returns A promise that resolves with the decoded vertex data
          */
         DracoCompression.prototype.decodeMeshAsync = function (data, attributes) {
+            var dataView = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
             return DracoCompression._GetDecoderModule().then(function (wrappedModule) {
                 var module = wrappedModule.module;
                 var vertexData = new BABYLON.VertexData();
                 var buffer = new module.DecoderBuffer();
-                buffer.Init(data, data.byteLength);
+                buffer.Init(dataView, dataView.byteLength);
                 var decoder = new module.Decoder();
                 var geometry;
                 var status;
@@ -62490,7 +62549,10 @@ var BABYLON;
             });
         };
         /**
-         * The configuration.
+         * The configuration. Defaults to the following urls:
+         * - wasmUrl: "https://preview.babylonjs.com/draco_wasm_wrapper_gltf.js"
+         * - wasmBinaryUrl: "https://preview.babylonjs.com/draco_decoder_gltf.wasm"
+         * - fallbackUrl: "https://preview.babylonjs.com/draco_decoder_gltf.js"
          */
         DracoCompression.Configuration = {
             decoder: {
@@ -67525,7 +67587,7 @@ var BABYLON;
             if (registeredPlugin) {
                 return registeredPlugin;
             }
-            BABYLON.Tools.Warn("Unable to find a plugin to load " + extension + " files. Trying to use .babylon default plugin.");
+            BABYLON.Tools.Warn("Unable to find a plugin to load " + extension + " files. Trying to use .babylon default plugin. To load from a specific filetype (eg. gltf) see: http://doc.babylonjs.com/how_to/load_from_any_file_type");
             return SceneLoader._getDefaultPlugin();
         };
         SceneLoader._getPluginForDirectLoad = function (data) {
@@ -67671,8 +67733,8 @@ var BABYLON;
         /**
          * Import meshes into a scene
          * @param meshNames an array of mesh names, a single mesh name, or empty string for all meshes that filter what meshes are imported
-         * @param rootUrl a string that defines the root url for scene and resources
-         * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+         * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+         * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
          * @param scene the instance of BABYLON.Scene to append to
          * @param onSuccess a callback with a list of imported meshes, particleSystems, and skeletons when import succeeds
          * @param onProgress a callback with a progress event for each file being loaded
@@ -67681,10 +67743,20 @@ var BABYLON;
          * @returns The loaded plugin
          */
         SceneLoader.ImportMesh = function (meshNames, rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onSuccess === void 0) { onSuccess = null; }
             if (onProgress === void 0) { onProgress = null; }
             if (onError === void 0) { onError = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
+            if (!scene) {
+                BABYLON.Tools.Error("No scene available to import mesh to");
+                return null;
+            }
+            if (!sceneFilename) {
+                sceneFilename = BABYLON.Tools.GetFilename(rootUrl);
+                rootUrl = BABYLON.Tools.GetFolderPath(rootUrl);
+            }
             if (sceneFilename.substr && sceneFilename.substr(0, 1) === "/") {
                 BABYLON.Tools.Error("Wrong sceneFilename parameter");
                 return null;
@@ -67759,14 +67831,16 @@ var BABYLON;
         /**
         * Import meshes into a scene
         * @param meshNames an array of mesh names, a single mesh name, or empty string for all meshes that filter what meshes are imported
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param scene the instance of BABYLON.Scene to append to
         * @param onProgress a callback with a progress event for each file being loaded
         * @param pluginExtension the extension used to determine the plugin
         * @returns The loaded list of imported meshes, particle systems, skeletons, and animation groups
         */
         SceneLoader.ImportMeshAsync = function (meshNames, rootUrl, sceneFilename, scene, onProgress, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onProgress === void 0) { onProgress = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
             return new Promise(function (resolve, reject) {
@@ -67784,8 +67858,8 @@ var BABYLON;
         };
         /**
         * Load a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param engine is the instance of BABYLON.Engine to use to create the scene
         * @param onSuccess a callback with the scene when import succeeds
         * @param onProgress a callback with a progress event for each file being loaded
@@ -67802,8 +67876,8 @@ var BABYLON;
         };
         /**
         * Load a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param engine is the instance of BABYLON.Engine to use to create the scene
         * @param onProgress a callback with a progress event for each file being loaded
         * @param pluginExtension the extension used to determine the plugin
@@ -67822,8 +67896,8 @@ var BABYLON;
         };
         /**
         * Append a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param scene is the instance of BABYLON.Scene to append to
         * @param onSuccess a callback with the scene when import succeeds
         * @param onProgress a callback with a progress event for each file being loaded
@@ -67832,10 +67906,20 @@ var BABYLON;
         * @returns The loaded plugin
         */
         SceneLoader.Append = function (rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onSuccess === void 0) { onSuccess = null; }
             if (onProgress === void 0) { onProgress = null; }
             if (onError === void 0) { onError = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
+            if (!scene) {
+                BABYLON.Tools.Error("No scene available to append to");
+                return null;
+            }
+            if (!sceneFilename) {
+                sceneFilename = BABYLON.Tools.GetFilename(rootUrl);
+                rootUrl = BABYLON.Tools.GetFolderPath(rootUrl);
+            }
             if (sceneFilename.substr && sceneFilename.substr(0, 1) === "/") {
                 BABYLON.Tools.Error("Wrong sceneFilename parameter");
                 return null;
@@ -67909,14 +67993,16 @@ var BABYLON;
         };
         /**
         * Append a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param scene is the instance of BABYLON.Scene to append to
         * @param onProgress a callback with a progress event for each file being loaded
         * @param pluginExtension the extension used to determine the plugin
         * @returns The given scene
         */
         SceneLoader.AppendAsync = function (rootUrl, sceneFilename, scene, onProgress, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onProgress === void 0) { onProgress = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
             return new Promise(function (resolve, reject) {
@@ -67929,9 +68015,9 @@ var BABYLON;
         };
         /**
         * Load a scene into an asset container
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
-        * @param scene is the instance of BABYLON.Scene to append to
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
+        * @param scene is the instance of BABYLON.Scene to append to (default: last created scene)
         * @param onSuccess a callback with the scene when import succeeds
         * @param onProgress a callback with a progress event for each file being loaded
         * @param onError a callback with the scene, a message, and possibly an exception when import fails
@@ -67939,10 +68025,20 @@ var BABYLON;
         * @returns The loaded plugin
         */
         SceneLoader.LoadAssetContainer = function (rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onSuccess === void 0) { onSuccess = null; }
             if (onProgress === void 0) { onProgress = null; }
             if (onError === void 0) { onError = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
+            if (!scene) {
+                BABYLON.Tools.Error("No scene available to load asset container to");
+                return null;
+            }
+            if (!sceneFilename) {
+                sceneFilename = BABYLON.Tools.GetFilename(rootUrl);
+                rootUrl = BABYLON.Tools.GetFolderPath(rootUrl);
+            }
             if (sceneFilename.substr && sceneFilename.substr(0, 1) === "/") {
                 BABYLON.Tools.Error("Wrong sceneFilename parameter");
                 return null;
@@ -68013,14 +68109,16 @@ var BABYLON;
         };
         /**
         * Load a scene into an asset container
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param scene is the instance of BABYLON.Scene to append to
         * @param onProgress a callback with a progress event for each file being loaded
         * @param pluginExtension the extension used to determine the plugin
         * @returns The loaded asset container
         */
         SceneLoader.LoadAssetContainerAsync = function (rootUrl, sceneFilename, scene, onProgress, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onProgress === void 0) { onProgress = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
             return new Promise(function (resolve, reject) {
@@ -98641,6 +98739,113 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.environmentHelper.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    /**
+     * This class is made for on one-liner static method to help creating particle systems.
+     */
+    var ParticleHelper = /** @class */ (function () {
+        function ParticleHelper() {
+        }
+        /**
+         * This is the main static method (one-liner) of this helper to create different particle systems.
+         * @param type This string represents the type to the particle system to create
+         * @param emitter The object where the particle system will start to emit from.
+         * @param scene The scene where the particle system should live.
+         * @param gpu If the system will use gpu.
+         * @returns the ParticleSystem created.
+         */
+        ParticleHelper.CreateAsync = function (type, emitter, scene, gpu) {
+            var _this = this;
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
+            if (gpu === void 0) { gpu = false; }
+            return new Promise(function (resolve, reject) {
+                if (scene) {
+                    _this._scene = scene;
+                }
+                else {
+                    return reject("A particle system need a scene.");
+                }
+                if (gpu && !BABYLON.GPUParticleSystem.IsSupported) {
+                    return reject("Particle system with GPU is not supported.");
+                }
+                _this._emitter = emitter;
+                BABYLON.Tools.LoadFile(_this._baseAssetsUrl + "/systems/" + type + ".json", function (data, response) {
+                    var newData = JSON.parse(data.toString());
+                    return resolve(_this._createSystem(newData));
+                }, undefined, undefined, undefined, function (req, exception) {
+                    return reject("An error occured while the creation of your particle system. Check if your type '" + type + "' exists.");
+                });
+            });
+        };
+        ParticleHelper._createSystem = function (data) {
+            // Create a particle system
+            var system = new BABYLON.ParticleSystem(data.type, data.capacity, this._scene);
+            // Texture of each particle
+            system.particleTexture = new BABYLON.Texture(this._baseAssetsUrl + "/textures/" + data.textureFile, this._scene);
+            // Where the particles come from
+            system.emitter = this._emitter; // the starting object, the emitter
+            // Colors of all particles
+            system.color1 = new BABYLON.Color4(data.color1.r, data.color1.g, data.color1.b, data.color1.a);
+            system.color2 = new BABYLON.Color4(data.color2.r, data.color2.g, data.color2.b, data.color2.a);
+            system.colorDead = new BABYLON.Color4(data.colorDead.r, data.colorDead.g, data.colorDead.b, data.colorDead.a);
+            // Size of each particle (random between...
+            system.minSize = data.minSize;
+            system.maxSize = data.maxSize;
+            // Life time of each particle (random between...
+            system.minLifeTime = data.minLifeTime;
+            system.maxLifeTime = data.maxLifeTime;
+            // Emission rate
+            system.emitRate = data.emitRate;
+            // Blend mode : BLENDMODE_ONEONE, or BLENDMODE_STANDARD
+            system.blendMode = data.blendMode;
+            // Set the gravity of all particles
+            system.gravity = new BABYLON.Vector3(data.gravity.x, data.gravity.y, data.gravity.z);
+            // Angular speed, in radians
+            system.minAngularSpeed = data.minAngularSpeed;
+            system.maxAngularSpeed = data.maxAngularSpeed;
+            // Speed
+            system.minEmitPower = data.minEmitPower;
+            system.maxEmitPower = data.maxEmitPower;
+            system.updateSpeed = data.updateSpeed;
+            switch (data.emitterType) {
+                case "box":
+                    if (!data.direction1 || !data.direction2) {
+                        throw new Error("Directions are missing in this particle system.");
+                    }
+                    if (!data.minEmitBox || !data.maxEmitBox) {
+                        throw new Error("EmitBox is missing in this particle system.");
+                    }
+                    system.createBoxEmitter(new BABYLON.Vector3(data.direction1.x, data.direction1.y, data.direction1.z), new BABYLON.Vector3(data.direction2.x, data.direction2.y, data.direction2.z), new BABYLON.Vector3(data.minEmitBox.x, data.minEmitBox.y, data.minEmitBox.z), new BABYLON.Vector3(data.maxEmitBox.x, data.maxEmitBox.y, data.maxEmitBox.z));
+                    break;
+                case "sphere":
+                    system.createSphereEmitter(data.radius);
+                    break;
+                case "directed_sphere":
+                    if (!data.direction1 || !data.direction2) {
+                        throw new Error("Directions are missing in this particle system.");
+                    }
+                    system.createDirectedSphereEmitter(data.radius, new BABYLON.Vector3(data.direction1.x, data.direction1.y, data.direction1.z), new BABYLON.Vector3(data.direction2.x, data.direction2.y, data.direction2.z));
+                    break;
+                case "cone":
+                    system.createConeEmitter(data.radius, data.angle);
+                    break;
+                default:
+                    break;
+            }
+            return system;
+        };
+        /**
+         * Base Assets URL.
+         */
+        ParticleHelper._baseAssetsUrl = "https://assets.babylonjs.com/particles";
+        return ParticleHelper;
+    }());
+    BABYLON.ParticleHelper = ParticleHelper;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.particleHelper.js.map
+
 
 var BABYLON;
 (function (BABYLON) {

+ 229 - 24
dist/preview release/babylon.no-module.max.js

@@ -15178,6 +15178,7 @@ var BABYLON;
             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
             gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(fullOptions.type, fullOptions.format), width, height, 0, this._getInternalFormat(fullOptions.format), this._getWebGLTextureType(fullOptions.type), null);
             // Create the framebuffer
+            var currentFrameBuffer = this._currentFramebuffer;
             var framebuffer = gl.createFramebuffer();
             this.bindUnboundFramebuffer(framebuffer);
             gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture._webGLTexture, 0);
@@ -15188,7 +15189,7 @@ var BABYLON;
             // Unbind
             this._bindTextureDirectly(gl.TEXTURE_2D, null);
             gl.bindRenderbuffer(gl.RENDERBUFFER, null);
-            this.bindUnboundFramebuffer(null);
+            this.bindUnboundFramebuffer(currentFrameBuffer);
             texture._framebuffer = framebuffer;
             texture.baseWidth = width;
             texture.baseHeight = height;
@@ -26216,8 +26217,11 @@ var BABYLON;
         /**
          * Add a mesh to the list of scene's meshes
          * @param newMesh defines the mesh to add
+         * @param recursive if all child meshes should also be added to the scene
          */
-        Scene.prototype.addMesh = function (newMesh) {
+        Scene.prototype.addMesh = function (newMesh, recursive) {
+            var _this = this;
+            if (recursive === void 0) { recursive = false; }
             this.meshes.push(newMesh);
             //notify the collision coordinator
             if (this.collisionCoordinator) {
@@ -26225,6 +26229,11 @@ var BABYLON;
             }
             newMesh._resyncLightSources();
             this.onNewMeshAddedObservable.notifyObservers(newMesh);
+            if (recursive) {
+                newMesh.getChildMeshes().forEach(function (m) {
+                    _this.addMesh(m);
+                });
+            }
         };
         /**
            * Remove a mesh for the list of scene's meshes
@@ -29304,6 +29313,20 @@ var BABYLON;
             this._moveAssets(this.scene.effectLayers, this.effectLayers, keepAssets.effectLayers);
             this.removeAllFromScene();
         };
+        /**
+         * Adds all meshes in the asset container to a root mesh that can be used to position all the contained meshes. The root mesh is then added to the front of the meshes in the assetContainer.
+         * @returns the root mesh
+         */
+        AssetContainer.prototype.createRootMesh = function () {
+            var rootMesh = new BABYLON.Mesh("assetContainerRootMesh", this.scene);
+            this.meshes.forEach(function (m) {
+                if (!m.parent) {
+                    rootMesh.addChild(m);
+                }
+            });
+            this.meshes.unshift(rootMesh);
+            return rootMesh;
+        };
         return AssetContainer;
     }());
     BABYLON.AssetContainer = AssetContainer;
@@ -50907,7 +50930,7 @@ var BABYLON;
             return node.getScene().beginAnimation(node, 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
         };
         /**
-         * Transition property of the Camera to the target Value
+         * Transition property of an host to the target Value
          * @param property The property to transition
          * @param targetValue The target Value of the property
          * @param host The object where the property to animate belongs
@@ -62288,6 +62311,41 @@ var BABYLON;
 (function (BABYLON) {
     /**
      * Draco compression (https://google.github.io/draco/)
+     *
+     * This class wraps the Draco module.
+     *
+     * **Encoder**
+     *
+     * The encoder is not currently implemented.
+     *
+     * **Decoder**
+     *
+     * By default, the configuration points to a copy of the Draco decoder files for glTF from https://preview.babylonjs.com.
+     *
+     * To update the configuration, use the following code:
+     * ```javascript
+     *     BABYLON.DracoCompression.Configuration = {
+     *         decoder: {
+     *             wasmUrl: "<url to the WebAssembly library>",
+     *             wasmBinaryUrl: "<url to the WebAssembly binary>",
+     *             fallbackUrl: "<url to the fallback JavaScript library>",
+     *         }
+     *     };
+     * ```
+     *
+     * Draco has two versions, one for WebAssembly and one for JavaScript. The decoder configuration can be set to only support Webssembly or only support the JavaScript version.
+     * Decoding will automatically fallback to the JavaScript version if WebAssembly version is not configured or if WebAssembly is not supported by the browser.
+     * Use `BABYLON.DracoCompression.DecoderAvailable` to determine if the decoder is available for the current session.
+     *
+     * To decode Draco compressed data, create a DracoCompression object and call decodeMeshAsync:
+     * ```javascript
+     *     var dracoCompression = new BABYLON.DracoCompression();
+     *     var vertexData = await dracoCompression.decodeMeshAsync(data, {
+     *         [BABYLON.VertexBuffer.PositionKind]: 0
+     *     });
+     * ```
+     *
+     * @see https://www.babylonjs-playground.com/#N3EK4B#0
      */
     var DracoCompression = /** @class */ (function () {
         /**
@@ -62324,16 +62382,17 @@ var BABYLON;
         };
         /**
          * Decode Draco compressed mesh data to vertex data.
-         * @param data The array buffer view for the Draco compression data
+         * @param data The ArrayBuffer or ArrayBufferView for the Draco compression data
          * @param attributes A map of attributes from vertex buffer kinds to Draco unique ids
          * @returns A promise that resolves with the decoded vertex data
          */
         DracoCompression.prototype.decodeMeshAsync = function (data, attributes) {
+            var dataView = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
             return DracoCompression._GetDecoderModule().then(function (wrappedModule) {
                 var module = wrappedModule.module;
                 var vertexData = new BABYLON.VertexData();
                 var buffer = new module.DecoderBuffer();
-                buffer.Init(data, data.byteLength);
+                buffer.Init(dataView, dataView.byteLength);
                 var decoder = new module.Decoder();
                 var geometry;
                 var status;
@@ -62457,7 +62516,10 @@ var BABYLON;
             });
         };
         /**
-         * The configuration.
+         * The configuration. Defaults to the following urls:
+         * - wasmUrl: "https://preview.babylonjs.com/draco_wasm_wrapper_gltf.js"
+         * - wasmBinaryUrl: "https://preview.babylonjs.com/draco_decoder_gltf.wasm"
+         * - fallbackUrl: "https://preview.babylonjs.com/draco_decoder_gltf.js"
          */
         DracoCompression.Configuration = {
             decoder: {
@@ -67492,7 +67554,7 @@ var BABYLON;
             if (registeredPlugin) {
                 return registeredPlugin;
             }
-            BABYLON.Tools.Warn("Unable to find a plugin to load " + extension + " files. Trying to use .babylon default plugin.");
+            BABYLON.Tools.Warn("Unable to find a plugin to load " + extension + " files. Trying to use .babylon default plugin. To load from a specific filetype (eg. gltf) see: http://doc.babylonjs.com/how_to/load_from_any_file_type");
             return SceneLoader._getDefaultPlugin();
         };
         SceneLoader._getPluginForDirectLoad = function (data) {
@@ -67638,8 +67700,8 @@ var BABYLON;
         /**
          * Import meshes into a scene
          * @param meshNames an array of mesh names, a single mesh name, or empty string for all meshes that filter what meshes are imported
-         * @param rootUrl a string that defines the root url for scene and resources
-         * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+         * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+         * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
          * @param scene the instance of BABYLON.Scene to append to
          * @param onSuccess a callback with a list of imported meshes, particleSystems, and skeletons when import succeeds
          * @param onProgress a callback with a progress event for each file being loaded
@@ -67648,10 +67710,20 @@ var BABYLON;
          * @returns The loaded plugin
          */
         SceneLoader.ImportMesh = function (meshNames, rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onSuccess === void 0) { onSuccess = null; }
             if (onProgress === void 0) { onProgress = null; }
             if (onError === void 0) { onError = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
+            if (!scene) {
+                BABYLON.Tools.Error("No scene available to import mesh to");
+                return null;
+            }
+            if (!sceneFilename) {
+                sceneFilename = BABYLON.Tools.GetFilename(rootUrl);
+                rootUrl = BABYLON.Tools.GetFolderPath(rootUrl);
+            }
             if (sceneFilename.substr && sceneFilename.substr(0, 1) === "/") {
                 BABYLON.Tools.Error("Wrong sceneFilename parameter");
                 return null;
@@ -67726,14 +67798,16 @@ var BABYLON;
         /**
         * Import meshes into a scene
         * @param meshNames an array of mesh names, a single mesh name, or empty string for all meshes that filter what meshes are imported
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param scene the instance of BABYLON.Scene to append to
         * @param onProgress a callback with a progress event for each file being loaded
         * @param pluginExtension the extension used to determine the plugin
         * @returns The loaded list of imported meshes, particle systems, skeletons, and animation groups
         */
         SceneLoader.ImportMeshAsync = function (meshNames, rootUrl, sceneFilename, scene, onProgress, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onProgress === void 0) { onProgress = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
             return new Promise(function (resolve, reject) {
@@ -67751,8 +67825,8 @@ var BABYLON;
         };
         /**
         * Load a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param engine is the instance of BABYLON.Engine to use to create the scene
         * @param onSuccess a callback with the scene when import succeeds
         * @param onProgress a callback with a progress event for each file being loaded
@@ -67769,8 +67843,8 @@ var BABYLON;
         };
         /**
         * Load a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param engine is the instance of BABYLON.Engine to use to create the scene
         * @param onProgress a callback with a progress event for each file being loaded
         * @param pluginExtension the extension used to determine the plugin
@@ -67789,8 +67863,8 @@ var BABYLON;
         };
         /**
         * Append a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param scene is the instance of BABYLON.Scene to append to
         * @param onSuccess a callback with the scene when import succeeds
         * @param onProgress a callback with a progress event for each file being loaded
@@ -67799,10 +67873,20 @@ var BABYLON;
         * @returns The loaded plugin
         */
         SceneLoader.Append = function (rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onSuccess === void 0) { onSuccess = null; }
             if (onProgress === void 0) { onProgress = null; }
             if (onError === void 0) { onError = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
+            if (!scene) {
+                BABYLON.Tools.Error("No scene available to append to");
+                return null;
+            }
+            if (!sceneFilename) {
+                sceneFilename = BABYLON.Tools.GetFilename(rootUrl);
+                rootUrl = BABYLON.Tools.GetFolderPath(rootUrl);
+            }
             if (sceneFilename.substr && sceneFilename.substr(0, 1) === "/") {
                 BABYLON.Tools.Error("Wrong sceneFilename parameter");
                 return null;
@@ -67876,14 +67960,16 @@ var BABYLON;
         };
         /**
         * Append a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param scene is the instance of BABYLON.Scene to append to
         * @param onProgress a callback with a progress event for each file being loaded
         * @param pluginExtension the extension used to determine the plugin
         * @returns The given scene
         */
         SceneLoader.AppendAsync = function (rootUrl, sceneFilename, scene, onProgress, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onProgress === void 0) { onProgress = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
             return new Promise(function (resolve, reject) {
@@ -67896,9 +67982,9 @@ var BABYLON;
         };
         /**
         * Load a scene into an asset container
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
-        * @param scene is the instance of BABYLON.Scene to append to
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
+        * @param scene is the instance of BABYLON.Scene to append to (default: last created scene)
         * @param onSuccess a callback with the scene when import succeeds
         * @param onProgress a callback with a progress event for each file being loaded
         * @param onError a callback with the scene, a message, and possibly an exception when import fails
@@ -67906,10 +67992,20 @@ var BABYLON;
         * @returns The loaded plugin
         */
         SceneLoader.LoadAssetContainer = function (rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onSuccess === void 0) { onSuccess = null; }
             if (onProgress === void 0) { onProgress = null; }
             if (onError === void 0) { onError = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
+            if (!scene) {
+                BABYLON.Tools.Error("No scene available to load asset container to");
+                return null;
+            }
+            if (!sceneFilename) {
+                sceneFilename = BABYLON.Tools.GetFilename(rootUrl);
+                rootUrl = BABYLON.Tools.GetFolderPath(rootUrl);
+            }
             if (sceneFilename.substr && sceneFilename.substr(0, 1) === "/") {
                 BABYLON.Tools.Error("Wrong sceneFilename parameter");
                 return null;
@@ -67980,14 +68076,16 @@ var BABYLON;
         };
         /**
         * Load a scene into an asset container
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param rootUrl a string that defines the root url for scene and resources OR the concatenation of rootURL and filename (eg. http://example.com/test.glb)
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene (default: empty string)
         * @param scene is the instance of BABYLON.Scene to append to
         * @param onProgress a callback with a progress event for each file being loaded
         * @param pluginExtension the extension used to determine the plugin
         * @returns The loaded asset container
         */
         SceneLoader.LoadAssetContainerAsync = function (rootUrl, sceneFilename, scene, onProgress, pluginExtension) {
+            if (sceneFilename === void 0) { sceneFilename = ""; }
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
             if (onProgress === void 0) { onProgress = null; }
             if (pluginExtension === void 0) { pluginExtension = null; }
             return new Promise(function (resolve, reject) {
@@ -98608,6 +98706,113 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.environmentHelper.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    /**
+     * This class is made for on one-liner static method to help creating particle systems.
+     */
+    var ParticleHelper = /** @class */ (function () {
+        function ParticleHelper() {
+        }
+        /**
+         * This is the main static method (one-liner) of this helper to create different particle systems.
+         * @param type This string represents the type to the particle system to create
+         * @param emitter The object where the particle system will start to emit from.
+         * @param scene The scene where the particle system should live.
+         * @param gpu If the system will use gpu.
+         * @returns the ParticleSystem created.
+         */
+        ParticleHelper.CreateAsync = function (type, emitter, scene, gpu) {
+            var _this = this;
+            if (scene === void 0) { scene = BABYLON.Engine.LastCreatedScene; }
+            if (gpu === void 0) { gpu = false; }
+            return new Promise(function (resolve, reject) {
+                if (scene) {
+                    _this._scene = scene;
+                }
+                else {
+                    return reject("A particle system need a scene.");
+                }
+                if (gpu && !BABYLON.GPUParticleSystem.IsSupported) {
+                    return reject("Particle system with GPU is not supported.");
+                }
+                _this._emitter = emitter;
+                BABYLON.Tools.LoadFile(_this._baseAssetsUrl + "/systems/" + type + ".json", function (data, response) {
+                    var newData = JSON.parse(data.toString());
+                    return resolve(_this._createSystem(newData));
+                }, undefined, undefined, undefined, function (req, exception) {
+                    return reject("An error occured while the creation of your particle system. Check if your type '" + type + "' exists.");
+                });
+            });
+        };
+        ParticleHelper._createSystem = function (data) {
+            // Create a particle system
+            var system = new BABYLON.ParticleSystem(data.type, data.capacity, this._scene);
+            // Texture of each particle
+            system.particleTexture = new BABYLON.Texture(this._baseAssetsUrl + "/textures/" + data.textureFile, this._scene);
+            // Where the particles come from
+            system.emitter = this._emitter; // the starting object, the emitter
+            // Colors of all particles
+            system.color1 = new BABYLON.Color4(data.color1.r, data.color1.g, data.color1.b, data.color1.a);
+            system.color2 = new BABYLON.Color4(data.color2.r, data.color2.g, data.color2.b, data.color2.a);
+            system.colorDead = new BABYLON.Color4(data.colorDead.r, data.colorDead.g, data.colorDead.b, data.colorDead.a);
+            // Size of each particle (random between...
+            system.minSize = data.minSize;
+            system.maxSize = data.maxSize;
+            // Life time of each particle (random between...
+            system.minLifeTime = data.minLifeTime;
+            system.maxLifeTime = data.maxLifeTime;
+            // Emission rate
+            system.emitRate = data.emitRate;
+            // Blend mode : BLENDMODE_ONEONE, or BLENDMODE_STANDARD
+            system.blendMode = data.blendMode;
+            // Set the gravity of all particles
+            system.gravity = new BABYLON.Vector3(data.gravity.x, data.gravity.y, data.gravity.z);
+            // Angular speed, in radians
+            system.minAngularSpeed = data.minAngularSpeed;
+            system.maxAngularSpeed = data.maxAngularSpeed;
+            // Speed
+            system.minEmitPower = data.minEmitPower;
+            system.maxEmitPower = data.maxEmitPower;
+            system.updateSpeed = data.updateSpeed;
+            switch (data.emitterType) {
+                case "box":
+                    if (!data.direction1 || !data.direction2) {
+                        throw new Error("Directions are missing in this particle system.");
+                    }
+                    if (!data.minEmitBox || !data.maxEmitBox) {
+                        throw new Error("EmitBox is missing in this particle system.");
+                    }
+                    system.createBoxEmitter(new BABYLON.Vector3(data.direction1.x, data.direction1.y, data.direction1.z), new BABYLON.Vector3(data.direction2.x, data.direction2.y, data.direction2.z), new BABYLON.Vector3(data.minEmitBox.x, data.minEmitBox.y, data.minEmitBox.z), new BABYLON.Vector3(data.maxEmitBox.x, data.maxEmitBox.y, data.maxEmitBox.z));
+                    break;
+                case "sphere":
+                    system.createSphereEmitter(data.radius);
+                    break;
+                case "directed_sphere":
+                    if (!data.direction1 || !data.direction2) {
+                        throw new Error("Directions are missing in this particle system.");
+                    }
+                    system.createDirectedSphereEmitter(data.radius, new BABYLON.Vector3(data.direction1.x, data.direction1.y, data.direction1.z), new BABYLON.Vector3(data.direction2.x, data.direction2.y, data.direction2.z));
+                    break;
+                case "cone":
+                    system.createConeEmitter(data.radius, data.angle);
+                    break;
+                default:
+                    break;
+            }
+            return system;
+        };
+        /**
+         * Base Assets URL.
+         */
+        ParticleHelper._baseAssetsUrl = "https://assets.babylonjs.com/particles";
+        return ParticleHelper;
+    }());
+    BABYLON.ParticleHelper = ParticleHelper;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.particleHelper.js.map
+
 
 var BABYLON;
 (function (BABYLON) {

File diff suppressed because it is too large
+ 35 - 35
dist/preview release/babylon.worker.js


File diff suppressed because it is too large
+ 231 - 26
dist/preview release/es6.js


File diff suppressed because it is too large
+ 3 - 3
dist/preview release/inspector/babylon.inspector.bundle.js


+ 3 - 0
dist/preview release/inspector/babylon.inspector.d.ts

@@ -1011,8 +1011,11 @@ declare module INSPECTOR {
         private _engine;
         private _glInfo;
         private _updateLoopHandler;
+        private _refreshRateCounter;
+        private refreshRate;
         private _sceneInstrumentation;
         private _engineInstrumentation;
+        private _inputElement;
         private _connectToInstrumentation();
         constructor(tabbar: TabBar, insp: Inspector);
         private _createStatLabel(content, parent);

+ 25 - 4
dist/preview release/inspector/babylon.inspector.js

@@ -3723,6 +3723,8 @@ var INSPECTOR;
             title.appendChild(versionSpan);
             title.appendChild(fpsSpan);
             _this._updateLoopHandler = _this._update.bind(_this);
+            _this._refreshRateCounter = 0;
+            _this.refreshRate = 4;
             // Count block
             title = INSPECTOR.Helpers.CreateDiv('stat-title2', _this._panel);
             title.textContent = "Count";
@@ -3797,8 +3799,16 @@ var INSPECTOR;
             title = INSPECTOR.Helpers.CreateDiv('stat-title2', _this._panel);
             title.textContent = "Duration";
             {
-                _this._createStatLabel("Meshes selection", _this._panel);
+                _this._createStatLabel("Refresh rate (refresh by second)", _this._panel);
                 var elemValue = INSPECTOR.Helpers.CreateDiv('stat-value', _this._panel);
+                _this._inputElement = INSPECTOR.Inspector.DOCUMENT.createElement('input');
+                _this._inputElement.value = _this.refreshRate;
+                elemValue.appendChild(_this._inputElement);
+                _this._inputElement.addEventListener('keyup', function (evt) {
+                    _this.refreshRate = _this._inputElement.value;
+                });
+                _this._createStatLabel("Meshes selection", _this._panel);
+                elemValue = INSPECTOR.Helpers.CreateDiv('stat-value', _this._panel);
                 _this._updatableProperties.push({
                     elem: elemValue,
                     updateFct: function () { return BABYLON.Tools.Format(_this._sceneInstrumentation.activeMeshesEvaluationTimeCounter.current); }
@@ -4003,9 +4013,20 @@ var INSPECTOR;
         };
         /** Update each properties of the stats panel */
         StatsTab.prototype._update = function () {
-            for (var _i = 0, _a = this._updatableProperties; _i < _a.length; _i++) {
-                var prop = _a[_i];
-                prop.elem.textContent = prop.updateFct();
+            if (this._refreshRateCounter > 1) {
+                this._refreshRateCounter--;
+            }
+            else {
+                for (var _i = 0, _a = this._updatableProperties; _i < _a.length; _i++) {
+                    var prop = _a[_i];
+                    prop.elem.textContent = prop.updateFct();
+                }
+                if (this._inspector.scene.getEngine().getFps() / this.refreshRate == Infinity) {
+                    this._refreshRateCounter = 1;
+                }
+                else {
+                    this._refreshRateCounter = this._inspector.scene.getEngine().getFps() / this.refreshRate;
+                }
             }
         };
         StatsTab.prototype.dispose = function () {

File diff suppressed because it is too large
+ 2 - 2
dist/preview release/inspector/babylon.inspector.min.js


File diff suppressed because it is too large
+ 57 - 57
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 365 - 119
dist/preview release/viewer/babylon.viewer.max.js


+ 6 - 2
dist/preview release/what's new.md

@@ -6,9 +6,11 @@
 
 ## Updates
 
+- All NPM packages have `latest`and `preview` streams [#3055](https://github.com/BabylonJS/Babylon.js/issues/3055) ([RaananW](https://github.com/RaananW))
+
 ### Core Engine
 
-- Added new `Animatable.waitAsync` function to use Promises with animations. Demo [Here](https://www.babylonjs-playground.com/#HZBCXR) ([Deltakosh](https://github.com/deltakosh)) 
+- Added new `Animatable.waitAsync` function to use Promises with animations. Demo [Here](https://www.babylonjs-playground.com/#HZBCXR) ([Deltakosh](https://github.com/deltakosh))
 - Added the choice of [forming a closed loop](http://doc.babylonjs.com/how_to/how_to_use_curve3#catmull-rom-spline) to the catamull-rom-spline curve3 ([johnk](https://github.com/babylonjsguide))
 - Added support for specifying the center of rotation to textures ([bghgary](http://www.github.com/bghgary))
 - Added webVR support for Oculus Go ([TrevorDev](https://github.com/TrevorDev))
@@ -26,6 +28,7 @@
 - No fullscreen button on small devices ([RaananW](https://github.com/RaananW))
 - Nav-Bar is now disaplayed on fullscreen per default ([RaananW](https://github.com/RaananW))
 - Viewer configuration supports deprecated values using the new configurationCompatibility processor  ([RaananW](https://github.com/RaananW))
+- Shadows will only render while models are entering the scene or animating ([RaananW](https://github.com/RaananW))
 
 ## Bug fixes
 
@@ -34,7 +37,7 @@
 - Fixed ```shadowEnabled``` property on lights. Shadows are not visble anymore when disabled ([sebavan](http://www.github.com/sebavan))
 - Physics `unregisterOnPhysicsCollide` didn't remove callback correctly [#4291](https://github.com/BabylonJS/Babylon.js/issues/4291) ([RaananW](https://github.com/RaananW))
 - Added missing getter and setter for global exposure in ColorCurves ([RaananW](https://github.com/RaananW))
-- Fixed an issue with view matrix when `ArcRotateCamera` was used with collisions ([Deltakosh](https://github.com/deltakosh)) 
+- Fixed an issue with view matrix when `ArcRotateCamera` was used with collisions ([Deltakosh](https://github.com/deltakosh))
 
 ### Viewer
 
@@ -42,5 +45,6 @@
 - Fix Animation Slider Interaction on Mozilla/Firefox ([sebavan](http://www.github.com/sebavan))
 - Fix Animation Slider Clickable area size Cross Plat ([sebavan](http://www.github.com/sebavan))
 - Ground material didn't take the default main color is no material definition was provided ([RaananW](https://github.com/RaananW))
+- Model configuration was not extended correctly if loaded more than one model ([RaananW](https://github.com/RaananW))
 
 ## Breaking changes

+ 29 - 3
inspector/src/tabs/StatsTab.ts

@@ -15,10 +15,14 @@ module INSPECTOR {
         private _glInfo: any;
 
         private _updateLoopHandler: any;
+        private _refreshRateCounter: any;
+        private refreshRate: any;
 
         private _sceneInstrumentation: BABYLON.Nullable<BABYLON.SceneInstrumentation>;
         private _engineInstrumentation: BABYLON.Nullable<BABYLON.EngineInstrumentation>;
 
+        private _inputElement: HTMLInputElement;
+
         private _connectToInstrumentation() {
             if (this._sceneInstrumentation) {
                 return;
@@ -67,6 +71,8 @@ module INSPECTOR {
             title.appendChild(fpsSpan);
 
             this._updateLoopHandler = this._update.bind(this);
+            this._refreshRateCounter = 0;
+            this.refreshRate = 4;
 
             // Count block
             title = Helpers.CreateDiv('stat-title2', this._panel);
@@ -153,8 +159,16 @@ module INSPECTOR {
             title = Helpers.CreateDiv('stat-title2', this._panel);
             title.textContent = "Duration";
             {
-                this._createStatLabel("Meshes selection", this._panel);
+                this._createStatLabel("Refresh rate (refresh by second)", this._panel);
                 let elemValue = Helpers.CreateDiv('stat-value', this._panel);
+                this._inputElement = Inspector.DOCUMENT.createElement('input');
+                this._inputElement.value = this.refreshRate;
+                elemValue.appendChild(this._inputElement);
+                this._inputElement.addEventListener('keyup', (evt : KeyboardEvent)=> {
+                this.refreshRate = this._inputElement.value;
+                })
+                this._createStatLabel("Meshes selection", this._panel);
+                elemValue = Helpers.CreateDiv('stat-value', this._panel);
                 this._updatableProperties.push({
                     elem: elemValue,
                     updateFct: () => { return BABYLON.Tools.Format(this._sceneInstrumentation!.activeMeshesEvaluationTimeCounter.current) }
@@ -345,9 +359,21 @@ module INSPECTOR {
 
         /** Update each properties of the stats panel */
         private _update() {
-            for (let prop of this._updatableProperties) {
-                prop.elem.textContent = prop.updateFct();
+            
+            if(this._refreshRateCounter > 1){
+                this._refreshRateCounter--;
+            }else{
+                for (let prop of this._updatableProperties) {
+                    prop.elem.textContent = prop.updateFct();
+                }
+                if(this._inspector.scene.getEngine().getFps()/this.refreshRate == Infinity){
+                    this._refreshRateCounter = 1;
+                }else{
+                    this._refreshRateCounter = this._inspector.scene.getEngine().getFps()/this.refreshRate;
+                }
+                
             }
+            
         }
 
         public dispose() {

+ 1 - 1
readme.md

@@ -3,7 +3,7 @@ Babylon.js
 
 Getting started? Play directly with the Babylon.js API via our [playground](http://www.babylonjs.com/playground). It contains also lot of simple samples to learn how to use it.
 
-[![Build Status](https://travis-ci.org/BabylonJS/Babylon.js.svg)](https://travis-ci.org/BabylonJS/Babylon.js) 
+[![Build Status](https://travis-ci.com/BabylonJS/Babylon.js.svg)](https://travis-ci.com/BabylonJS/Babylon.js) 
 
 **Any questions?** Here is our official [forum](http://www.html5gamedevs.com/forum/16-babylonjs/) on www.html5gamedevs.com.
 

+ 1 - 1
src/Animations/babylon.animation.ts

@@ -399,7 +399,7 @@
         }
 
         /**
-		 * Transition property of the Camera to the target Value
+		 * Transition property of an host to the target Value
 		 * @param property The property to transition
 		 * @param targetValue The target Value of the property
          * @param host The object where the property to animate belongs

+ 2 - 1
src/Engine/babylon.engine.ts

@@ -4864,6 +4864,7 @@
             gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(fullOptions.type, fullOptions.format), width, height, 0, this._getInternalFormat(fullOptions.format), this._getWebGLTextureType(fullOptions.type), null);
 
             // Create the framebuffer
+            var currentFrameBuffer = this._currentFramebuffer;
             var framebuffer = gl.createFramebuffer();
             this.bindUnboundFramebuffer(framebuffer);
             gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture._webGLTexture, 0);
@@ -4877,7 +4878,7 @@
             // Unbind
             this._bindTextureDirectly(gl.TEXTURE_2D, null);
             gl.bindRenderbuffer(gl.RENDERBUFFER, null);
-            this.bindUnboundFramebuffer(null);
+            this.bindUnboundFramebuffer(currentFrameBuffer);
 
             texture._framebuffer = framebuffer;
             texture.baseWidth = width;