Browse Source

Merge pull request #2890 from RaananW/exception-onerror

onError exception handling
Raanan Weber 8 years ago
parent
commit
37d5a7b52e

+ 53 - 45
src/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -38,7 +38,7 @@
 
 
             return false;
             return false;
         },
         },
-        importMesh: (meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]): boolean => {
+        importMesh: (meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], onError?: (message: string, exception?: any) => void): boolean => {
             // Entire method running in try block, so ALWAYS logs as far as it got, only actually writes details
             // Entire method running in try block, so ALWAYS logs as far as it got, only actually writes details
             // when SceneLoader.debugLogging = true (default), or exception encountered.
             // when SceneLoader.debugLogging = true (default), or exception encountered.
             // Everything stored in var log instead of writing separate lines to support only writing in exception,
             // Everything stored in var log instead of writing separate lines to support only writing in exception,
@@ -53,7 +53,7 @@
                 } else if (!Array.isArray(meshesNames)) {
                 } else if (!Array.isArray(meshesNames)) {
                     meshesNames = [meshesNames];
                     meshesNames = [meshesNames];
                 }
                 }
-                
+
                 if (parsedData.meshes !== undefined && parsedData.meshes !== null) {
                 if (parsedData.meshes !== undefined && parsedData.meshes !== null) {
                     var loadedSkeletonsIds = [];
                     var loadedSkeletonsIds = [];
                     var loadedMaterialsIds = [];
                     var loadedMaterialsIds = [];
@@ -68,7 +68,7 @@
                                 // Remove found mesh name from list.
                                 // Remove found mesh name from list.
                                 delete meshesNames[meshesNames.indexOf(parsedMesh.name)];
                                 delete meshesNames[meshesNames.indexOf(parsedMesh.name)];
                             }
                             }
-        
+
                             //Geometry?
                             //Geometry?
                             if (parsedMesh.geometryId !== undefined && parsedMesh.geometryId !== null) {
                             if (parsedMesh.geometryId !== undefined && parsedMesh.geometryId !== null) {
                                 //does the file contain geometries?
                                 //does the file contain geometries?
@@ -118,7 +118,7 @@
                                     }
                                     }
                                 }
                                 }
                             }
                             }
-        
+
                             // Material ?
                             // Material ?
                             if (parsedMesh.materialId) {
                             if (parsedMesh.materialId) {
                                 var materialFound = (loadedMaterialsIds.indexOf(parsedMesh.materialId) !== -1);
                                 var materialFound = (loadedMaterialsIds.indexOf(parsedMesh.materialId) !== -1);
@@ -151,7 +151,7 @@
                                     }
                                     }
                                 }
                                 }
                             }
                             }
-        
+
                             // Skeleton ?
                             // Skeleton ?
                             if (parsedMesh.skeletonId > -1 && parsedData.skeletons !== undefined && parsedData.skeletons !== null) {
                             if (parsedMesh.skeletonId > -1 && parsedData.skeletons !== undefined && parsedData.skeletons !== null) {
                                 var skeletonAlreadyLoaded = (loadedSkeletonsIds.indexOf(parsedMesh.skeletonId) > -1);
                                 var skeletonAlreadyLoaded = (loadedSkeletonsIds.indexOf(parsedMesh.skeletonId) > -1);
@@ -173,7 +173,7 @@
                             log += "\n\tMesh " + mesh.toString(fullDetails);
                             log += "\n\tMesh " + mesh.toString(fullDetails);
                         }
                         }
                     }
                     }
-        
+
                     // Connecting parents
                     // Connecting parents
                     var currentMesh: AbstractMesh;
                     var currentMesh: AbstractMesh;
                     for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                     for (index = 0, cache = scene.meshes.length; index < cache; index++) {
@@ -183,7 +183,7 @@
                             currentMesh._waitingParentId = undefined;
                             currentMesh._waitingParentId = undefined;
                         }
                         }
                     }
                     }
-        
+
                     // freeze and compute world matrix application
                     // freeze and compute world matrix application
                     for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                     for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                         currentMesh = scene.meshes[index];
                         currentMesh = scene.meshes[index];
@@ -195,7 +195,7 @@
                         }
                         }
                     }
                     }
                 }
                 }
-    
+
                 // Particles
                 // Particles
                 if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
                 if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
                     for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
                     for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
@@ -209,17 +209,21 @@
                 return true;
                 return true;
 
 
             } catch (err) {
             } catch (err) {
-                Tools.Log(logOperation("importMesh", parsedData ? parsedData.producer : "Unknown") + log);
-                log = null;
-                throw err;
-
+                let msg = logOperation("importMesh", parsedData ? parsedData.producer : "Unknown") + log;
+                if (onError) {
+                    onError(msg, err);
+                } else {
+                    Tools.Log(msg);
+                    log = null;
+                    throw err;
+                }
             } finally {
             } finally {
                 if (log !== null && SceneLoader.loggingLevel !== SceneLoader.NO_LOGGING) {
                 if (log !== null && SceneLoader.loggingLevel !== SceneLoader.NO_LOGGING) {
                     Tools.Log(logOperation("importMesh", parsedData ? parsedData.producer : "Unknown") + (SceneLoader.loggingLevel !== SceneLoader.MINIMAL_LOGGING ? log : ""));
                     Tools.Log(logOperation("importMesh", parsedData ? parsedData.producer : "Unknown") + (SceneLoader.loggingLevel !== SceneLoader.MINIMAL_LOGGING ? log : ""));
                 }
                 }
             }
             }
         },
         },
-        load: (scene: Scene, data: string, rootUrl: string): boolean => {
+        load: (scene: Scene, data: string, rootUrl: string, onError?: (message: string, exception?: any) => void): boolean => {
             // Entire method running in try block, so ALWAYS logs as far as it got, only actually writes details
             // Entire method running in try block, so ALWAYS logs as far as it got, only actually writes details
             // when SceneLoader.debugLogging = true (default), or exception encountered.
             // when SceneLoader.debugLogging = true (default), or exception encountered.
             // Everything stored in var log instead of writing separate lines to support only writing in exception,
             // Everything stored in var log instead of writing separate lines to support only writing in exception,
@@ -229,7 +233,7 @@
                 var parsedData = JSON.parse(data);
                 var parsedData = JSON.parse(data);
                 log = "";
                 log = "";
                 var fullDetails = SceneLoader.loggingLevel === SceneLoader.DETAILED_LOGGING;
                 var fullDetails = SceneLoader.loggingLevel === SceneLoader.DETAILED_LOGGING;
-                
+
                 // Scene
                 // Scene
                 if (parsedData.useDelayedTextureLoading !== undefined && parsedData.useDelayedTextureLoading !== null) {
                 if (parsedData.useDelayedTextureLoading !== undefined && parsedData.useDelayedTextureLoading !== null) {
                     scene.useDelayedTextureLoading = parsedData.useDelayedTextureLoading && !BABYLON.SceneLoader.ForceFullSceneLoadingForIncremental;
                     scene.useDelayedTextureLoading = parsedData.useDelayedTextureLoading && !BABYLON.SceneLoader.ForceFullSceneLoadingForIncremental;
@@ -246,7 +250,7 @@
                 if (parsedData.gravity !== undefined && parsedData.gravity !== null) {
                 if (parsedData.gravity !== undefined && parsedData.gravity !== null) {
                     scene.gravity = BABYLON.Vector3.FromArray(parsedData.gravity);
                     scene.gravity = BABYLON.Vector3.FromArray(parsedData.gravity);
                 }
                 }
-                
+
                 // Fog
                 // Fog
                 if (parsedData.fogMode && parsedData.fogMode !== 0) {
                 if (parsedData.fogMode && parsedData.fogMode !== 0) {
                     scene.fogMode = parsedData.fogMode;
                     scene.fogMode = parsedData.fogMode;
@@ -262,7 +266,7 @@
                         case 3: log += "linear\n"; break;
                         case 3: log += "linear\n"; break;
                     }
                     }
                 }
                 }
-                
+
                 //Physics
                 //Physics
                 if (parsedData.physicsEnabled) {
                 if (parsedData.physicsEnabled) {
                     var physicsPlugin;
                     var physicsPlugin;
@@ -276,12 +280,12 @@
                     var physicsGravity = parsedData.physicsGravity ? BABYLON.Vector3.FromArray(parsedData.physicsGravity) : null;
                     var physicsGravity = parsedData.physicsGravity ? BABYLON.Vector3.FromArray(parsedData.physicsGravity) : null;
                     scene.enablePhysics(physicsGravity, physicsPlugin);
                     scene.enablePhysics(physicsGravity, physicsPlugin);
                 }
                 }
-                
+
                 // Metadata
                 // Metadata
                 if (parsedData.metadata !== undefined && parsedData.metadata !== null) {
                 if (parsedData.metadata !== undefined && parsedData.metadata !== null) {
                     scene.metadata = parsedData.metadata;
                     scene.metadata = parsedData.metadata;
                 }
                 }
-                
+
                 //collisions, if defined. otherwise, default is true
                 //collisions, if defined. otherwise, default is true
                 if (parsedData.collisionsEnabled !== undefined && parsedData.collisionsEnabled !== null) {
                 if (parsedData.collisionsEnabled !== undefined && parsedData.collisionsEnabled !== null) {
                     scene.collisionsEnabled = parsedData.collisionsEnabled;
                     scene.collisionsEnabled = parsedData.collisionsEnabled;
@@ -299,7 +303,7 @@
                         log += "\n\t\t" + light.toString(fullDetails);
                         log += "\n\t\t" + light.toString(fullDetails);
                     }
                     }
                 }
                 }
