Selaa lähdekoodia

Merge remote-tracking branch 'BabylonJS/master' into modules

Raanan Weber 7 vuotta sitten
vanhempi
commit
880daf5ca7
28 muutettua tiedostoa jossa 14923 lisäystä ja 14691 poistoa
  1. 4754 4749
      Playground/babylon.d.txt
  2. 2 0
      assets/meshes/controllers/_redirects
  3. 3970 3965
      dist/preview release/babylon.d.ts
  4. 44 44
      dist/preview release/babylon.js
  5. 43 11
      dist/preview release/babylon.max.js
  6. 44 44
      dist/preview release/babylon.worker.js
  7. 5704 5569
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  8. 48 48
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  9. 96 45
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  10. 1 3
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  11. 21 24
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  12. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  13. 1 3
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  14. 21 24
      dist/preview release/loaders/babylon.glTFFileLoader.js
  15. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  16. 21 24
      dist/preview release/loaders/babylonjs.loaders.js
  17. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  18. 1 3
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  19. 44 44
      dist/preview release/viewer/babylon.viewer.js
  20. 20 31
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  21. 3 3
      src/Gamepad/Controllers/babylon.oculusTouchController.ts
  22. 2 2
      src/Gamepad/Controllers/babylon.viveController.ts
  23. 37 37
      src/Gamepad/Controllers/babylon.windowsMotionController.ts
  24. 14 8
      src/Helpers/babylon.environmentHelper.ts
  25. 4 0
      src/Loading/babylon.sceneLoader.ts
  26. 17 1
      src/Particles/babylon.particleSystem.ts
  27. 2 0
      src/PostProcess/RenderPipeline/Pipelines/babylon.standardRenderingPipeline.ts
  28. 1 1
      src/Rendering/babylon.geometryBufferRenderer.ts

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 4754 - 4749
Playground/babylon.d.txt


+ 2 - 0
assets/meshes/controllers/_redirects

@@ -0,0 +1,2 @@
+# Redirect microsoft controllers if ID was not found on the server
+/microsoft/*/:controller.glb   /microsoft/default/:controller.glb   200

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3970 - 3965
dist/preview release/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 44 - 44
dist/preview release/babylon.js


+ 43 - 11
dist/preview release/babylon.max.js

@@ -5808,6 +5808,22 @@ var BABYLON;
         return LoadFileError;
     }(Error));
     BABYLON.LoadFileError = LoadFileError;
+    var RetryStrategy = /** @class */ (function () {
+        function RetryStrategy() {
+        }
+        RetryStrategy.ExponentialBackoff = function (maxRetries, baseInterval) {
+            if (maxRetries === void 0) { maxRetries = 3; }
+            if (baseInterval === void 0) { baseInterval = 500; }
+            return function (url, request, retryIndex) {
+                if (request.status !== 0 || retryIndex >= maxRetries || url.indexOf("file:") !== -1) {
+                    return -1;
+                }
+                return Math.pow(2, retryIndex) * baseInterval;
+            };
+        };
+        return RetryStrategy;
+    }());
+    BABYLON.RetryStrategy = RetryStrategy;
     // Screenshots
     var screenshotCanvas;
     var cloneValue = function (source, destinationObject) {
@@ -6198,11 +6214,13 @@ var BABYLON;
             }
             return img;
         };