-    
+
                 // Animations
                 // Animations
                 if (parsedData.animations !== undefined && parsedData.animations !== null) {
                 if (parsedData.animations !== undefined && parsedData.animations !== null) {
                     for (index = 0, cache = parsedData.animations.length; index < cache; index++) {
                     for (index = 0, cache = parsedData.animations.length; index < cache; index++) {
@@ -314,7 +318,7 @@
                 if (parsedData.autoAnimate) {
                 if (parsedData.autoAnimate) {
                     scene.beginAnimation(scene, parsedData.autoAnimateFrom, parsedData.autoAnimateTo, parsedData.autoAnimateLoop, parsedData.autoAnimateSpeed || 1.0);
                     scene.beginAnimation(scene, parsedData.autoAnimateFrom, parsedData.autoAnimateTo, parsedData.autoAnimateLoop, parsedData.autoAnimateSpeed || 1.0);
                 }
                 }
-    
+
                 // Materials
                 // Materials
                 if (parsedData.materials !== undefined && parsedData.materials !== null) {
                 if (parsedData.materials !== undefined && parsedData.materials !== null) {
                     for (index = 0, cache = parsedData.materials.length; index < cache; index++) {
                     for (index = 0, cache = parsedData.materials.length; index < cache; index++) {
@@ -340,7 +344,7 @@
                         var parsedManager = MorphTargetManager.Parse(managerData, scene);
                         var parsedManager = MorphTargetManager.Parse(managerData, scene);
                     }
                     }
                 }
                 }
-    
+
                 // Skeletons
                 // Skeletons
                 if (parsedData.skeletons !== undefined && parsedData.skeletons !== null) {
                 if (parsedData.skeletons !== undefined && parsedData.skeletons !== null) {
                     for (index = 0, cache = parsedData.skeletons.length; index < cache; index++) {
                     for (index = 0, cache = parsedData.skeletons.length; index < cache; index++) {
@@ -350,7 +354,7 @@
                         log += "\n\t\t" + skeleton.toString(fullDetails);
                         log += "\n\t\t" + skeleton.toString(fullDetails);
                     }
                     }
                 }
                 }
-    
+
                 // Geometries
                 // Geometries
                 var geometries = parsedData.geometries;
                 var geometries = parsedData.geometries;
                 if (geometries !== undefined && geometries !== null) {
                 if (geometries !== undefined && geometries !== null) {
@@ -362,7 +366,7 @@
                             Geometry.Primitives.Box.Parse(parsedBox, scene);
                             Geometry.Primitives.Box.Parse(parsedBox, scene);
                         }
                         }
                     }
                     }
-    
+
                     // Spheres
                     // Spheres
                     var spheres = geometries.spheres;
                     var spheres = geometries.spheres;
                     if (spheres !== undefined && spheres !== null) {
                     if (spheres !== undefined && spheres !== null) {
@@ -371,7 +375,7 @@
                             Geometry.Primitives.Sphere.Parse(parsedSphere, scene);
                             Geometry.Primitives.Sphere.Parse(parsedSphere, scene);
                         }
                         }
                     }
                     }
-    
+
                     // Cylinders
                     // Cylinders
                     var cylinders = geometries.cylinders;
                     var cylinders = geometries.cylinders;
                     if (cylinders !== undefined && cylinders !== null) {
                     if (cylinders !== undefined && cylinders !== null) {
@@ -380,7 +384,7 @@
                             Geometry.Primitives.Cylinder.Parse(parsedCylinder, scene);
                             Geometry.Primitives.Cylinder.Parse(parsedCylinder, scene);
                         }
                         }
                     }
                     }
-    
+
                     // Toruses
                     // Toruses
                     var toruses = geometries.toruses;
                     var toruses = geometries.toruses;
                     if (toruses !== undefined && toruses !== null) {
                     if (toruses !== undefined && toruses !== null) {
@@ -389,7 +393,7 @@
                             Geometry.Primitives.Torus.Parse(parsedTorus, scene);
                             Geometry.Primitives.Torus.Parse(parsedTorus, scene);
                         }
                         }
                     }
                     }
-    
+
                     // Grounds
                     // Grounds
                     var grounds = geometries.grounds;
                     var grounds = geometries.grounds;
                     if (grounds !== undefined && grounds !== null) {
                     if (grounds !== undefined && grounds !== null) {
@@ -398,7 +402,7 @@
                             Geometry.Primitives.Ground.Parse(parsedGround, scene);
                             Geometry.Primitives.Ground.Parse(parsedGround, scene);
                         }
                         }
                     }
                     }
-    
+
                     // Planes
                     // Planes
                     var planes = geometries.planes;
                     var planes = geometries.planes;
                     if (planes !== undefined && planes !== null) {
                     if (planes !== undefined && planes !== null) {
@@ -407,7 +411,7 @@
                             Geometry.Primitives.Plane.Parse(parsedPlane, scene);
                             Geometry.Primitives.Plane.Parse(parsedPlane, scene);
                         }
                         }
                     }
                     }
-    
+
                     // TorusKnots
                     // TorusKnots
                     var torusKnots = geometries.torusKnots;
                     var torusKnots = geometries.torusKnots;
                     if (torusKnots !== undefined && torusKnots !== null) {
                     if (torusKnots !== undefined && torusKnots !== null) {
@@ -416,7 +420,7 @@
                             Geometry.Primitives.TorusKnot.Parse(parsedTorusKnot, scene);
                             Geometry.Primitives.TorusKnot.Parse(parsedTorusKnot, scene);
                         }
                         }
                     }
                     }
-    
+
                     // VertexData
                     // VertexData
                     var vertexData = geometries.vertexData;
                     var vertexData = geometries.vertexData;
                     if (vertexData !== undefined && vertexData !== null) {
                     if (vertexData !== undefined && vertexData !== null) {
@@ -426,7 +430,7 @@
                         }
                         }
                     }
                     }
                 }
                 }
-    
+
                 // Meshes
                 // Meshes
                 if (parsedData.meshes !== undefined && parsedData.meshes !== null) {
                 if (parsedData.meshes !== undefined && parsedData.meshes !== null) {
                     for (index = 0, cache = parsedData.meshes.length; index < cache; index++) {
                     for (index = 0, cache = parsedData.meshes.length; index < cache; index++) {
@@ -436,7 +440,7 @@
                         log += "\n\t\t" + mesh.toString(fullDetails);
                         log += "\n\t\t" + mesh.toString(fullDetails);
                     }
                     }
                 }
                 }
-    
+
                 // Cameras
                 // Cameras
                 if (parsedData.cameras !== undefined && parsedData.cameras !== null) {
                 if (parsedData.cameras !== undefined && parsedData.cameras !== null) {
                     for (index = 0, cache = parsedData.cameras.length; index < cache; index++) {
                     for (index = 0, cache = parsedData.cameras.length; index < cache; index++) {
@@ -449,7 +453,7 @@
                 if (parsedData.activeCameraID !== undefined && parsedData.activeCameraID !== null) {
                 if (parsedData.activeCameraID !== undefined && parsedData.activeCameraID !== null) {
                     scene.setActiveCameraByID(parsedData.activeCameraID);
                     scene.setActiveCameraByID(parsedData.activeCameraID);
                 }
                 }
-    
+
                 // Browsing all the graph to connect the dots
                 // Browsing all the graph to connect the dots
                 for (index = 0, cache = scene.cameras.length; index < cache; index++) {
                 for (index = 0, cache = scene.cameras.length; index < cache; index++) {
                     var camera = scene.cameras[index];
                     var camera = scene.cameras[index];
@@ -466,7 +470,7 @@
                         light._waitingParentId = undefined;
                         light._waitingParentId = undefined;
                     }
                     }
                 }
                 }
-    
+
                 // Sounds
                 // Sounds
                 var loadedSounds: Sound[] = [];
                 var loadedSounds: Sound[] = [];
                 var loadedSound: Sound;
                 var loadedSound: Sound;
@@ -489,7 +493,7 @@
                 }
                 }
 
 
                 loadedSounds = [];
                 loadedSounds = [];
-    
+
                 // Connect parents & children and parse actions
                 // Connect parents & children and parse actions
                 for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                 for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                     var mesh = scene.meshes[index];
                     var mesh = scene.meshes[index];
@@ -502,7 +506,7 @@
                         mesh._waitingActions = undefined;
                         mesh._waitingActions = undefined;
                     }
                     }
                 }
                 }
-    
+
                 // freeze world matrix application
                 // freeze world matrix application
                 for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                 for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                     var currentMesh = scene.meshes[index];
                     var currentMesh = scene.meshes[index];
@@ -513,7 +517,7 @@
                         currentMesh.computeWorldMatrix(true);
                         currentMesh.computeWorldMatrix(true);
                     }
                     }
                 }
                 }
-    
+
                 // Particles Systems
                 // Particles Systems
                 if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
                 if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
                     for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
                     for (index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
@@ -521,7 +525,7 @@
                         ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
                         ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
                     }
                     }
                 }
                 }
-    
+
                 // Lens flares
                 // Lens flares
                 if (parsedData.lensFlareSystems !== undefined && parsedData.lensFlareSystems !== null) {
                 if (parsedData.lensFlareSystems !== undefined && parsedData.lensFlareSystems !== null) {
                     for (index = 0, cache = parsedData.lensFlareSystems.length; index < cache; index++) {
                     for (index = 0, cache = parsedData.lensFlareSystems.length; index < cache; index++) {
@@ -529,7 +533,7 @@
                         LensFlareSystem.Parse(parsedLensFlareSystem, scene, rootUrl);
                         LensFlareSystem.Parse(parsedLensFlareSystem, scene, rootUrl);
                     }
                     }
                 }
                 }
-    
+
                 // Shadows
                 // Shadows
                 if (parsedData.shadowGenerators !== undefined && parsedData.shadowGenerators !== null) {
                 if (parsedData.shadowGenerators !== undefined && parsedData.shadowGenerators !== null) {
                     for (index = 0, cache = parsedData.shadowGenerators.length; index < cache; index++) {
                     for (index = 0, cache = parsedData.shadowGenerators.length; index < cache; index++) {
@@ -537,7 +541,7 @@
                         ShadowGenerator.Parse(parsedShadowGenerator, scene);
                         ShadowGenerator.Parse(parsedShadowGenerator, scene);
                     }
                     }
                 }
                 }
-                
+
                 // Lights exclusions / inclusions
                 // Lights exclusions / inclusions
                 for (index = 0, cache = scene.lights.length; index < cache; index++) {
                 for (index = 0, cache = scene.lights.length; index < cache; index++) {
                     var light = scene.lights[index];
                     var light = scene.lights[index];
@@ -567,20 +571,24 @@
                         light._includedOnlyMeshesIds = [];
                         light._includedOnlyMeshesIds = [];
                     }
                     }
                 }
                 }
-    
+
                 // Actions (scene)
                 // Actions (scene)
                 if (parsedData.actions !== undefined && parsedData.actions !== null) {
                 if (parsedData.actions !== undefined && parsedData.actions !== null) {
                     ActionManager.Parse(parsedData.actions, null, scene);
                     ActionManager.Parse(parsedData.actions, null, scene);
                 }
                 }
-    
+
                 // Finish
                 // Finish
                 return true;
                 return true;
 
 
             } catch (err) {
             } catch (err) {
-                Tools.Log(logOperation("importScene", parsedData ? parsedData.producer : "Unknown") + log);
-                log = null;
-                throw err;
-
+                let msg = logOperation("importScene", parsedData ? parsedData.producer : "Unknown") + log;
+                if (onError) {
+                    onError(msg, err);
+                } else {
+                    Tools.Log(msg);
+                    log = null;
+                    throw err;
+                }
             } finally {
             } finally {
                 if (log !== null && SceneLoader.loggingLevel !== SceneLoader.NO_LOGGING) {
                 if (log !== null && SceneLoader.loggingLevel !== SceneLoader.NO_LOGGING) {
                     Tools.Log(logOperation("importScene", parsedData ? parsedData.producer : "Unknown") + (SceneLoader.loggingLevel !== SceneLoader.MINIMAL_LOGGING ? log : ""));
                     Tools.Log(logOperation("importScene", parsedData ? parsedData.producer : "Unknown") + (SceneLoader.loggingLevel !== SceneLoader.MINIMAL_LOGGING ? log : ""));

+ 37 - 14
src/Loading/babylon.sceneLoader.ts

@@ -8,8 +8,8 @@
     export interface ISceneLoaderPlugin {
     export interface ISceneLoaderPlugin {
         name: string;
         name: string;
         extensions: string | ISceneLoaderPluginExtensions;
         extensions: string | ISceneLoaderPluginExtensions;
-        importMesh: (meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], onError: (message: string) => void) => boolean;
-        load: (scene: Scene, data: string, rootUrl: string, onError: (message: string) => void) => boolean;
+        importMesh: (meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], onError?: (message: string, exception?: any) => void) => boolean;
+        load: (scene: Scene, data: string, rootUrl: string, onError?: (message: string, exception?: any) => void) => boolean;
         canDirectLoad?: (data: string) => boolean;
         canDirectLoad?: (data: string) => boolean;
     }
     }
 
 
@@ -17,7 +17,7 @@
         name: string;
         name: string;
         extensions: string | ISceneLoaderPluginExtensions;
         extensions: string | ISceneLoaderPluginExtensions;
         importMeshAsync: (meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
         importMeshAsync: (meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
-        loadAsync: (scene: Scene, data: string, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void) => void;
+        loadAsync: (scene: Scene, data: string, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string, exception?: any) => void) => void;
         canDirectLoad?: (data: string) => boolean;
         canDirectLoad?: (data: string) => boolean;
     }
     }
 
 
@@ -80,7 +80,7 @@
 
 
         public static set CleanBoneMatrixWeights(value: boolean) {
         public static set CleanBoneMatrixWeights(value: boolean) {
             SceneLoader._CleanBoneMatrixWeights = value;
             SceneLoader._CleanBoneMatrixWeights = value;
-        }        
+        }
 
 
         // Members
         // Members
         public static OnPluginActivatedObservable = new Observable<ISceneLoaderPlugin | ISceneLoaderPluginAsync>();
         public static OnPluginActivatedObservable = new Observable<ISceneLoaderPlugin | ISceneLoaderPluginAsync>();
@@ -233,8 +233,12 @@
             scene._addPendingData(loadingToken);
             scene._addPendingData(loadingToken);
 
 
             var errorHandler = (message?: string, exception?: any) => {
             var errorHandler = (message?: string, exception?: any) => {
+                let errorMessage = "Unable to import meshes from " + rootUrl + sceneFilename + (message ? ": " + message : "");
                 if (onError) {
                 if (onError) {
-                    onError(scene, "Unable to import meshes from " + rootUrl + sceneFilename + (message ? ": " + message : ""));
+                    onError(scene, errorMessage, exception);
+                } else {
+                    Tools.Error(errorMessage);
+                    // should the exception be thrown?
                 }
                 }
                 scene._removePendingData(loadingToken);
                 scene._removePendingData(loadingToken);
             };
             };
@@ -256,18 +260,29 @@
                     }
                     }
 
 
                     if (onSuccess) {
                     if (onSuccess) {
-                        scene.importedMeshesFiles.push(rootUrl + sceneFilename);
-                        onSuccess(meshes, particleSystems, skeletons);
-                        scene._removePendingData(loadingToken);
+                        // wrap onSuccess with try-catch to know if something went wrong.
+                        try {
+                            scene.importedMeshesFiles.push(rootUrl + sceneFilename);
+                            onSuccess(meshes, particleSystems, skeletons);
+                            scene._removePendingData(loadingToken);
+                        } catch (e) {
+                            let message = 'Error in onSuccess callback.';
+                            errorHandler(message, e);
+                        }
                     }
                     }
                 }
                 }
                 else {
                 else {
                     var asyncedPlugin = <ISceneLoaderPluginAsync>plugin;
                     var asyncedPlugin = <ISceneLoaderPluginAsync>plugin;
                     asyncedPlugin.importMeshAsync(meshNames, scene, data, rootUrl, (meshes, particleSystems, skeletons) => {
                     asyncedPlugin.importMeshAsync(meshNames, scene, data, rootUrl, (meshes, particleSystems, skeletons) => {
                         if (onSuccess) {
                         if (onSuccess) {
-                            scene.importedMeshesFiles.push(rootUrl + sceneFilename);
-                            onSuccess(meshes, particleSystems, skeletons);
-                            scene._removePendingData(loadingToken);
+                            try {
+                                scene.importedMeshesFiles.push(rootUrl + sceneFilename);
+                                onSuccess(meshes, particleSystems, skeletons);
+                                scene._removePendingData(loadingToken);
+                            } catch (e) {
+                                let message = 'Error in onSuccess callback.';
+                                errorHandler(message, e);
+                            }
                         }
                         }
                     }, progressHandler, errorHandler);
                     }, progressHandler, errorHandler);
                 }
                 }