-        Tools.LoadFile = function (url, callback, progressCallBack, database, useArrayBuffer, onError) {
+        Tools.LoadFile = function (url, callback, progressCallBack, database, useArrayBuffer, onError, onRetry, retryStrategy) {
+            if (retryStrategy === void 0) { retryStrategy = null; }
             url = Tools.CleanUrl(url);
             url = Tools.PreprocessUrl(url);
             var request = null;
-            var noIndexedDB = function () {
+            var noIndexedDB = function (retryIndex) {
+                var oldRequest = request;
                 request = new XMLHttpRequest();
                 var loadUrl = Tools.BaseUrl + url;
                 request.open('GET', loadUrl, true);
@@ -6219,19 +6237,29 @@ var BABYLON;
                         req.onreadystatechange = function () { }; //some browsers have issues where onreadystatechange can be called multiple times with the same value
                         if (req.status >= 200 && req.status < 300 || (!Tools.IsWindowObjectExist() && (req.status === 0))) {
                             callback(!useArrayBuffer ? req.responseText : req.response, req.responseURL);
+                            return;
                         }
-                        else {
-                            var e = new LoadFileError("Error status: " + req.status + " - Unable to load " + loadUrl, req);
-                            if (onError) {
-                                onError(req, e);
-                            }
-                            else {
-                                throw e;
+                        retryStrategy = retryStrategy || Tools.DefaultRetryStrategy;
+                        if (retryStrategy) {
+                            var waitTime = retryStrategy(loadUrl, req, retryIndex || 0);
+                            if (waitTime !== -1) {
+                                setTimeout(function () { return noIndexedDB((retryIndex || 0) + 1); }, waitTime);
+                                return;
                             }
                         }
+                        var e = new Error("Error status: " + req.status + " - Unable to load " + loadUrl);
+                        if (onError) {
+                            onError(req, e);
+                        }
+                        else {
+                            throw e;
+                        }
                     }
                 };
-                request.send(null);
+                request.send();
+                if (oldRequest && onRetry) {
+                    onRetry(oldRequest, request);
+                }
             };
             var loadFromIndexedDB = function () {
                 if (database) {
@@ -6962,6 +6990,7 @@ var BABYLON;
             return hash;
         };
         Tools.BaseUrl = "";
+        Tools.DefaultRetryStrategy = RetryStrategy.ExponentialBackoff();
         /**
          * Default behaviour for cors in the application.
          * It can be a string if the expected behavior is identical in the entire app.
@@ -53736,6 +53765,9 @@ var BABYLON;
         SceneLoader.GetPluginForExtension = function (extension) {
             return SceneLoader._getPluginForExtension(extension).plugin;
         };
+        SceneLoader.IsPluginForExtensionAvailable = function (extension) {
+            return !!SceneLoader._registeredPlugins[extension];
+        };
         SceneLoader.RegisterPlugin = function (plugin) {
             if (typeof plugin.extensions === "string") {
                 var extension = plugin.extensions;
@@ -57982,7 +58014,7 @@ var BABYLON;
             var path;
             var filename;
             // Checking if GLB loader is present
-            if (BABYLON.SceneLoader.GetPluginForExtension("glb")) {
+            if (BABYLON.SceneLoader.IsPluginForExtensionAvailable("glb")) {
                 // Determine the device specific folder based on the ID suffix
                 var device = 'default';
                 if (this.id && !forceDefault) {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 44 - 44
dist/preview release/babylon.worker.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 5704 - 5569
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 48 - 48
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 96 - 45
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -5808,6 +5808,22 @@ var BABYLON;
         return LoadFileError;
     }(Error));
     BABYLON.LoadFileError = LoadFileError;
+    var RetryStrategy = /** @class */ (function () {
+        function RetryStrategy() {
+        }
+        RetryStrategy.ExponentialBackoff = function (maxRetries, baseInterval) {
+            if (maxRetries === void 0) { maxRetries = 3; }
+            if (baseInterval === void 0) { baseInterval = 500; }
+            return function (url, request, retryIndex) {
+                if (request.status !== 0 || retryIndex >= maxRetries || url.indexOf("file:") !== -1) {
+                    return -1;
+                }
+                return Math.pow(2, retryIndex) * baseInterval;
+            };
+        };
+        return RetryStrategy;
+    }());
+    BABYLON.RetryStrategy = RetryStrategy;
     // Screenshots
     var screenshotCanvas;
     var cloneValue = function (source, destinationObject) {
@@ -6198,11 +6214,13 @@ var BABYLON;
             }
             return img;
         };
-        Tools.LoadFile = function (url, callback, progressCallBack, database, useArrayBuffer, onError) {
+        Tools.LoadFile = function (url, callback, progressCallBack, database, useArrayBuffer, onError, onRetry, retryStrategy) {
+            if (retryStrategy === void 0) { retryStrategy = null; }
             url = Tools.CleanUrl(url);
             url = Tools.PreprocessUrl(url);
             var request = null;
-            var noIndexedDB = function () {
+            var noIndexedDB = function (retryIndex) {
+                var oldRequest = request;
                 request = new XMLHttpRequest();
                 var loadUrl = Tools.BaseUrl + url;
                 request.open('GET', loadUrl, true);
@@ -6219,19 +6237,29 @@ var BABYLON;
                         req.onreadystatechange = function () { }; //some browsers have issues where onreadystatechange can be called multiple times with the same value
                         if (req.status >= 200 && req.status < 300 || (!Tools.IsWindowObjectExist() && (req.status === 0))) {
                             callback(!useArrayBuffer ? req.responseText : req.response, req.responseURL);
+                            return;
                         }
-                        else {
-                            var e = new LoadFileError("Error status: " + req.status + " - Unable to load " + loadUrl, req);
-                            if (onError) {
-                                onError(req, e);
-                            }
-                            else {
-                                throw e;
+                        retryStrategy = retryStrategy || Tools.DefaultRetryStrategy;
+                        if (retryStrategy) {
+                            var waitTime = retryStrategy(loadUrl, req, retryIndex || 0);
+                            if (waitTime !== -1) {
+                                setTimeout(function () { return noIndexedDB((retryIndex || 0) + 1); }, waitTime);
+                                return;
                             }
                         }
+                        var e = new Error("Error status: " + req.status + " - Unable to load " + loadUrl);
+                        if (onError) {
+                            onError(req, e);
+                        }
+                        else {
+                            throw e;
+                        }
                     }
                 };
-                request.send(null);
+                request.send();
+                if (oldRequest && onRetry) {
+                    onRetry(oldRequest, request);
+                }
             };
             var loadFromIndexedDB = function () {
                 if (database) {
@@ -6962,6 +6990,7 @@ var BABYLON;
             return hash;
         };
         Tools.BaseUrl = "";
+        Tools.DefaultRetryStrategy = RetryStrategy.ExponentialBackoff();
         /**
          * Default behaviour for cors in the application.
          * It can be a string if the expected behavior is identical in the entire app.
@@ -45846,6 +45875,13 @@ var BABYLON;
             serializationObject.blendMode = this.blendMode;
             serializationObject.customShader = this.customShader;
             serializationObject.preventAutoStart = this.preventAutoStart;
+            serializationObject.startSpriteCellID = this.startSpriteCellID;
+            serializationObject.endSpriteCellID = this.endSpriteCellID;
+            serializationObject.spriteCellLoop = this.spriteCellLoop;
+            serializationObject.spriteCellChangeSpeed = this.spriteCellChangeSpeed;
+            serializationObject.spriteCellWidth = this.spriteCellWidth;
+            serializationObject.spriteCellHeight = this.spriteCellHeight;
+            serializationObject.isAnimationSheetEnabled = this._isAnimationSheetEnabled;
             return serializationObject;
         };
         ParticleSystem.Parse = function (parsedParticleSystem, scene, rootUrl) {
@@ -45857,7 +45893,7 @@ var BABYLON;
                 var defines = (program.shaderOptions.defines.length > 0) ? program.shaderOptions.defines.join("\n") : "";
                 custom = scene.getEngine().createEffectForParticles(program.shaderPath.fragmentElement, program.shaderOptions.uniforms, program.shaderOptions.samplers, defines);
             }
-            var particleSystem = new ParticleSystem(name, parsedParticleSystem.capacity, scene, custom);
+            var particleSystem = new ParticleSystem(name, parsedParticleSystem.capacity, scene, custom, parsedParticleSystem.isAnimationSheetEnabled);
             particleSystem.customShader = program;
             if (parsedParticleSystem.id) {
                 particleSystem.id = parsedParticleSystem.id;
@@ -45910,6 +45946,12 @@ var BABYLON;
             particleSystem.targetStopDuration = parsedParticleSystem.targetStopDuration;
             particleSystem.textureMask = BABYLON.Color4.FromArray(parsedParticleSystem.textureMask);
             particleSystem.blendMode = parsedParticleSystem.blendMode;
+            particleSystem.startSpriteCellID = parsedParticleSystem.startSpriteCellID;
+            particleSystem.endSpriteCellID = parsedParticleSystem.endSpriteCellID;
+            particleSystem.spriteCellLoop = parsedParticleSystem.spriteCellLoop;
+            particleSystem.spriteCellChangeSpeed = parsedParticleSystem.spriteCellChangeSpeed;
+            particleSystem.spriteCellWidth = parsedParticleSystem.spriteCellWidth;
+            particleSystem.spriteCellHeight = parsedParticleSystem.spriteCellHeight;
             if (!particleSystem.preventAutoStart) {
                 particleSystem.start();
             }
@@ -53582,6 +53624,9 @@ var BABYLON;
         SceneLoader.GetPluginForExtension = function (extension) {
             return SceneLoader._getPluginForExtension(extension).plugin;
         };
+        SceneLoader.IsPluginForExtensionAvailable = function (extension) {
+            return !!SceneLoader._registeredPlugins[extension];
+        };
         SceneLoader.RegisterPlugin = function (plugin) {
             if (typeof plugin.extensions === "string") {
                 var extension = plugin.extensions;
@@ -57828,7 +57873,7 @@ var BABYLON;
             var path;
             var filename;
             // Checking if GLB loader is present
-            if (BABYLON.SceneLoader.GetPluginForExtension("glb")) {
+            if (BABYLON.SceneLoader.IsPluginForExtensionAvailable("glb")) {
                 // Determine the device specific folder based on the ID suffix
                 var device = 'default';
                 if (this.id && !forceDefault) {
@@ -60381,6 +60426,9 @@ var BABYLON;
         ], StandardRenderingPipeline.prototype, "motionStrength", void 0);
         __decorate([
             BABYLON.serialize()
+        ], StandardRenderingPipeline.prototype, "_ratio", void 0);
+        __decorate([
+            BABYLON.serialize()
         ], StandardRenderingPipeline.prototype, "BloomEnabled", null);
         __decorate([
             BABYLON.serialize()
@@ -60885,7 +60933,7 @@ var BABYLON;
                     return;
                 }
                 // Culling
-                engine.setState(material.backFaceCulling);
+                engine.setState(material.backFaceCulling, 0, false, scene.useRightHandedSystem);
                 // Managing instances
                 var batch = mesh._getInstancesRenderList(subMesh._id);
                 if (batch.mustReturn) {
@@ -79675,9 +79723,11 @@ var BABYLON;
                 this._groundMaterial.dispose();
                 this._groundMaterial = null;
             }
-            if (this._options.groundTexture && !newOptions.groundTexture && this._groundTexture) {
-                this._groundTexture.dispose();
-                this._groundTexture = null;
+            if (this._groundTexture) {
+                if (this._options.groundTexture != newOptions.groundTexture) {
+                    this._groundTexture.dispose();
+                    this._groundTexture = null;
+                }
             }
             if (this._skybox && !newOptions.createSkybox) {
                 this._skybox.dispose();
@@ -79687,16 +79737,20 @@ var BABYLON;
                 this._skyboxMaterial.dispose();
                 this._skyboxMaterial = null;
             }
-            if (this._options.skyboxTexture && !newOptions.skyboxTexture && this._skyboxTexture) {
-                this._skyboxTexture.dispose();
-                this._skyboxTexture = null;
+            if (this._skyboxTexture) {
+                if (this._options.skyboxTexture != newOptions.skyboxTexture) {
+                    this._skyboxTexture.dispose();
+                    this._skyboxTexture = null;
+                }
             }
             if (this._groundMirror && !newOptions.enableGroundMirror) {
                 this._groundMirror.dispose();
                 this._groundMirror = null;
             }
-            if (this._options.environmentTexture && !newOptions.environmentTexture && this._scene.environmentTexture) {
-                this._scene.environmentTexture.dispose();
+            if (this._scene.environmentTexture) {
+                if (this._options.environmentTexture != newOptions.environmentTexture) {
+                    this._scene.environmentTexture.dispose();
+                }
             }
             this._options = newOptions;
             this._setupBackground();
@@ -82703,14 +82757,6 @@ var BABYLON;
                 this._loaderPendingCount = 0;
                 this._loaderTrackers = new Array();
                 this._parent = parent;
-                if (!GLTFLoader._progressEventFactory) {
-                    if (typeof window["ProgressEvent"] === "function") {
-                        GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByConstructor;
-                    }
-                    else {
-                        GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByDocument;
-                    }
-                }
             }
             GLTFLoader.RegisterExtension = function (extension) {
                 if (GLTFLoader.Extensions[extension.name]) {
@@ -82721,14 +82767,6 @@ var BABYLON;
                 // Keep the order of registration so that extensions registered first are called first.
                 GLTF2.GLTFLoaderExtension._Extensions.push(extension);
             };
-            GLTFLoader._createProgressEventByConstructor = function (name, data) {
-                return new ProgressEvent(name, data);
-            };
-            GLTFLoader._createProgressEventByDocument = function (name, data) {
-                var event = document.createEvent("ProgressEvent");
-                event.initProgressEvent(name, false, false, data.lengthComputable, data.loaded, data.total);
-                return event;
-            };
             GLTFLoader.prototype.dispose = function () {
                 if (this._disposed) {
                     return;
@@ -82781,21 +82819,19 @@ var BABYLON;
                 if (!this._progressCallback) {
                     return;
                 }
+                var lengthComputable = true;
                 var loaded = 0;
                 var total = 0;
                 for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
                     var request = _a[_i];
-                    if (!request._loaded || !request._total) {
+                    if (request._lengthComputable === undefined || request._loaded === undefined || request._total === undefined) {
                         return;
                     }
+                    lengthComputable = lengthComputable && request._lengthComputable;
                     loaded += request._loaded;
                     total += request._total;
                 }
-                this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
-                    lengthComputable: true,
-                    loaded: loaded,
-                    total: total
-                }));
+                this._progressCallback(GLTFLoader._createProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             };
             GLTFLoader.prototype._executeWhenRenderReady = function (func) {
                 if (this._renderReady) {
@@ -84083,6 +84119,7 @@ var BABYLON;
                 }, function (event) {
                     _this._tryCatchOnError(function () {
                         if (request && !_this._renderReady) {
+                            request._lengthComputable = event.lengthComputable;
                             request._loaded = event.loaded;
                             request._total = event.total;
                             _this._onProgress();
@@ -84092,10 +84129,10 @@ var BABYLON;
                     _this._tryCatchOnError(function () {
                         throw new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request);
                     });
+                }, function (oldRequest, newRequest) {
+                    _this._requests.splice(_this._requests.indexOf(oldRequest), 1, newRequest);
                 });
                 if (request) {
-                    request._loaded = null;
-                    request._total = null;
                     this._requests.push(request);
                 }
             };
@@ -84280,6 +84317,20 @@ var BABYLON;
                 }
             };
             GLTFLoader.Extensions = {};
+            // IE 11 Compatibility.
+            GLTFLoader._createProgressEvent = (typeof window["ProgressEvent"] === "function")
+                ? function (lengthComputable, loaded, total) {
+                    return new ProgressEvent("GLTFLoaderProgress", {
+                        lengthComputable: lengthComputable,
+                        loaded: loaded,
+                        total: total
+                    });
+                }
+                : function (lengthComputable, loaded, total) {
+                    var event = document.createEvent("ProgressEvent");
+                    event.initProgressEvent("GLTFLoaderProgress", false, false, lengthComputable, loaded, total);
+                    return event;
+                };
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;

+ 1 - 3
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -379,9 +379,7 @@ declare module BABYLON.GLTF2 {
             [name: string]: GLTFLoaderExtension;
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
-        private static _progressEventFactory;
-        private static _createProgressEventByConstructor(name, data);
-        private static _createProgressEventByDocument(name, data);
+        private static _createProgressEvent;
         constructor(parent: GLTFFileLoader);
         dispose(): void;
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress?: (event: ProgressEvent) => void, onError?: (message: string, exception?: any) => void): void;

+ 21 - 24
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -387,14 +387,6 @@ var BABYLON;
                 this._loaderPendingCount = 0;
                 this._loaderTrackers = new Array();
                 this._parent = parent;
-                if (!GLTFLoader._progressEventFactory) {
-                    if (typeof window["ProgressEvent"] === "function") {
-                        GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByConstructor;
-                    }
-                    else {
-                        GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByDocument;
-                    }
-                }
             }
             GLTFLoader.RegisterExtension = function (extension) {
                 if (GLTFLoader.Extensions[extension.name]) {
@@ -405,14 +397,6 @@ var BABYLON;
                 // Keep the order of registration so that extensions registered first are called first.
                 GLTF2.GLTFLoaderExtension._Extensions.push(extension);
             };
-            GLTFLoader._createProgressEventByConstructor = function (name, data) {
-                return new ProgressEvent(name, data);
-            };
-            GLTFLoader._createProgressEventByDocument = function (name, data) {
-                var event = document.createEvent("ProgressEvent");
-                event.initProgressEvent(name, false, false, data.lengthComputable, data.loaded, data.total);
-                return event;
-            };
             GLTFLoader.prototype.dispose = function () {
                 if (this._disposed) {
                     return;
@@ -465,21 +449,19 @@ var BABYLON;
                 if (!this._progressCallback) {
                     return;
                 }
+                var lengthComputable = true;
                 var loaded = 0;
                 var total = 0;
                 for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
                     var request = _a[_i];
-                    if (!request._loaded || !request._total) {
+                    if (request._lengthComputable === undefined || request._loaded === undefined || request._total === undefined) {
                         return;
                     }
+                    lengthComputable = lengthComputable && request._lengthComputable;
                     loaded += request._loaded;
                     total += request._total;
                 }
-                this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
-                    lengthComputable: true,
-                    loaded: loaded,
-                    total: total
-                }));
+                this._progressCallback(GLTFLoader._createProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             };
             GLTFLoader.prototype._executeWhenRenderReady = function (func) {
                 if (this._renderReady) {
@@ -1767,6 +1749,7 @@ var BABYLON;
                 }, function (event) {
                     _this._tryCatchOnError(function () {
                         if (request && !_this._renderReady) {
+                            request._lengthComputable = event.lengthComputable;
                             request._loaded = event.loaded;
                             request._total = event.total;
                             _this._onProgress();
@@ -1776,10 +1759,10 @@ var BABYLON;
                     _this._tryCatchOnError(function () {
                         throw new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request);
                     });
+                }, function (oldRequest, newRequest) {
+                    _this._requests.splice(_this._requests.indexOf(oldRequest), 1, newRequest);
                 });
                 if (request) {
-                    request._loaded = null;
-                    request._total = null;
                     this._requests.push(request);
                 }
             };
@@ -1964,6 +1947,20 @@ var BABYLON;
                 }
             };
             GLTFLoader.Extensions = {};
+            // IE 11 Compatibility.
+            GLTFLoader._createProgressEvent = (typeof window["ProgressEvent"] === "function")
+                ? function (lengthComputable, loaded, total) {
+                    return new ProgressEvent("GLTFLoaderProgress", {
+                        lengthComputable: lengthComputable,
+                        loaded: loaded,
+                        total: total
+                    });
+                }
+                : function (lengthComputable, loaded, total) {
+                    var event = document.createEvent("ProgressEvent");
+                    event.initProgressEvent("GLTFLoaderProgress", false, false, lengthComputable, loaded, total);
+                    return event;
+                };
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 1 - 3
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -926,9 +926,7 @@ declare module BABYLON.GLTF2 {
             [name: string]: GLTFLoaderExtension;
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
-        private static _progressEventFactory;
-        private static _createProgressEventByConstructor(name, data);
-        private static _createProgressEventByDocument(name, data);
+        private static _createProgressEvent;
         constructor(parent: GLTFFileLoader);
         dispose(): void;
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress?: (event: ProgressEvent) => void, onError?: (message: string, exception?: any) => void): void;

+ 21 - 24
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -2543,14 +2543,6 @@ var BABYLON;
                 this._loaderPendingCount = 0;
                 this._loaderTrackers = new Array();
                 this._parent = parent;
-                if (!GLTFLoader._progressEventFactory) {
-                    if (typeof window["ProgressEvent"] === "function") {
-                        GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByConstructor;
-                    }
-                    else {
-                        GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByDocument;
-                    }
-                }
             }
             GLTFLoader.RegisterExtension = function (extension) {
                 if (GLTFLoader.Extensions[extension.name]) {
@@ -2561,14 +2553,6 @@ var BABYLON;
                 // Keep the order of registration so that extensions registered first are called first.
                 GLTF2.GLTFLoaderExtension._Extensions.push(extension);
             };
-            GLTFLoader._createProgressEventByConstructor = function (name, data) {
-                return new ProgressEvent(name, data);
-            };
-            GLTFLoader._createProgressEventByDocument = function (name, data) {
-                var event = document.createEvent("ProgressEvent");
-                event.initProgressEvent(name, false, false, data.lengthComputable, data.loaded, data.total);
-                return event;
-            };
             GLTFLoader.prototype.dispose = function () {
                 if (this._disposed) {
                     return;
@@ -2621,21 +2605,19 @@ var BABYLON;
                 if (!this._progressCallback) {
                     return;
                 }
+                var lengthComputable = true;
                 var loaded = 0;
                 var total = 0;
                 for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
                     var request = _a[_i];
-                    if (!request._loaded || !request._total) {
+                    if (request._lengthComputable === undefined || request._loaded === undefined || request._total === undefined) {
                         return;
                     }
+                    lengthComputable = lengthComputable && request._lengthComputable;
                     loaded += request._loaded;
                     total += request._total;
                 }
-                this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
-                    lengthComputable: true,
-                    loaded: loaded,
-                    total: total
-                }));
+                this._progressCallback(GLTFLoader._createProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             };
             GLTFLoader.prototype._executeWhenRenderReady = function (func) {
                 if (this._renderReady) {
@@ -3923,6 +3905,7 @@ var BABYLON;
                 }, function (event) {
                     _this._tryCatchOnError(function () {
                         if (request && !_this._renderReady) {
+                            request._lengthComputable = event.lengthComputable;
                             request._loaded = event.loaded;
                             request._total = event.total;
                             _this._onProgress();
@@ -3932,10 +3915,10 @@ var BABYLON;
                     _this._tryCatchOnError(function () {
                         throw new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request);
                     });
+                }, function (oldRequest, newRequest) {
+                    _this._requests.splice(_this._requests.indexOf(oldRequest), 1, newRequest);
                 });
                 if (request) {
-                    request._loaded = null;
-                    request._total = null;
                     this._requests.push(request);
                 }
             };
@@ -4120,6 +4103,20 @@ var BABYLON;
                 }
             };
             GLTFLoader.Extensions = {};
+            // IE 11 Compatibility.
+            GLTFLoader._createProgressEvent = (typeof window["ProgressEvent"] === "function")
+                ? function (lengthComputable, loaded, total) {
+                    return new ProgressEvent("GLTFLoaderProgress", {
+                        lengthComputable: lengthComputable,
+                        loaded: loaded,
+                        total: total
+                    });
+                }
+                : function (lengthComputable, loaded, total) {
+                    var event = document.createEvent("ProgressEvent");
+                    event.initProgressEvent("GLTFLoaderProgress", false, false, lengthComputable, loaded, total);
+                    return event;
+                };
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 21 - 24
dist/preview release/loaders/babylonjs.loaders.js

@@ -3499,14 +3499,6 @@ var BABYLON;
                 this._loaderPendingCount = 0;
                 this._loaderTrackers = new Array();
                 this._parent = parent;
-                if (!GLTFLoader._progressEventFactory) {
-                    if (typeof window["ProgressEvent"] === "function") {
-                        GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByConstructor;
-                    }
-                    else {
-                        GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByDocument;
-                    }
-                }
             }
             GLTFLoader.RegisterExtension = function (extension) {
                 if (GLTFLoader.Extensions[extension.name]) {
@@ -3517,14 +3509,6 @@ var BABYLON;
                 // Keep the order of registration so that extensions registered first are called first.
                 GLTF2.GLTFLoaderExtension._Extensions.push(extension);
             };
-            GLTFLoader._createProgressEventByConstructor = function (name, data) {
-                return new ProgressEvent(name, data);
-            };
-            GLTFLoader._createProgressEventByDocument = function (name, data) {
-                var event = document.createEvent("ProgressEvent");
-                event.initProgressEvent(name, false, false, data.lengthComputable, data.loaded, data.total);
-                return event;
-            };
             GLTFLoader.prototype.dispose = function () {
                 if (this._disposed) {
                     return;
@@ -3577,21 +3561,19 @@ var BABYLON;
                 if (!this._progressCallback) {
                     return;
                 }
+                var lengthComputable = true;
                 var loaded = 0;
                 var total = 0;
                 for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
                     var request = _a[_i];
-                    if (!request._loaded || !request._total) {
+                    if (request._lengthComputable === undefined || request._loaded === undefined || request._total === undefined) {
                         return;
                     }
+                    lengthComputable = lengthComputable && request._lengthComputable;
                     loaded += request._loaded;
                     total += request._total;
                 }
-                this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
-                    lengthComputable: true,
-                    loaded: loaded,
-                    total: total
-                }));
+                this._progressCallback(GLTFLoader._createProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             };
             GLTFLoader.prototype._executeWhenRenderReady = function (func) {
                 if (this._renderReady) {
@@ -4879,6 +4861,7 @@ var BABYLON;
                 }, function (event) {
                     _this._tryCatchOnError(function () {
                         if (request && !_this._renderReady) {
+                            request._lengthComputable = event.lengthComputable;
                             request._loaded = event.loaded;
                             request._total = event.total;
                             _this._onProgress();
@@ -4888,10 +4871,10 @@ var BABYLON;
                     _this._tryCatchOnError(function () {
                         throw new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request);
                     });
+                }, function (oldRequest, newRequest) {
+                    _this._requests.splice(_this._requests.indexOf(oldRequest), 1, newRequest);
                 });
                 if (request) {
-                    request._loaded = null;
-                    request._total = null;
                     this._requests.push(request);
                 }
             };
@@ -5076,6 +5059,20 @@ var BABYLON;
                 }
             };
             GLTFLoader.Extensions = {};
+            // IE 11 Compatibility.
+            GLTFLoader._createProgressEvent = (typeof window["ProgressEvent"] === "function")
+                ? function (lengthComputable, loaded, total) {
+                    return new ProgressEvent("GLTFLoaderProgress", {
+                        lengthComputable: lengthComputable,
+                        loaded: loaded,
+                        total: total
+                    });
+                }
+                : function (lengthComputable, loaded, total) {
+                    var event = document.createEvent("ProgressEvent");
+                    event.initProgressEvent("GLTFLoaderProgress", false, false, lengthComputable, loaded, total);
+                    return event;
+                };
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


+ 1 - 3
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -1024,9 +1024,7 @@ declare module BABYLON.GLTF2 {
             [name: string]: GLTFLoaderExtension;
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
-        private static _progressEventFactory;
-        private static _createProgressEventByConstructor(name, data);
-        private static _createProgressEventByDocument(name, data);
+        private static _createProgressEvent;
         constructor(parent: GLTFFileLoader);
         dispose(): void;
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress?: (event: ProgressEvent) => void, onError?: (message: string, exception?: any) => void): void;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 44 - 44
dist/preview release/viewer/babylon.viewer.js


+ 20 - 31
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -34,16 +34,11 @@ module BABYLON.GLTF2 {
     }
 
     interface GLTFLoaderRequest extends XMLHttpRequest {
+        _lengthComputable?: boolean;
         _loaded?: number;
         _total?: number;
     }
 
-    interface IProgressEventData {
-        lengthComputable: boolean;
-        loaded: number;
-        total: number;
-    }
-
     export class GLTFLoader implements IGLTFLoader {
         public _gltf: IGLTF;
         public _babylonScene: Scene;
@@ -85,28 +80,23 @@ module BABYLON.GLTF2 {
         }
 
         // IE 11 Compatibility.
-        private static _progressEventFactory: (name: string, data: IProgressEventData) => ProgressEvent;
-
-        private static _createProgressEventByConstructor(name: string, data: IProgressEventData): ProgressEvent {
-            return new ProgressEvent(name, data);
-        }
-
-        private static _createProgressEventByDocument(name: string, data: IProgressEventData): ProgressEvent {
-            const event = document.createEvent("ProgressEvent");
-            event.initProgressEvent(name, false, false, data.lengthComputable, data.loaded, data.total);
-            return event;
-        }
+        private static _createProgressEvent: (lengthComputable: boolean, loaded: number, total: number) => ProgressEvent =
+            (typeof (<any>window)["ProgressEvent"] === "function")
+                ? (lengthComputable, loaded, total) => {
+                    return new ProgressEvent("GLTFLoaderProgress", {
+                        lengthComputable: lengthComputable,
+                        loaded: loaded,
+                        total: total
+                    });
+                }
+                : (lengthComputable, loaded, total) => {
+                    const event = document.createEvent("ProgressEvent");
+                    event.initProgressEvent("GLTFLoaderProgress", false, false, lengthComputable, loaded, total);
+                    return event;
+                };
 
         public constructor(parent: GLTFFileLoader) {
             this._parent = parent;
-            if (!GLTFLoader._progressEventFactory) {
-                if (typeof (<any>window)["ProgressEvent"] === "function") {
-                    GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByConstructor;
-                }
-                else {
-                    GLTFLoader._progressEventFactory = GLTFLoader._createProgressEventByDocument;
-                }
-            }
         }
 
         public dispose(): void {
@@ -167,22 +157,20 @@ module BABYLON.GLTF2 {
                 return;
             }
 
+            let lengthComputable = true;
             let loaded = 0;
             let total = 0;
             for (let request of this._requests) {
-                if (!request._loaded || !request._total) {
+                if (request._lengthComputable === undefined || request._loaded === undefined || request._total === undefined) {
                     return;
                 }
 
+                lengthComputable = lengthComputable && request._lengthComputable;
                 loaded += request._loaded;
                 total += request._total;
             }
 
-            this._progressCallback(GLTFLoader._progressEventFactory("GLTFLoaderProgress", {
-                lengthComputable: true,
-                loaded: loaded,
-                total: total
-            }));
+            this._progressCallback(GLTFLoader._createProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
         }
 
         public _executeWhenRenderReady(func: () => void): void {
@@ -1635,6 +1623,7 @@ module BABYLON.GLTF2 {
             }, event => {
                 this._tryCatchOnError(() => {
                     if (request && !this._renderReady) {
+                        request._lengthComputable = event.lengthComputable;
                         request._loaded = event.loaded;
                         request._total = event.total;
                         this._onProgress();

+ 3 - 3
src/Gamepad/Controllers/babylon.oculusTouchController.ts

@@ -1,9 +1,9 @@
 module BABYLON {
 
     export class OculusTouchController extends WebVRController {
-        private static readonly MODEL_BASE_URL:string = 'https://controllers.babylonjs.com/oculus/';
-        private static readonly MODEL_LEFT_FILENAME:string = 'left.babylon';
-        private static readonly MODEL_RIGHT_FILENAME:string = 'right.babylon';
+        public static MODEL_BASE_URL: string = 'https://controllers.babylonjs.com/oculus/';
+        public static MODEL_LEFT_FILENAME: string = 'left.babylon';
+        public static MODEL_RIGHT_FILENAME: string = 'right.babylon';
 
         public onSecondaryTriggerStateChangedObservable = new Observable<ExtendedGamepadButton>();
 

+ 2 - 2
src/Gamepad/Controllers/babylon.viveController.ts

@@ -1,8 +1,8 @@
 module BABYLON {
 
     export class ViveController extends WebVRController {
-        private static readonly MODEL_BASE_URL:string = 'https://controllers.babylonjs.com/vive/';
-        private static readonly MODEL_FILENAME:string = 'wand.babylon';
+        public static MODEL_BASE_URL: string = 'https://controllers.babylonjs.com/vive/';
+        public static MODEL_FILENAME: string = 'wand.babylon';
 
         constructor(vrGamepad: any) {
             super(vrGamepad);

+ 37 - 37
src/Gamepad/Controllers/babylon.windowsMotionController.ts

@@ -3,8 +3,8 @@ module BABYLON {
     class LoadedMeshInfo {
         public rootNode: AbstractMesh;
         public pointingPoseNode: AbstractMesh;
-        public buttonMeshes: { [id: string] : IButtonMeshInfo; } = {};
-        public axisMeshes: { [id: number] : IAxisMeshInfo; } = {};
+        public buttonMeshes: { [id: string]: IButtonMeshInfo; } = {};
+        public axisMeshes: { [id: number]: IAxisMeshInfo; } = {};
     }
 
     interface IMeshInfo {
@@ -23,18 +23,18 @@ module BABYLON {
     }
 
     export class WindowsMotionController extends WebVRController {
-        private static readonly MODEL_BASE_URL:string = 'https://controllers.babylonjs.com/microsoft/';
-        private static readonly MODEL_LEFT_FILENAME:string = 'left.glb';
-        private static readonly MODEL_RIGHT_FILENAME:string = 'right.glb';
+        public static MODEL_BASE_URL: string = 'https://controllers.babylonjs.com/microsoft/';
+        public static MODEL_LEFT_FILENAME: string = 'left.glb';
+        public static MODEL_RIGHT_FILENAME: string = 'right.glb';
 
-        public static readonly GAMEPAD_ID_PREFIX:string = 'Spatial Controller (Spatial Interaction Source) ';
+        public static readonly GAMEPAD_ID_PREFIX: string = 'Spatial Controller (Spatial Interaction Source) ';
         private static readonly GAMEPAD_ID_PATTERN = /([0-9a-zA-Z]+-[0-9a-zA-Z]+)$/;
 
         private _loadedMeshInfo: Nullable<LoadedMeshInfo>;
         private readonly _mapping = {
             // Semantic button names
             buttons: ['thumbstick', 'trigger', 'grip', 'menu', 'trackpad'],
-            
+
             // A mapping of the button name to glTF model node name
             // that should be transformed by button value.
             buttonMeshNames: {
@@ -74,7 +74,7 @@ module BABYLON {
             this.controllerType = PoseEnabledControllerType.WINDOWS;
             this._loadedMeshInfo = null;
         }
-        
+
         public get onTriggerButtonStateChangedObservable(): Observable<ExtendedGamepadButton> {
             return this.onTriggerStateChangedObservable;
         }
@@ -89,7 +89,7 @@ module BABYLON {
 
         public get onThumbstickButtonStateChangedObservable(): Observable<ExtendedGamepadButton> {
             return this.onPadStateChangedObservable;
-        }    
+        }
 
         public get onTouchpadButtonStateChangedObservable(): Observable<ExtendedGamepadButton> {
             return this.onTrackpadChangedObservable;
@@ -98,17 +98,17 @@ module BABYLON {
         public get onTouchpadValuesChangedObservable(): Observable<StickValues> {
             return this.onTrackpadValuesChangedObservable;
         }
-        
+
         /**
          * Called once per frame by the engine.
          */
         public update() {
             super.update();
-            
+
             // Only need to animate axes if there is a loaded mesh
             if (this._loadedMeshInfo) {
                 if (this.browserGamepad.axes) {
-                    if(this.browserGamepad.axes[2] != this.trackpad.x || this.browserGamepad.axes[3] != this.trackpad.y){
+                    if (this.browserGamepad.axes[2] != this.trackpad.x || this.browserGamepad.axes[3] != this.trackpad.y) {
                         this.trackpad.x = this.browserGamepad["axes"][2];
                         this.trackpad.y = this.browserGamepad["axes"][3];
                         this.onTrackpadValuesChangedObservable.notifyObservers(this.trackpad);
@@ -119,7 +119,7 @@ module BABYLON {
                 }
             }
         }
-        
+
         /**
          * Called once for each button that changed state since the last frame
          * @param buttonIdx Which button index changed
@@ -129,7 +129,7 @@ module BABYLON {
         protected handleButtonChange(buttonIdx: number, state: ExtendedGamepadButton, changes: GamepadButtonChanges) {
             let buttonName = this._mapping.buttons[buttonIdx];
             if (!buttonName) {
-                return; 
+                return;
             }
 
             // Only emit events for buttons that we know how to map from index to name
@@ -140,9 +140,9 @@ module BABYLON {
 
             this.lerpButtonTransform(buttonName, state.value);
         }
-        
+
         protected lerpButtonTransform(buttonName: string, buttonValue: number) {
-            
+
             // If there is no loaded mesh, there is nothing to transform.
             if (!this._loadedMeshInfo) {
                 return;
@@ -155,18 +155,18 @@ module BABYLON {
             }
 
             BABYLON.Quaternion.SlerpToRef(
-                meshInfo.unpressed.rotationQuaternion, 
-                meshInfo.pressed.rotationQuaternion, 
+                meshInfo.unpressed.rotationQuaternion,
+                meshInfo.pressed.rotationQuaternion,
                 buttonValue,
                 meshInfo.value.rotationQuaternion);
             BABYLON.Vector3.LerpToRef(
-                meshInfo.unpressed.position, 
+                meshInfo.unpressed.position,
                 meshInfo.pressed.position,
                 buttonValue,
                 meshInfo.value.position);
         }
-        
-        protected lerpAxisTransform(axis:number, axisValue: number) {
+
+        protected lerpAxisTransform(axis: number, axisValue: number) {
             if (!this._loadedMeshInfo) {
                 return;
             }
@@ -178,33 +178,33 @@ module BABYLON {
 
             if (!meshInfo.min.rotationQuaternion || !meshInfo.max.rotationQuaternion || !meshInfo.value.rotationQuaternion) {
                 return;
-            }            
+            }
 
             // Convert from gamepad value range (-1 to +1) to lerp range (0 to 1)
             let lerpValue = axisValue * 0.5 + 0.5;
             BABYLON.Quaternion.SlerpToRef(
-                meshInfo.min.rotationQuaternion, 
-                meshInfo.max.rotationQuaternion, 
+                meshInfo.min.rotationQuaternion,
+                meshInfo.max.rotationQuaternion,
                 lerpValue,
                 meshInfo.value.rotationQuaternion);
             BABYLON.Vector3.LerpToRef(
-                meshInfo.min.position, 
+                meshInfo.min.position,
                 meshInfo.max.position,
                 lerpValue,
                 meshInfo.value.position);
         }
-        
+
         /**
          * Implements abstract method on WebVRController class, loading controller meshes and calling this.attachToMesh if successful.
          * @param scene scene in which to add meshes
          * @param meshLoaded optional callback function that will be called if the mesh loads successfully.
          */
         public initControllerMesh(scene: Scene, meshLoaded?: (mesh: AbstractMesh) => void, forceDefault = false) {
-            let path: string;        
+            let path: string;
             let filename: string;
 
             // Checking if GLB loader is present
-            if (SceneLoader.GetPluginForExtension("glb")) {
+            if (SceneLoader.IsPluginForExtensionAvailable("glb")) {
                 // Determine the device specific folder based on the ID suffix
                 let device = 'default';
                 if (this.id && !forceDefault) {
@@ -259,21 +259,21 @@ module BABYLON {
          * @param meshes list of meshes that make up the controller model to process
          * @return structured view of the given meshes, with mapping of buttons and axes to meshes that can be transformed.
          */
-        private processModel(scene: Scene, meshes: AbstractMesh[]) : Nullable<LoadedMeshInfo> {
+        private processModel(scene: Scene, meshes: AbstractMesh[]): Nullable<LoadedMeshInfo> {
             let loadedMeshInfo = null;
 
             // Create a new mesh to contain the glTF hierarchy
             let parentMesh = new BABYLON.Mesh(this.id + " " + this.hand, scene);
 
             // Find the root node in the loaded glTF scene, and attach it as a child of 'parentMesh'
-            let childMesh : Nullable<AbstractMesh> = null;
+            let childMesh: Nullable<AbstractMesh> = null;
             for (let i = 0; i < meshes.length; i++) {
                 let mesh = meshes[i];
 
                 if (!mesh.parent) {
                     // Exclude controller meshes from picking results
                     mesh.isPickable = false;
-                    
+
                     // Handle root node, attach to the new parentMesh
                     childMesh = mesh;
                     break;
@@ -291,8 +291,8 @@ module BABYLON {
 
             return loadedMeshInfo;
         }
-        
-        private createMeshInfo(rootNode: AbstractMesh) : LoadedMeshInfo {
+
+        private createMeshInfo(rootNode: AbstractMesh): LoadedMeshInfo {
             let loadedMeshInfo = new LoadedMeshInfo();
             var i;
             loadedMeshInfo.rootNode = rootNode;
@@ -367,18 +367,18 @@ module BABYLON {
 
             // Pointing Ray
             loadedMeshInfo.pointingPoseNode = getChildByName(rootNode, this._mapping.pointingPoseMeshName);
-            if (!loadedMeshInfo.pointingPoseNode) {                
+            if (!loadedMeshInfo.pointingPoseNode) {
                 Tools.Warn('Missing pointing pose mesh with name: ' + this._mapping.pointingPoseMeshName);
             }
 
             return loadedMeshInfo;
-            
+
             // Look through all children recursively. This will return null if no mesh exists with the given name.
             function getChildByName(node: Node, name: string) {
                 return node.getChildMeshes(false, n => n.name === name)[0];
             }
             // Look through only immediate children. This will return null if no mesh exists with the given name.
-            function getImmediateChildByName (node: Node, name: string) : AbstractMesh {
+            function getImmediateChildByName(node: Node, name: string): AbstractMesh {
                 return node.getChildMeshes(true, n => n.name == name)[0];
             }
         }
@@ -394,7 +394,7 @@ module BABYLON {
             var forward = new BABYLON.Vector3(0, 0, -1);
             var forwardWorld = BABYLON.Vector3.TransformNormal(forward, m);
 
-            var direction = BABYLON.Vector3.Normalize(forwardWorld);            
+            var direction = BABYLON.Vector3.Normalize(forwardWorld);
 
             return new Ray(origin, direction, length);
         }

+ 14 - 8
src/Helpers/babylon.environmentHelper.ts

@@ -338,9 +338,11 @@ namespace BABYLON {
                 this._groundMaterial = null;
             }
 
-            if (this._options.groundTexture && !newOptions.groundTexture && this._groundTexture) {
-                this._groundTexture.dispose();
-                this._groundTexture = null;
+            if (this._groundTexture) {
+                if (this._options.groundTexture != newOptions.groundTexture) {
+                    this._groundTexture.dispose();
+                    this._groundTexture = null;
+                }
             }
 
             if (this._skybox && !newOptions.createSkybox) {
@@ -353,9 +355,11 @@ namespace BABYLON {
                 this._skyboxMaterial = null;
             }
 
-            if (this._options.skyboxTexture && !newOptions.skyboxTexture && this._skyboxTexture) {
-                this._skyboxTexture.dispose();
-                this._skyboxTexture = null;
+            if (this._skyboxTexture) {
+                if (this._options.skyboxTexture != newOptions.skyboxTexture) {
+                    this._skyboxTexture.dispose();
+                    this._skyboxTexture = null;
+                }
             }
 
             if (this._groundMirror && !newOptions.enableGroundMirror) {
@@ -363,8 +367,10 @@ namespace BABYLON {
                 this._groundMirror = null;
             }
 
-            if (this._options.environmentTexture && !newOptions.environmentTexture && this._scene.environmentTexture) {
-                this._scene.environmentTexture.dispose();
+            if (this._scene.environmentTexture) {
+                if (this._options.environmentTexture != newOptions.environmentTexture) {
+                    this._scene.environmentTexture.dispose();
+                }
             }
 
             this._options = newOptions;

+ 4 - 0
src/Loading/babylon.sceneLoader.ts

@@ -216,6 +216,10 @@
             return SceneLoader._getPluginForExtension(extension).plugin;
         }
 
+        public static IsPluginForExtensionAvailable(extension: string): boolean {
+            return !!SceneLoader._registeredPlugins[extension];
+        }
+
         public static RegisterPlugin(plugin: ISceneLoaderPlugin | ISceneLoaderPluginAsync): void {
             if (typeof plugin.extensions === "string") {
                 var extension = <string>plugin.extensions;

+ 17 - 1
src/Particles/babylon.particleSystem.ts

@@ -672,6 +672,15 @@
             serializationObject.customShader = this.customShader;
             serializationObject.preventAutoStart = this.preventAutoStart;
 
+            serializationObject.startSpriteCellID = this.startSpriteCellID;
+            serializationObject.endSpriteCellID = this.endSpriteCellID;
+            serializationObject.spriteCellLoop = this.spriteCellLoop;
+            serializationObject.spriteCellChangeSpeed = this.spriteCellChangeSpeed;
+            serializationObject.spriteCellWidth = this.spriteCellWidth;
+            serializationObject.spriteCellHeight = this.spriteCellHeight;
+
+            serializationObject.isAnimationSheetEnabled = this._isAnimationSheetEnabled;
+
             return serializationObject;
         }
 
@@ -684,7 +693,7 @@
                 var defines: string = (program.shaderOptions.defines.length > 0) ? program.shaderOptions.defines.join("\n") : "";
                 custom = scene.getEngine().createEffectForParticles(program.shaderPath.fragmentElement, program.shaderOptions.uniforms, program.shaderOptions.samplers, defines);
             }
-            var particleSystem = new ParticleSystem(name, parsedParticleSystem.capacity, scene, custom);
+            var particleSystem = new ParticleSystem(name, parsedParticleSystem.capacity, scene, custom, parsedParticleSystem.isAnimationSheetEnabled);
             particleSystem.customShader = program;
 
             if (parsedParticleSystem.id) {
@@ -744,6 +753,13 @@
             particleSystem.textureMask = Color4.FromArray(parsedParticleSystem.textureMask);
             particleSystem.blendMode = parsedParticleSystem.blendMode;
 
+            particleSystem.startSpriteCellID = parsedParticleSystem.startSpriteCellID;
+            particleSystem.endSpriteCellID = parsedParticleSystem.endSpriteCellID;
+            particleSystem.spriteCellLoop = parsedParticleSystem.spriteCellLoop;
+            particleSystem.spriteCellChangeSpeed = parsedParticleSystem.spriteCellChangeSpeed;
+            particleSystem.spriteCellWidth = parsedParticleSystem.spriteCellWidth;
+            particleSystem.spriteCellHeight = parsedParticleSystem.spriteCellHeight;
+
             if (!particleSystem.preventAutoStart) {
                 particleSystem.start();
             }

+ 2 - 0
src/PostProcess/RenderPipeline/Pipelines/babylon.standardRenderingPipeline.ts

@@ -99,6 +99,8 @@
         private _hdrCurrentLuminance: number = 1.0;
 
         private _floatTextureType: number;
+
+        @serialize()
         private _ratio: number;
 
         // Getters and setters

+ 1 - 1
src/Rendering/babylon.geometryBufferRenderer.ts

@@ -144,7 +144,7 @@ module BABYLON {
                 }
 
                 // Culling
-                engine.setState(material.backFaceCulling);
+                engine.setState(material.backFaceCulling, 0, false, scene.useRightHandedSystem);
 
                 // Managing instances
                 var batch = mesh._getInstancesRenderList(subMesh._id);