@@ -310,8 +325,12 @@
             scene._addPendingData(loadingToken);
             scene._addPendingData(loadingToken);
 
 
             var errorHandler = (message?: string, exception?: any) => {
             var errorHandler = (message?: string, exception?: any) => {
+                let errorMessage = "Unable to load from " + rootUrl + sceneFilename + (message ? ": " + message : "");
                 if (onError) {
                 if (onError) {
-                    onError(scene, "Unable to load from " + rootUrl + sceneFilename + (message ? ": " + message : ""));
+                    onError(scene, errorMessage, exception);
+                } else {
+                    Tools.Error(errorMessage);
+                    // should the exception be thrown?
                 }
                 }
                 scene._removePendingData(loadingToken);
                 scene._removePendingData(loadingToken);
                 scene.getEngine().hideLoadingUI();
                 scene.getEngine().hideLoadingUI();
@@ -331,7 +350,11 @@
                     }
                     }
 
 
                     if (onSuccess) {
                     if (onSuccess) {
-                        onSuccess(scene);
+                        try {
+                            onSuccess(scene);
+                        } catch (e) {
+                            errorHandler("Error in onSuccess callback", e);
+                        }
                     }
                     }
 
 
                     scene.loadingPluginName = plugin.name;
                     scene.loadingPluginName = plugin.name;
@@ -342,7 +365,7 @@
                         if (onSuccess) {
                         if (onSuccess) {
                             onSuccess(scene);
                             onSuccess(scene);
                         }
                         }
-                        
+
                         scene.loadingPluginName = plugin.name;
                         scene.loadingPluginName = plugin.name;
                         scene._removePendingData(loadingToken);
                         scene._removePendingData(loadingToken);
                     }, progressHandler, errorHandler);
                     }, progressHandler, errorHandler);

+ 1 - 1
src/Materials/Textures/babylon.cubeTexture.ts

@@ -18,7 +18,7 @@
             return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension);
             return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension);
         }
         }
 
 
-        constructor(rootUrl: string, scene: Scene, extensions?: string[], noMipmap?: boolean, files?: string[], onLoad: () => void = null, onError: () => void = null, format: number = Engine.TEXTUREFORMAT_RGBA, prefiltered = false, forcedExtension = null) {
+        constructor(rootUrl: string, scene: Scene, extensions?: string[], noMipmap?: boolean, files?: string[], onLoad: () => void = null, onError: (message?: string, exception?: any) => void = null, format: number = Engine.TEXTUREFORMAT_RGBA, prefiltered = false, forcedExtension = null) {
             super(scene);
             super(scene);
 
 
             this.name = rootUrl;
             this.name = rootUrl;

+ 2 - 2
src/Materials/Textures/babylon.hdrCubeTexture.ts

@@ -69,7 +69,7 @@ module BABYLON {
          * @param useInGammaSpace Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space)
          * @param useInGammaSpace Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space)
          * @param usePMREMGenerator Specifies wether or not to generate the CubeMap through CubeMapGen to avoid seams issue at run time.
          * @param usePMREMGenerator Specifies wether or not to generate the CubeMap through CubeMapGen to avoid seams issue at run time.
          */
          */
-        constructor(url: string, scene: Scene, size?: number, noMipmap = false, generateHarmonics = true, useInGammaSpace = false, usePMREMGenerator = false, onLoad: () => void = null, onError: () => void = null) {
+        constructor(url: string, scene: Scene, size?: number, noMipmap = false, generateHarmonics = true, useInGammaSpace = false, usePMREMGenerator = false, onLoad: () => void = null, onError: (message?: string, exception?: any) => void = null) {
             super(scene);
             super(scene);
 
 
             if (!url) {
             if (!url) {
@@ -436,7 +436,7 @@ module BABYLON {
             serializationObject.customType = "BABYLON.HDRCubeTexture";
             serializationObject.customType = "BABYLON.HDRCubeTexture";
             serializationObject.noMipmap = this._noMipmap;
             serializationObject.noMipmap = this._noMipmap;
             serializationObject.isBlocking = this._isBlocking;
             serializationObject.isBlocking = this._isBlocking;
-            
+
             return serializationObject;
             return serializationObject;
         }
         }
 
 

+ 15 - 15
src/Materials/Textures/babylon.texture.ts

@@ -1,12 +1,12 @@
 module BABYLON {
 module BABYLON {
     export class Texture extends BaseTexture {
     export class Texture extends BaseTexture {
         // Constants
         // Constants
-        public static NEAREST_SAMPLINGMODE = 1;        
+        public static NEAREST_SAMPLINGMODE = 1;
         public static NEAREST_NEAREST_MIPLINEAR = 1; // nearest is mag = nearest and min = nearest and mip = linear
         public static NEAREST_NEAREST_MIPLINEAR = 1; // nearest is mag = nearest and min = nearest and mip = linear
-        
+
         public static BILINEAR_SAMPLINGMODE = 2;
         public static BILINEAR_SAMPLINGMODE = 2;
         public static LINEAR_LINEAR_MIPNEAREST = 2; // Bilinear is mag = linear and min = linear and mip = nearest
         public static LINEAR_LINEAR_MIPNEAREST = 2; // Bilinear is mag = linear and min = linear and mip = nearest
-        
+
         public static TRILINEAR_SAMPLINGMODE = 3;
         public static TRILINEAR_SAMPLINGMODE = 3;
         public static LINEAR_LINEAR_MIPLINEAR = 3; // Trilinear is mag = linear and min = linear and mip = linear
         public static LINEAR_LINEAR_MIPLINEAR = 3; // Trilinear is mag = linear and min = linear and mip = linear
 
 
@@ -103,7 +103,7 @@
             return this._samplingMode;
             return this._samplingMode;
         }
         }
 
 
-        constructor(url: string, scene: Scene, noMipmap: boolean = false, invertY: boolean = true, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null, buffer: any = null, deleteBuffer: boolean = false, format?: number) {
+        constructor(url: string, scene: Scene, noMipmap: boolean = false, invertY: boolean = true, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: (message?: string, esception?: any) => void = null, buffer: any = null, deleteBuffer: boolean = false, format?: number) {
             super(scene);
             super(scene);
 
 
             this.name = url;
             this.name = url;
@@ -270,13 +270,13 @@
                 this.uScale === this._cachedUScale &&
                 this.uScale === this._cachedUScale &&
                 this.vScale === this._cachedVScale &&
                 this.vScale === this._cachedVScale &&
                 this.coordinatesMode === this._cachedCoordinatesMode) {
                 this.coordinatesMode === this._cachedCoordinatesMode) {
-                    if (this.coordinatesMode === Texture.PROJECTION_MODE) {
-                        if (this._cachedProjectionMatrixId === scene.getProjectionMatrix().updateFlag) {
-                            return this._cachedTextureMatrix;
-                        }
-                    } else {
+                if (this.coordinatesMode === Texture.PROJECTION_MODE) {
+                    if (this._cachedProjectionMatrixId === scene.getProjectionMatrix().updateFlag) {
                         return this._cachedTextureMatrix;
                         return this._cachedTextureMatrix;
                     }
                     }
+                } else {
+                    return this._cachedTextureMatrix;
+                }
             }
             }
 
 
             if (!this._cachedTextureMatrix) {
             if (!this._cachedTextureMatrix) {
@@ -317,7 +317,7 @@
                     Matrix.IdentityToRef(this._cachedTextureMatrix);
                     Matrix.IdentityToRef(this._cachedTextureMatrix);
                     break;
                     break;
             }
             }
-            
+
             scene.markAllMaterialsAsDirty(Material.TextureDirtyFlag, (mat) => {
             scene.markAllMaterialsAsDirty(Material.TextureDirtyFlag, (mat) => {
                 return (mat.getActiveTextures().indexOf(this) !== -1);
                 return (mat.getActiveTextures().indexOf(this) !== -1);
             });
             });
@@ -340,7 +340,7 @@
 
 
         public serialize(): any {
         public serialize(): any {
             var serializationObject = super.serialize();
             var serializationObject = super.serialize();
-            
+
             if (typeof this._buffer === "string" && this._buffer.substr(0, 5) === "data:") {
             if (typeof this._buffer === "string" && this._buffer.substr(0, 5) === "data:") {
                 serializationObject.base64String = this._buffer;
                 serializationObject.base64String = this._buffer;
                 serializationObject.name = serializationObject.name.replace("data:", "");
                 serializationObject.name = serializationObject.name.replace("data:", "");
@@ -371,10 +371,10 @@
         }
         }
 
 
         public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): BaseTexture {
         public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): BaseTexture {
-            if (parsedTexture.customType) { 
+            if (parsedTexture.customType) {
                 var customTexture = Tools.Instantiate(parsedTexture.customType);
                 var customTexture = Tools.Instantiate(parsedTexture.customType);
                 // Update Sampling Mode
                 // Update Sampling Mode
-                var parsedCustomTexture:any = customTexture.Parse(parsedTexture, scene, rootUrl);
+                var parsedCustomTexture: any = customTexture.Parse(parsedTexture, scene, rootUrl);
                 if (parsedTexture.samplingMode && parsedCustomTexture.updateSamplingMode && parsedCustomTexture._samplingMode) {
                 if (parsedTexture.samplingMode && parsedCustomTexture.updateSamplingMode && parsedCustomTexture._samplingMode) {
                     if (parsedCustomTexture._samplingMode !== parsedTexture.samplingMode) {
                     if (parsedCustomTexture._samplingMode !== parsedTexture.samplingMode) {
                         parsedCustomTexture.updateSamplingMode(parsedTexture.samplingMode);
                         parsedCustomTexture.updateSamplingMode(parsedTexture.samplingMode);
@@ -417,7 +417,7 @@
 
 
             // Update Sampling Mode
             // Update Sampling Mode
             if (parsedTexture.samplingMode) {
             if (parsedTexture.samplingMode) {
-                var sampling:number = parsedTexture.samplingMode;
+                var sampling: number = parsedTexture.samplingMode;
                 if (texture._samplingMode !== sampling) {
                 if (texture._samplingMode !== sampling) {
                     texture.updateSamplingMode(sampling);
                     texture.updateSamplingMode(sampling);
                 }
                 }
@@ -435,7 +435,7 @@
             return texture;
             return texture;
         }
         }
 
 
-        public static LoadFromDataString(name: string, buffer: any, scene: Scene, deleteBuffer: boolean = false, noMipmap: boolean = false, invertY: boolean = true, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null, format: number = Engine.TEXTUREFORMAT_RGBA): Texture {
+        public static LoadFromDataString(name: string, buffer: any, scene: Scene, deleteBuffer: boolean = false, noMipmap: boolean = false, invertY: boolean = true, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: (message?: string, exception?: any) => void = null, format: number = Engine.TEXTUREFORMAT_RGBA): Texture {
             if (name.substr(0, 5) !== "data:") {
             if (name.substr(0, 5) !== "data:") {
                 name = "data:" + name;
                 name = "data:" + name;
             }
             }

+ 62 - 53
src/Tools/babylon.assetsManager.ts

@@ -1,10 +1,10 @@
 module BABYLON {
 module BABYLON {
     export interface IAssetTask {
     export interface IAssetTask {
         onSuccess: (task: IAssetTask) => void;
         onSuccess: (task: IAssetTask) => void;
-        onError: (task: IAssetTask) => void;
+        onError: (task: IAssetTask, message?: string, exception?: any) => void;
         isCompleted: boolean;
         isCompleted: boolean;
 
 
-        run(scene: Scene, onSuccess: () => void, onError: () => void);
+        run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void);
     }
     }
 
 
     export class MeshAssetTask implements IAssetTask {
     export class MeshAssetTask implements IAssetTask {
@@ -13,14 +13,14 @@
         public loadedSkeletons: Array<Skeleton>;
         public loadedSkeletons: Array<Skeleton>;
 
 
         public onSuccess: (task: IAssetTask) => void;
         public onSuccess: (task: IAssetTask) => void;
-        public onError: (task: IAssetTask) => void;
+        public onError: (task: IAssetTask, message?: string, exception?: any) => void;
 
 
         public isCompleted = false;
         public isCompleted = false;
 
 
         constructor(public name: string, public meshesNames: any, public rootUrl: string, public sceneFilename: string) {
         constructor(public name: string, public meshesNames: any, public rootUrl: string, public sceneFilename: string) {
         }
         }
 
 
-        public run(scene: Scene, onSuccess: () => void, onError: () => void) {
+        public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
             SceneLoader.ImportMesh(this.meshesNames, this.rootUrl, this.sceneFilename, scene,
             SceneLoader.ImportMesh(this.meshesNames, this.rootUrl, this.sceneFilename, scene,
                 (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => {
                 (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => {
                     this.loadedMeshes = meshes;
                     this.loadedMeshes = meshes;
@@ -34,20 +34,20 @@
                     }
                     }
 
 
                     onSuccess();
                     onSuccess();
-                }, null, () => {
+                }, null, (scene, message, exception) => {
                     if (this.onError) {
                     if (this.onError) {
-                        this.onError(this);
+                        this.onError(this, message, exception);
                     }
                     }
 
 
-                    onError();
+                    onError(message, exception);
                 }
                 }
-                );
+            );
         }
         }
     }
     }
 
 
     export class TextFileAssetTask implements IAssetTask {
     export class TextFileAssetTask implements IAssetTask {
         public onSuccess: (task: IAssetTask) => void;
         public onSuccess: (task: IAssetTask) => void;
-        public onError: (task: IAssetTask) => void;
+        public onError: (task: IAssetTask, message?: string, exception?: any) => void;
 
 
         public isCompleted = false;
         public isCompleted = false;
         public text: string;
         public text: string;
@@ -55,7 +55,7 @@
         constructor(public name: string, public url: string) {
         constructor(public name: string, public url: string) {
         }
         }
 
 
-        public run(scene: Scene, onSuccess: () => void, onError: () => void) {
+        public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
             Tools.LoadFile(this.url, (data) => {
             Tools.LoadFile(this.url, (data) => {
 
 
                 this.text = data;
                 this.text = data;
@@ -66,19 +66,19 @@
                 }
                 }
 
 
                 onSuccess();
                 onSuccess();
-            }, null, scene.database, false, () => {
-                    if (this.onError) {
-                        this.onError(this);
-                    }
+            }, null, scene.database, false, (request, exception) => {
+                if (this.onError) {
+                    this.onError(this, request.status + " " + request.statusText, exception);
+                }
 
 
-                    onError();
-                });
+                onError(request.status + " " + request.statusText, exception);
+            });
         }
         }
     }
     }
 
 
     export class BinaryFileAssetTask implements IAssetTask {
     export class BinaryFileAssetTask implements IAssetTask {
         public onSuccess: (task: IAssetTask) => void;
         public onSuccess: (task: IAssetTask) => void;
-        public onError: (task: IAssetTask) => void;
+        public onError: (task: IAssetTask, message?: string, exception?: any) => void;
 
 
         public isCompleted = false;
         public isCompleted = false;
         public data: ArrayBuffer;
         public data: ArrayBuffer;
@@ -86,7 +86,7 @@
         constructor(public name: string, public url: string) {
         constructor(public name: string, public url: string) {
         }
         }
 
 
-        public run(scene: Scene, onSuccess: () => void, onError: () => void) {
+        public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
             Tools.LoadFile(this.url, (data) => {
             Tools.LoadFile(this.url, (data) => {
 
 
                 this.data = data;
                 this.data = data;
@@ -97,19 +97,19 @@
                 }
                 }
 
 
                 onSuccess();
                 onSuccess();
-            }, null, scene.database, true, () => {
-                    if (this.onError) {
-                        this.onError(this);
-                    }
+            }, null, scene.database, true, (request, exception) => {
+                if (this.onError) {
+                    this.onError(this, request.status + " " + request.statusText, exception);
+                }
 
 
-                    onError();
-                });
+                onError(request.status + " " + request.statusText, exception);
+            });
         }
         }
     }
     }
 
 
     export class ImageAssetTask implements IAssetTask {
     export class ImageAssetTask implements IAssetTask {
         public onSuccess: (task: IAssetTask) => void;
         public onSuccess: (task: IAssetTask) => void;
-        public onError: (task: IAssetTask) => void;
+        public onError: (task: IAssetTask, message?: string, exception?: any) => void;
 
 
         public isCompleted = false;
         public isCompleted = false;
         public image: HTMLImageElement;
         public image: HTMLImageElement;
@@ -117,7 +117,7 @@
         constructor(public name: string, public url: string) {
         constructor(public name: string, public url: string) {
         }
         }
 
 
-        public run(scene: Scene, onSuccess: () => void, onError: () => void) {
+        public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
             var img = new Image();
             var img = new Image();
 
 
             Tools.SetCorsBehavior(this.url, img);
             Tools.SetCorsBehavior(this.url, img);
@@ -133,12 +133,12 @@
                 onSuccess();
                 onSuccess();
             };
             };
 
 
-            img.onerror = () => {
+            img.onerror = (err: ErrorEvent): any => {
                 if (this.onError) {
                 if (this.onError) {
-                    this.onError(this);
+                    this.onError(this, "Error loading image", err);
                 }
                 }
 
 
-                onError();
+                onError("Error loading image", err);
             };
             };
 
 
             img.src = this.url;
             img.src = this.url;
@@ -147,13 +147,13 @@
 
 
     export interface ITextureAssetTask extends IAssetTask {
     export interface ITextureAssetTask extends IAssetTask {
         onSuccess: (task: ITextureAssetTask) => void;
         onSuccess: (task: ITextureAssetTask) => void;
-        onError: (task: ITextureAssetTask) => void;
+        onError: (task: ITextureAssetTask, ) => void;
         texture: Texture;
         texture: Texture;
     }
     }
 
 
     export class TextureAssetTask implements ITextureAssetTask {
     export class TextureAssetTask implements ITextureAssetTask {
         public onSuccess: (task: ITextureAssetTask) => void;
         public onSuccess: (task: ITextureAssetTask) => void;
-        public onError: (task: ITextureAssetTask) => void;
+        public onError: (task: ITextureAssetTask, message?: string, exception?: any) => void;
 
 
         public isCompleted = false;
         public isCompleted = false;
         public texture: Texture;
         public texture: Texture;
@@ -161,7 +161,7 @@
         constructor(public name: string, public url: string, public noMipmap?: boolean, public invertY?: boolean, public samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
         constructor(public name: string, public url: string, public noMipmap?: boolean, public invertY?: boolean, public samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
         }
         }
 
 
-        public run(scene: Scene, onSuccess: () => void, onError: () => void) {
+        public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
 
 
             var onload = () => {
             var onload = () => {
                 this.isCompleted = true;
                 this.isCompleted = true;
@@ -173,12 +173,12 @@
                 onSuccess();
                 onSuccess();
             };
             };
 
 
-            var onerror = () => {
+            var onerror = (msg, exception) => {
                 if (this.onError) {
                 if (this.onError) {
-                    this.onError(this);
+                    this.onError(this, msg, exception);
                 }
                 }
 
 
-                onError();
+                onError(msg, exception);
             };
             };
 
 
             this.texture = new Texture(this.url, scene, this.noMipmap, this.invertY, this.samplingMode, onload, onerror);
             this.texture = new Texture(this.url, scene, this.noMipmap, this.invertY, this.samplingMode, onload, onerror);
@@ -187,7 +187,7 @@
 
 
     export class CubeTextureAssetTask implements IAssetTask {
     export class CubeTextureAssetTask implements IAssetTask {
         public onSuccess: (task: IAssetTask) => void;
         public onSuccess: (task: IAssetTask) => void;
-        public onError: (task: IAssetTask) => void;
+        public onError: (task: IAssetTask, message?: string, exception?: any) => void;
 
 
         public isCompleted = false;
         public isCompleted = false;
         public texture: CubeTexture;
         public texture: CubeTexture;
@@ -195,7 +195,7 @@
         constructor(public name: string, public url: string, public extensions?: string[], public noMipmap?: boolean, public files?: string[]) {
         constructor(public name: string, public url: string, public extensions?: string[], public noMipmap?: boolean, public files?: string[]) {
         }
         }
 
 
-        public run(scene: Scene, onSuccess: () => void, onError: () => void) {
+        public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
 
 
             var onload = () => {
             var onload = () => {
                 this.isCompleted = true;
                 this.isCompleted = true;
@@ -207,21 +207,21 @@
                 onSuccess();
                 onSuccess();
             };
             };
 
 
-            var onerror = () => {
+            var onerror = (msg, exception) => {
                 if (this.onError) {
                 if (this.onError) {
-                    this.onError(this);
+                    this.onError(this, msg, exception);
                 }
                 }
 
 
-                onError();
+                onError(msg, exception);
             };
             };
 
 
             this.texture = new CubeTexture(this.url, scene, this.extensions, this.noMipmap, this.files, onload, onerror);
             this.texture = new CubeTexture(this.url, scene, this.extensions, this.noMipmap, this.files, onload, onerror);
         }
         }
     }
     }
 
 
-      export class HDRCubeTextureAssetTask implements IAssetTask {
+    export class HDRCubeTextureAssetTask implements IAssetTask {
         public onSuccess: (task: IAssetTask) => void;
         public onSuccess: (task: IAssetTask) => void;
-        public onError: (task: IAssetTask) => void;
+        public onError: (task: IAssetTask, message?: string, exception?: any) => void;
 
 
         public isCompleted = false;
         public isCompleted = false;
         public texture: HDRCubeTexture;
         public texture: HDRCubeTexture;
@@ -229,7 +229,7 @@
         constructor(public name: string, public url: string, public size?: number, public noMipmap = false, public generateHarmonics = true, public useInGammaSpace = false, public usePMREMGenerator = false) {
         constructor(public name: string, public url: string, public size?: number, public noMipmap = false, public generateHarmonics = true, public useInGammaSpace = false, public usePMREMGenerator = false) {
         }
         }
 
 
-        public run(scene: Scene, onSuccess: () => void, onError: () => void) {
+        public run(scene: Scene, onSuccess: () => void, onError: (message?: string, exception?: any) => void) {
 
 
             var onload = () => {
             var onload = () => {
                 this.isCompleted = true;
                 this.isCompleted = true;
@@ -241,12 +241,12 @@
                 onSuccess();
                 onSuccess();
             };
             };
 
 
-            var onerror = () => {
+            var onerror = (message?: string, exception?: any) => {
                 if (this.onError) {
                 if (this.onError) {
-                    this.onError(this);
+                    this.onError(this, message, exception);
                 }
                 }
 
 
-                onError();
+                onError(message, exception);
             };
             };
 
 
             this.texture = new HDRCubeTexture(this.url, scene, this.size, this.noMipmap, this.generateHarmonics, this.useInGammaSpace, this.usePMREMGenerator, onload, onerror);
             this.texture = new HDRCubeTexture(this.url, scene, this.size, this.noMipmap, this.generateHarmonics, this.useInGammaSpace, this.usePMREMGenerator, onload, onerror);
@@ -263,6 +263,12 @@
         public onTaskSuccess: (task: IAssetTask) => void;
         public onTaskSuccess: (task: IAssetTask) => void;
         public onTaskError: (task: IAssetTask) => void;
         public onTaskError: (task: IAssetTask) => void;
 
 
+        //Observables
+
+        public onTaskSuccessObservable = new Observable<IAssetTask>();
+        public onTaskErrorObservable = new Observable<IAssetTask>();
+        public onTasksDoneObservable = new Observable<IAssetTask[]>();
+
         public useDefaultLoadingScreen = true;
         public useDefaultLoadingScreen = true;
 
 
         constructor(scene: Scene) {
         constructor(scene: Scene) {
@@ -318,7 +324,7 @@
 
 
             return task;
             return task;
         }
         }
-        
+
         private _decreaseWaitingTasksCount(): void {
         private _decreaseWaitingTasksCount(): void {
             this.waitingTasksCount--;
             this.waitingTasksCount--;
 
 
@@ -336,13 +342,15 @@
                 if (this.onTaskSuccess) {
                 if (this.onTaskSuccess) {
                     this.onTaskSuccess(task);
                     this.onTaskSuccess(task);
                 }
                 }
+                this.onTaskSuccessObservable.notifyObservers(task);
                 this._decreaseWaitingTasksCount();
                 this._decreaseWaitingTasksCount();
             }, () => {
             }, () => {
-                    if (this.onTaskError) {
-                        this.onTaskError(task);
-                    }
-                    this._decreaseWaitingTasksCount();
-                });
+                if (this.onTaskError) {
+                    this.onTaskError(task);
+                }
+                this.onTaskErrorObservable.notifyObservers(task);
+                this._decreaseWaitingTasksCount();
+            });
         }
         }
 
 
         public reset(): AssetsManager {
         public reset(): AssetsManager {
@@ -357,6 +365,7 @@
                 if (this.onFinish) {
                 if (this.onFinish) {
                     this.onFinish(this.tasks);
                     this.onFinish(this.tasks);
                 }
                 }
+                this.onTasksDoneObservable.notifyObservers(this.tasks);
                 return this;
                 return this;
             }
             }
 
 
@@ -370,6 +379,6 @@
             }
             }
 
 
             return this;
             return this;
-        }     
+        }
     }
     }
 } 
 } 

File diff suppressed because it is too large
+ 51 - 45
src/Tools/babylon.tools.ts


+ 43 - 37
src/babylon.engine.ts

@@ -105,7 +105,7 @@
     }
     }
 
 
     var partialLoad = (url: string, index: number, loadedImages: any, scene,
     var partialLoad = (url: string, index: number, loadedImages: any, scene,
-        onfinish: (images: HTMLImageElement[]) => void, onErrorCallBack: () => void = null) => {
+        onfinish: (images: HTMLImageElement[]) => void, onErrorCallBack: (message?: string, exception?: any) => void = null) => {
 
 
         var img: HTMLImageElement;
         var img: HTMLImageElement;
 
 
@@ -122,13 +122,13 @@
             }
             }
         };
         };
 
 
-        var onerror = () => {
+        var onerror = (message?: string, exception?: any) => {
             if (scene) {
             if (scene) {
                 scene._removePendingData(img);
                 scene._removePendingData(img);
             }
             }
 
 
             if (onErrorCallBack) {
             if (onErrorCallBack) {
-                onErrorCallBack();
+                onErrorCallBack(message, exception);
             }
             }
         };
         };
 
 
@@ -139,7 +139,7 @@
     }
     }
 
 
     var cascadeLoad = (rootUrl: string, scene,
     var cascadeLoad = (rootUrl: string, scene,
-        onfinish: (images: HTMLImageElement[]) => void, files: string[], onError: () => void = null) => {
+        onfinish: (images: HTMLImageElement[]) => void, files: string[], onError: (message?: string, exception?: any) => void = null) => {
 
 
         var loadedImages: any = [];
         var loadedImages: any = [];
         loadedImages._internalCount = 0;
         loadedImages._internalCount = 0;
@@ -552,7 +552,7 @@
         /**
         /**
          * Observable event triggered each time the canvas gains focus
          * Observable event triggered each time the canvas gains focus
          */
          */
-        public onCanvasFocusObservable = new Observable<Engine>();        
+        public onCanvasFocusObservable = new Observable<Engine>();
 
 
         /**
         /**
          * Observable event triggered each time the canvas receives pointerout event
          * Observable event triggered each time the canvas receives pointerout event
@@ -605,14 +605,14 @@
 
 
         public static audioEngine: AudioEngine;
         public static audioEngine: AudioEngine;
 
 
-        
+
         // Focus
         // Focus
         private _onFocus: () => void;
         private _onFocus: () => void;
-        private _onBlur: () => void;       
+        private _onBlur: () => void;
         private _onCanvasPointerOut: () => void;
         private _onCanvasPointerOut: () => void;
         private _onCanvasBlur: () => void;
         private _onCanvasBlur: () => void;
         private _onCanvasFocus: () => void;
         private _onCanvasFocus: () => void;
-        
+
         private _onFullscreenChange: () => void;
         private _onFullscreenChange: () => void;
         private _onPointerLockChange: () => void;
         private _onPointerLockChange: () => void;
 
 
@@ -821,18 +821,18 @@
                 if (!this._gl) {
                 if (!this._gl) {
                     throw new Error("WebGL not supported");
                     throw new Error("WebGL not supported");
                 }
                 }
-    
+
                 this._onCanvasFocus = () => {
                 this._onCanvasFocus = () => {
                     this.onCanvasFocusObservable.notifyObservers(this);
                     this.onCanvasFocusObservable.notifyObservers(this);
                 }
                 }
-    
+
                 this._onCanvasBlur = () => {
                 this._onCanvasBlur = () => {
                     this.onCanvasBlurObservable.notifyObservers(this);
                     this.onCanvasBlurObservable.notifyObservers(this);
                 }
                 }
-    
+
                 canvas.addEventListener("focus", this._onCanvasFocus);
                 canvas.addEventListener("focus", this._onCanvasFocus);
                 canvas.addEventListener("blur", this._onCanvasBlur);
                 canvas.addEventListener("blur", this._onCanvasBlur);
-    
+
                 this._onBlur = () => {
                 this._onBlur = () => {
                     if (this.disablePerformanceMonitorInBackground) {
                     if (this.disablePerformanceMonitorInBackground) {
                         this._performanceMonitor.disable();
                         this._performanceMonitor.disable();
@@ -868,7 +868,7 @@
 
 
                     this._onContextRestored = (evt: Event) => {
                     this._onContextRestored = (evt: Event) => {
                         // Adding a timeout to avoid race condition at browser level
                         // Adding a timeout to avoid race condition at browser level
-                        setTimeout(()=> {
+                        setTimeout(() => {
                             // Rebuild gl context
                             // Rebuild gl context
                             this._initGLContext();
                             this._initGLContext();
 
 
@@ -894,7 +894,7 @@
 
 
                     canvas.addEventListener("webglcontextlost", this._onContextLost, false);
                     canvas.addEventListener("webglcontextlost", this._onContextLost, false);
                     canvas.addEventListener("webglcontextrestored", this._onContextRestored, false);
                     canvas.addEventListener("webglcontextrestored", this._onContextRestored, false);
-                }                
+                }
             } else {
             } else {
                 this._gl = <WebGLRenderingContext>canvasOrContext;
                 this._gl = <WebGLRenderingContext>canvasOrContext;
                 this._renderingCanvas = this._gl.canvas
                 this._renderingCanvas = this._gl.canvas
@@ -1106,7 +1106,7 @@
                     this._caps.drawBuffersExtension = true;
                     this._caps.drawBuffersExtension = true;
                     this._gl.drawBuffers = drawBuffersExtension.drawBuffersWEBGL.bind(drawBuffersExtension);
                     this._gl.drawBuffers = drawBuffersExtension.drawBuffersWEBGL.bind(drawBuffersExtension);
                     this._gl.DRAW_FRAMEBUFFER = this._gl.FRAMEBUFFER;
                     this._gl.DRAW_FRAMEBUFFER = this._gl.FRAMEBUFFER;
-                    
+
                     for (var i = 0; i < 16; i++) {
                     for (var i = 0; i < 16; i++) {
                         this._gl["COLOR_ATTACHMENT" + i + "_WEBGL"] = drawBuffersExtension["COLOR_ATTACHMENT" + i + "_WEBGL"];
                         this._gl["COLOR_ATTACHMENT" + i + "_WEBGL"] = drawBuffersExtension["COLOR_ATTACHMENT" + i + "_WEBGL"];
                     }
                     }
@@ -1408,7 +1408,7 @@
 
 
                     // Present
                     // Present
                     this.endFrame();
                     this.endFrame();
-                }  
+                }
             }
             }
 
 
             if (this._activeRenderLoops.length > 0) {
             if (this._activeRenderLoops.length > 0) {
@@ -1595,15 +1595,15 @@
         }
         }
 
 
         // WebVR functions
         // WebVR functions
-        public isVRDevicePresent() : boolean {
+        public isVRDevicePresent(): boolean {
             return !!this._vrDisplay;
             return !!this._vrDisplay;
         }
         }
 
 
-        public getVRDevice() : any {
+        public getVRDevice(): any {
             return this._vrDisplay;
             return this._vrDisplay;
         }
         }
 
 
-        public initWebVR(): Observable<{vrDisplay: any, vrSupported: any}> {
+        public initWebVR(): Observable<{ vrDisplay: any, vrSupported: any }> {
             var notifyObservers = () => {
             var notifyObservers = () => {
                 var eventArgs = {
                 var eventArgs = {
                     vrDisplay: this._vrDisplay,
                     vrDisplay: this._vrDisplay,
@@ -1623,14 +1623,14 @@
                     this._frameHandler = Tools.QueueNewFrame(this._bindedRenderFunction);
                     this._frameHandler = Tools.QueueNewFrame(this._bindedRenderFunction);
                     notifyObservers();
                     notifyObservers();
                 };
                 };
-                this._onVrDisplayPresentChange = () => {                    
+                this._onVrDisplayPresentChange = () => {
                     this._vrExclusivePointerMode = this._vrDisplay && this._vrDisplay.isPresenting;
                     this._vrExclusivePointerMode = this._vrDisplay && this._vrDisplay.isPresenting;
                 }
                 }
                 window.addEventListener('vrdisplayconnect', this._onVrDisplayConnect);
                 window.addEventListener('vrdisplayconnect', this._onVrDisplayConnect);
                 window.addEventListener('vrdisplaydisconnect', this._onVrDisplayDisconnect);
                 window.addEventListener('vrdisplaydisconnect', this._onVrDisplayDisconnect);
                 window.addEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
                 window.addEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
             }
             }
-            
+
             this._getVRDisplays(notifyObservers);
             this._getVRDisplays(notifyObservers);
 
 
             return this.onVRDisplayChangedObservable;
             return this.onVRDisplayChangedObservable;
@@ -1645,7 +1645,7 @@
                 var onRejected = () => {
                 var onRejected = () => {
                     this.onVRRequestPresentComplete.notifyObservers(false);
                     this.onVRRequestPresentComplete.notifyObservers(false);
                 };
                 };
-                
+
                 this.onVRRequestPresentStart.notifyObservers(this);
                 this.onVRRequestPresentStart.notifyObservers(this);
                 this._vrDisplay.requestPresent([{ source: this.getRenderingCanvas() }]).then(onResolved).catch(onRejected);
                 this._vrDisplay.requestPresent([{ source: this.getRenderingCanvas() }]).then(onResolved).catch(onRejected);
             }
             }
@@ -3268,7 +3268,7 @@
 
 
             var width = size.width || size;
             var width = size.width || size;
             var height = size.height || size;
             var height = size.height || size;
-            
+
             var textures = [];
             var textures = [];
             var attachments = []
             var attachments = []
 
 
@@ -3295,7 +3295,7 @@
 
 
                 var texture = new InternalTexture(this, InternalTexture.DATASOURCE_MULTIRENDERTARGET);
                 var texture = new InternalTexture(this, InternalTexture.DATASOURCE_MULTIRENDERTARGET);
                 var attachment = gl[this.webGLVersion > 1 ? "COLOR_ATTACHMENT" + i : "COLOR_ATTACHMENT" + i + "_WEBGL"];
                 var attachment = gl[this.webGLVersion > 1 ? "COLOR_ATTACHMENT" + i : "COLOR_ATTACHMENT" + i + "_WEBGL"];
-                
+
                 textures.push(texture);
                 textures.push(texture);
                 attachments.push(attachment);
                 attachments.push(attachment);
 
 
@@ -3548,7 +3548,7 @@
             return texture;
             return texture;
         }
         }
 
 
-        public createPrefilteredCubeTexture(rootUrl: string, scene: Scene, scale: number, offset: number, onLoad: (internalTexture: InternalTexture) => void, onError: () => void = null, format?: number, forcedExtension = null): InternalTexture {
+        public createPrefilteredCubeTexture(rootUrl: string, scene: Scene, scale: number, offset: number, onLoad: (internalTexture: InternalTexture) => void, onError: (message?: string, exception?: any) => void = null, format?: number, forcedExtension = null): InternalTexture {
             var callback = (loadData) => {
             var callback = (loadData) => {
                 if (!loadData) {
                 if (!loadData) {
                     if (onLoad) {
                     if (onLoad) {
@@ -3633,7 +3633,7 @@
             return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension);
             return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension);
         }
         }
 
 
-        public createCubeTexture(rootUrl: string, scene: Scene, files: string[], noMipmap?: boolean, onLoad: (data?: any) => void = null, onError: () => void = null, format?: number, forcedExtension = null): InternalTexture {
+        public createCubeTexture(rootUrl: string, scene: Scene, files: string[], noMipmap?: boolean, onLoad: (data?: any) => void = null, onError: (message?: string, exception?: any) => void = null, format?: number, forcedExtension = null): InternalTexture {
             var gl = this._gl;
             var gl = this._gl;
 
 
             var texture = new InternalTexture(this, InternalTexture.DATASOURCE_CUBE);
             var texture = new InternalTexture(this, InternalTexture.DATASOURCE_CUBE);
@@ -3658,6 +3658,12 @@
                 isDDS = (extension === ".dds");
                 isDDS = (extension === ".dds");
             }
             }
 
 
+            let onerror = (request, exception) => {
+                if (onError) {
+                    onError(request.status + " " + request.statusText, exception)
+                }
+            }
+
             if (isKTX) {
             if (isKTX) {
                 Tools.LoadFile(rootUrl, data => {
                 Tools.LoadFile(rootUrl, data => {
                     var ktx = new Internals.KhronosTextureContainer(data, 6);
                     var ktx = new Internals.KhronosTextureContainer(data, 6);
@@ -3681,7 +3687,7 @@
                     texture.width = ktx.pixelWidth;
                     texture.width = ktx.pixelWidth;
                     texture.height = ktx.pixelHeight;
                     texture.height = ktx.pixelHeight;
                     texture.isReady = true;
                     texture.isReady = true;
-                }, null, null, true, onError);
+                }, null, null, true, onerror);
             } else if (isDDS) {
             } else if (isDDS) {
                 Tools.LoadFile(rootUrl, data => {
                 Tools.LoadFile(rootUrl, data => {
                     var info = Internals.DDSTools.GetDDSInfo(data);
                     var info = Internals.DDSTools.GetDDSInfo(data);
@@ -3714,7 +3720,7 @@
                     if (onLoad) {
                     if (onLoad) {
                         onLoad({ isDDS: true, width: info.width, info, data, texture });
                         onLoad({ isDDS: true, width: info.width, info, data, texture });
                     }
                     }
-                }, null, null, true, onError);
+                }, null, null, true, onerror);
             } else {
             } else {
                 cascadeLoad(rootUrl, scene, imgs => {
                 cascadeLoad(rootUrl, scene, imgs => {
                     var width = this.needPOTTextures ? Tools.GetExponentOfTwo(imgs[0].width, this._caps.maxCubemapTextureSize) : imgs[0].width;
                     var width = this.needPOTTextures ? Tools.GetExponentOfTwo(imgs[0].width, this._caps.maxCubemapTextureSize) : imgs[0].width;
@@ -3889,7 +3895,7 @@
             callback: (ArrayBuffer: ArrayBuffer) => ArrayBufferView[],
             callback: (ArrayBuffer: ArrayBuffer) => ArrayBufferView[],
             mipmmapGenerator: ((faces: ArrayBufferView[]) => ArrayBufferView[][]),
             mipmmapGenerator: ((faces: ArrayBufferView[]) => ArrayBufferView[][]),
             onLoad: () => void = null,
             onLoad: () => void = null,
-            onError: () => void = null,
+            onError: (message?: string, exception?: any) => void = null,
             samplingMode = Texture.TRILINEAR_SAMPLINGMODE,
             samplingMode = Texture.TRILINEAR_SAMPLINGMODE,
             invertY = false): InternalTexture {
             invertY = false): InternalTexture {
 
 
@@ -3899,10 +3905,10 @@
             texture.url = url;
             texture.url = url;
             this._internalTexturesCache.push(texture);
             this._internalTexturesCache.push(texture);
 
 
-            var onerror = () => {
+            var onerror = (request, exception) => {
                 scene._removePendingData(texture);
                 scene._removePendingData(texture);
                 if (onError) {
                 if (onError) {
-                    onError();
+                    onError(request.status + " " + request.statusText, exception);
                 }
                 }
             };
             };
 
 
@@ -3956,7 +3962,7 @@
 
 
             Tools.LoadFile(url, data => {
             Tools.LoadFile(url, data => {
                 internalCallback(data);
                 internalCallback(data);
-            }, onerror, scene.database, true);
+            }, undefined, scene.database, true, onerror);
 
 
             return texture;
             return texture;
         };
         };
@@ -4208,7 +4214,7 @@
 
 
                 if (internalTexture._cachedWrapU !== texture.wrapU) {
                 if (internalTexture._cachedWrapU !== texture.wrapU) {
                     internalTexture._cachedWrapU = texture.wrapU;
                     internalTexture._cachedWrapU = texture.wrapU;
-                    
+
                     switch (texture.wrapU) {
                     switch (texture.wrapU) {
                         case Texture.WRAP_ADDRESSMODE:
                         case Texture.WRAP_ADDRESSMODE:
                             this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, this._gl.REPEAT);
                             this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, this._gl.REPEAT);
@@ -4270,7 +4276,7 @@
             var value = texture.anisotropicFilteringLevel;
             var value = texture.anisotropicFilteringLevel;
 
 
 
 
-            if (internalTexture.samplingMode !== Texture.LINEAR_LINEAR_MIPNEAREST 
+            if (internalTexture.samplingMode !== Texture.LINEAR_LINEAR_MIPNEAREST
                 && internalTexture.samplingMode !== Texture.LINEAR_LINEAR_MIPLINEAR
                 && internalTexture.samplingMode !== Texture.LINEAR_LINEAR_MIPLINEAR
                 && internalTexture.samplingMode !== Texture.LINEAR_LINEAR) {
                 && internalTexture.samplingMode !== Texture.LINEAR_LINEAR) {
                 value = 1; // Forcing the anisotropic to 1 because else webgl will force filters to linear
                 value = 1; // Forcing the anisotropic to 1 because else webgl will force filters to linear
@@ -4429,7 +4435,7 @@
             window.removeEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted);
             window.removeEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted);
             window.removeEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted);
             window.removeEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted);
             this._renderingCanvas.removeEventListener("focus", this._onCanvasFocus);
             this._renderingCanvas.removeEventListener("focus", this._onCanvasFocus);
-            this._renderingCanvas.removeEventListener("blur", this._onCanvasBlur);            
+            this._renderingCanvas.removeEventListener("blur", this._onCanvasBlur);
             this._renderingCanvas.removeEventListener("pointerout", this._onCanvasBlur);
             this._renderingCanvas.removeEventListener("pointerout", this._onCanvasBlur);
 
 
             if (!this._doNotHandleContextLost) {
             if (!this._doNotHandleContextLost) {
@@ -4444,13 +4450,13 @@
             document.removeEventListener("mspointerlockchange", this._onPointerLockChange);
             document.removeEventListener("mspointerlockchange", this._onPointerLockChange);
             document.removeEventListener("mozpointerlockchange", this._onPointerLockChange);
             document.removeEventListener("mozpointerlockchange", this._onPointerLockChange);
             document.removeEventListener("webkitpointerlockchange", this._onPointerLockChange);
             document.removeEventListener("webkitpointerlockchange", this._onPointerLockChange);
-            
+
             if (this._onVrDisplayConnect) {
             if (this._onVrDisplayConnect) {
                 window.removeEventListener('vrdisplayconnect', this._onVrDisplayConnect);
                 window.removeEventListener('vrdisplayconnect', this._onVrDisplayConnect);
                 window.removeEventListener('vrdisplaydisconnect', this._onVrDisplayDisconnect);
                 window.removeEventListener('vrdisplaydisconnect', this._onVrDisplayDisconnect);
                 window.removeEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
                 window.removeEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
                 this._onVrDisplayConnect = undefined;
                 this._onVrDisplayConnect = undefined;
-                this._onVrDisplayDisconnect = undefined;                
+                this._onVrDisplayDisconnect = undefined;
             }
             }
 
 
             // Remove from Instances
             // Remove from Instances