Pārlūkot izejas kodu

Merge pull request #2986 from BabylonJS/strctCheckNull

Strict check null
David Catuhe 7 gadi atpakaļ
vecāks
revīzija
580d122c02
37 mainītis faili ar 25264 papildinājumiem un 24285 dzēšanām
  1. 1 0
      Tools/Gulp/config.json
  2. 0 9
      Tools/Gulp/gulpfile.js
  3. 0 1
      Tools/Gulp/package.json
  4. 10213 10210
      dist/preview release/babylon.d.ts
  5. 43 43
      dist/preview release/babylon.js
  6. 546 240
      dist/preview release/babylon.max.js
  7. 10213 10210
      dist/preview release/babylon.module.d.ts
  8. 44 44
      dist/preview release/babylon.worker.js
  9. 1368 1365
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  10. 43 43
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  11. 546 240
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  12. 1368 1365
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  13. 3 3
      src/Actions/babylon.action.ts
  14. 21 19
      src/Actions/babylon.actionManager.ts
  15. 8 5
      src/Animations/babylon.animatable.ts
  16. 41 20
      src/Animations/babylon.animation.ts
  17. 1 1
      src/Animations/babylon.runtimeAnimation.ts
  18. 31 20
      src/Cameras/babylon.camera.ts
  19. 9 4
      src/Cameras/babylon.followCamera.ts
  20. 230 109
      src/Engine/babylon.engine.ts
  21. 43 23
      src/Materials/Textures/babylon.baseTexture.ts
  22. 21 19
      src/Materials/Textures/babylon.internalTexture.ts
  23. 93 27
      src/Materials/Textures/babylon.renderTargetTexture.ts
  24. 56 19
      src/Materials/Textures/babylon.texture.ts
  25. 5 5
      src/Materials/babylon.uniformBuffer.ts
  26. 1 1
      src/Mesh/babylon.abstractMesh.ts
  27. 2 2
      src/PostProcess/babylon.passPostProcess.ts
  28. 15 13
      src/PostProcess/babylon.postProcess.ts
  29. 1 1
      src/PostProcess/babylon.postProcessManager.ts
  30. 21 17
      src/Rendering/babylon.renderingGroup.ts
  31. 13 13
      src/Rendering/babylon.renderingManager.ts
  32. 27 19
      src/Tools/babylon.database.ts
  33. 42 26
      src/Tools/babylon.tools.ts
  34. 2 3
      src/babylon.mixins.ts
  35. 18 12
      src/babylon.node.ts
  36. 172 134
      src/babylon.scene.ts
  37. 3 0
      src/babylon.types.ts

+ 1 - 0
Tools/Gulp/config.json

@@ -160,6 +160,7 @@
     "workloads": {
         "core": {
             "files": [
+                "../../src/babylon.types.js",
                 "../../src/Events/babylon.keyboardEvents.js",
                 "../../src/Events/babylon.pointerEvents.js",
                 "../../src/Math/babylon.math.js",

+ 0 - 9
Tools/Gulp/gulpfile.js

@@ -21,8 +21,6 @@ var path = require('path');
 var sass = require('gulp-sass');
 var webpack = require('webpack-stream');
 
-var zip = require('gulp-zip');
-
 var config = require("./config.json");
 
 var del = require('del');
@@ -518,13 +516,6 @@ gulp.task('webserver', function () {
 gulp.task('run', ['watch', 'webserver'], function () {
 });
 
-
-gulp.task("zip-blender", function () {
-    return gulp.src('../../Exporters/Blender/src/**')
-        .pipe(zip('Blender2Babylon-5.4.zip'))
-        .pipe(gulp.dest('../../Exporters/Blender'));
-});
-
 gulp.task('clean-JS-MAP', function () {
     return del([
         '../../src/**/*.js.map', '../../src/**/*.js'

+ 0 - 1
Tools/Gulp/package.json

@@ -32,7 +32,6 @@
     "style-loader": "^0.13.1",
     "exports-loader": "^0.6.3",
     "imports-loader": "^0.7.0",
-    "gulp-zip": "~3.2.0",
     "del": "2.2.2"
   },
   "scripts": {

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 10213 - 10210
dist/preview release/babylon.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 43 - 43
dist/preview release/babylon.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 546 - 240
dist/preview release/babylon.max.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 10213 - 10210
dist/preview release/babylon.module.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 44 - 44
dist/preview release/babylon.worker.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1368 - 1365
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 43 - 43
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 546 - 240
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1368 - 1365
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


+ 3 - 3
src/Actions/babylon.action.ts

@@ -5,7 +5,7 @@
 
         private _nextActiveAction: Action;
         private _child: Action;
-        private _condition: Condition;
+        private _condition?: Condition;
         private _triggerParameter: any;
 
         public onBeforeExecuteObservable = new Observable<Action>();
@@ -31,7 +31,7 @@
             return this._triggerParameter;
         }
 
-        public _executeCurrent(evt: ActionEvent): void {
+        public _executeCurrent(evt?: ActionEvent): void {
             if (this._nextActiveAction._condition) {
                 var condition = this._nextActiveAction._condition;
                 var currentRenderId = this._actionManager.getScene().getRenderId();
@@ -59,7 +59,7 @@
             this.skipToNextActiveAction();
         }
 
-        public execute(evt: ActionEvent): void {
+        public execute(evt?: ActionEvent): void {
 
         }
 

+ 21 - 19
src/Actions/babylon.actionManager.ts

@@ -11,7 +11,7 @@
          * @param meshUnderPointer The mesh that is currently pointed at (can be null)
          * @param sourceEvent the original (browser) event that triggered the ActionEvent
          */
-        constructor(public source: any, public pointerX: number, public pointerY: number, public meshUnderPointer: AbstractMesh, public sourceEvent?: any, public additionalData?: any) {
+        constructor(public source: any, public pointerX: number, public pointerY: number, public meshUnderPointer: Nullable<AbstractMesh>, public sourceEvent?: any, public additionalData?: any) {
 
         }
 
@@ -295,7 +295,7 @@
          * @param {BABYLON.Action} action - the action to be registered
          * @return {BABYLON.Action} the action amended (prepared) after registration
          */
-        public registerAction(action: Action): Action {
+        public registerAction(action: Action): Nullable<Action> {
             if (action.trigger === ActionManager.OnEveryFrameTrigger) {
                 if (this.getScene().actionManager !== this) {
                     Tools.Warn("OnEveryFrameTrigger can only be used with scene.actionManager");
@@ -323,27 +323,29 @@
          * @param {number} trigger - the trigger to process
          * @param evt {BABYLON.ActionEvent} the event details to be processed
          */
-        public processTrigger(trigger: number, evt: ActionEvent): void {
+        public processTrigger(trigger: number, evt?: ActionEvent): void {
             for (var index = 0; index < this.actions.length; index++) {
                 var action = this.actions[index];
 
                 if (action.trigger === trigger) {
-                    if (trigger === ActionManager.OnKeyUpTrigger
-                        || trigger === ActionManager.OnKeyDownTrigger) {
-                        var parameter = action.getTriggerParameter();
+                    if (evt) {
+                        if (trigger === ActionManager.OnKeyUpTrigger
+                            || trigger === ActionManager.OnKeyDownTrigger) {
+                            var parameter = action.getTriggerParameter();
 
-                        if (parameter && parameter !== evt.sourceEvent.keyCode) {
-                            if (!parameter.toLowerCase) {
-                                continue;
-                            }
-                            var lowerCase = parameter.toLowerCase();
-
-                            if (lowerCase !== evt.sourceEvent.key) {
-                                var unicode = evt.sourceEvent.charCode ? evt.sourceEvent.charCode : evt.sourceEvent.keyCode;
-                                var actualkey = String.fromCharCode(unicode).toLowerCase();
-                                if (actualkey !== lowerCase) {
+                            if (parameter && parameter !== evt.sourceEvent.keyCode) {
+                                if (!parameter.toLowerCase) {
                                     continue;
                                 }
+                                var lowerCase = parameter.toLowerCase();
+
+                                if (lowerCase !== evt.sourceEvent.key) {
+                                    var unicode = evt.sourceEvent.charCode ? evt.sourceEvent.charCode : evt.sourceEvent.keyCode;
+                                    var actualkey = String.fromCharCode(unicode).toLowerCase();
+                                    if (actualkey !== lowerCase) {
+                                        continue;
+                                    }
+                                }
                             }
                         }
                     }
@@ -427,7 +429,7 @@
                 return newInstance;
             };
 
-            var parseParameter = (name: string, value: string, target: any, propertyPath: string): any => {
+            var parseParameter = (name: string, value: string, target: any, propertyPath: Nullable<string>): any => {
                 if (propertyPath === null) {
                     // String, boolean or float
                     var floatValue = parseFloat(value);
@@ -474,13 +476,13 @@
             };
 
             // traverse graph per trigger
-            var traverse = (parsedAction: any, trigger: any, condition: Condition, action: Action, combineArray: Array<Action> = null) => {
+            var traverse = (parsedAction: any, trigger: any, condition: Nullable<Condition>, action: Nullable<Action>, combineArray: Nullable<Array<Action>> = null) => {
                 if (parsedAction.detached)
                     return;
 
                 var parameters = new Array<any>();
                 var target: any = null;
-                var propertyPath: string = null;
+                var propertyPath: Nullable<string> = null;
                 var combine = parsedAction.combine && parsedAction.combine.length > 0;
 
                 // Parameters

+ 8 - 5
src/Animations/babylon.animatable.ts

@@ -1,7 +1,7 @@
 module BABYLON {
     export class Animatable {
-        private _localDelayOffset: number = null;
-        private _pausedDelay: number = null;
+        private _localDelayOffset: Nullable<number> = null;
+        private _pausedDelay: Nullable<number> = null;
         private _runtimeAnimations = new Array<RuntimeAnimation>();
         private _paused = false;
         private _scene: Scene;
@@ -22,7 +22,7 @@
             this._speedRatio = value;
         }
 
-        constructor(scene: Scene, public target: any, public fromFrame: number = 0, public toFrame: number = 100, public loopAnimation: boolean = false, speedRatio: number = 1.0, public onAnimationEnd?: () => void, animations?: any) {
+        constructor(scene: Scene, public target: any, public fromFrame: number = 0, public toFrame: number = 100, public loopAnimation: boolean = false, speedRatio: number = 1.0, public onAnimationEnd?: Nullable<() => void>, animations?: any) {
             if (animations) {
                 this.appendAnimations(target, animations);
             }
@@ -45,7 +45,7 @@
             }
         }
 
-        public getAnimationByTargetProperty(property: string): Animation {
+        public getAnimationByTargetProperty(property: string): Nullable<Animation> {
             var runtimeAnimations = this._runtimeAnimations;
 
             for (var index = 0; index < runtimeAnimations.length; index++) {
@@ -57,7 +57,7 @@
             return null;
         }
 
-        public getRuntimeAnimationByTargetProperty(property: string): RuntimeAnimation {
+        public getRuntimeAnimationByTargetProperty(property: string): Nullable<RuntimeAnimation> {
             var runtimeAnimations = this._runtimeAnimations;
 
             for (var index = 0; index < runtimeAnimations.length; index++) {
@@ -105,6 +105,9 @@
                 var currentFrame = runtimeAnimations[0].currentFrame;
                 var adjustTime = frame - currentFrame;
                 var delay = adjustTime * 1000 / fps;
+                if (this._localDelayOffset === null) {
+                    this._localDelayOffset = 0;
+                }
                 this._localDelayOffset -= delay;
             }
 

+ 41 - 20
src/Animations/babylon.animation.ts

@@ -96,10 +96,10 @@
 
         public blendingSpeed = 0.01;
 
-        private _ranges: { [name: string]: AnimationRange; } = {};
+        private _ranges: { [name: string]: Nullable<AnimationRange> } = {};
 
         static _PrepareAnimation(name: string, targetProperty: string, framePerSecond: number, totalFrame: number,
-            from: any, to: any, loopMode?: number, easingFunction?: EasingFunction): Animation {
+            from: any, to: any, loopMode?: number, easingFunction?: EasingFunction): Nullable<Animation> {
             var dataType = undefined;
 
             if (!isNaN(parseFloat(from)) && isFinite(from)) {
@@ -153,19 +153,27 @@
 
         public static CreateAndStartAnimation(name: string, node: Node, targetProperty: string,
             framePerSecond: number, totalFrame: number,
-            from: any, to: any, loopMode?: number, easingFunction?: EasingFunction, onAnimationEnd?: () => void) {
+            from: any, to: any, loopMode?: number, easingFunction?: EasingFunction, onAnimationEnd?: () => void): Nullable<Animatable> {
 
             var animation = Animation._PrepareAnimation(name, targetProperty, framePerSecond, totalFrame, from, to, loopMode, easingFunction);
 
+            if (!animation) {
+                return null;
+            }
+
             return node.getScene().beginDirectAnimation(node, [animation], 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
         }
 
         public static CreateMergeAndStartAnimation(name: string, node: Node, targetProperty: string,
             framePerSecond: number, totalFrame: number,
-            from: any, to: any, loopMode?: number, easingFunction?: EasingFunction, onAnimationEnd?: () => void) {
+            from: any, to: any, loopMode?: number, easingFunction?: EasingFunction, onAnimationEnd?: () => void): Nullable<Animatable> {
 
             var animation = Animation._PrepareAnimation(name, targetProperty, framePerSecond, totalFrame, from, to, loopMode, easingFunction);
 
+            if (!animation) {
+                return null;
+            }
+
             node.animations.push(animation);
 
             return node.getScene().beginAnimation(node, 0, totalFrame, (animation.loopMode === 1), 1.0, onAnimationEnd);
@@ -182,7 +190,7 @@
 		 * @param duration The duration of the animation, in milliseconds
 		 * @param onAnimationEnd Call back trigger at the end of the animation.
 		 */
-		public static TransitionTo(property: string, targetValue: any, host: any, scene: Scene, frameRate: number, transition: Animation, duration: number,	onAnimationEnd: () => void = null): Animatable {
+		public static TransitionTo(property: string, targetValue: any, host: any, scene: Scene, frameRate: number, transition: Animation, duration: number,	onAnimationEnd: Nullable<() => void> = null): Nullable<Animatable> {
 
 			if (duration <= 0) {
 				host[property] = targetValue;
@@ -293,23 +301,27 @@
         }
 
         public deleteRange(name: string, deleteFrames = true): void {
-            if (this._ranges[name]) {
-                if (deleteFrames) {
-                    var from = this._ranges[name].from;
-                    var to = this._ranges[name].to;
- 
-                    // this loop MUST go high to low for multiple splices to work
-                    for (var key = this._keys.length - 1; key >= 0; key--) {
-                        if (this._keys[key].frame >= from && this._keys[key].frame <= to) {
-                            this._keys.splice(key, 1);
-                        }
+            let range = this._ranges[name];
+            if (!range) {
+                return;
+
+            }
+            if (deleteFrames) {
+                var from = range.from;
+                var to = range.to;
+
+                // this loop MUST go high to low for multiple splices to work
+                for (var key = this._keys.length - 1; key >= 0; key--) {
+                    if (this._keys[key].frame >= from && this._keys[key].frame <= to) {
+                        this._keys.splice(key, 1);
                     }
                 }
-                this._ranges[name] = undefined; // said much faster than 'delete this._range[name]' 
             }
+            this._ranges[name] = null; // said much faster than 'delete this._range[name]' 
+        
         }
 
-        public getRange(name: string): AnimationRange {
+        public getRange(name: string): Nullable<AnimationRange> {
             return this._ranges[name];
         }
 
@@ -394,7 +406,11 @@
             if (this._ranges) {
                 clone._ranges = {};
                 for (var name in this._ranges) {
-                    clone._ranges[name] = this._ranges[name].clone();
+                    let range = this._ranges[name];
+                    if (!range) {
+                        continue;
+                    }
+                    clone._ranges[name] = range.clone();
                 }
             }
 
@@ -442,10 +458,15 @@
 
             serializationObject.ranges = [];
             for (var name in this._ranges) {
+                let source  =this._ranges[name];
+
+                if (!source) {
+                    continue;
+                }
                 var range: any = {};
                 range.name = name;
-                range.from = this._ranges[name].from;
-                range.to = this._ranges[name].to;
+                range.from = source.from;
+                range.to = source.to;
                 serializationObject.ranges.push(range);
             }
 

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

@@ -50,7 +50,7 @@
             return value;
         }      
         
-        private _interpolate(currentFrame: number, repeatCount: number, loopMode: number, offsetValue?: any, highLimitValue?: any) {
+        private _interpolate(currentFrame: number, repeatCount: number, loopMode?: number, offsetValue?: any, highLimitValue?: any) {
             if (loopMode === Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) {
                 return highLimitValue.clone ? highLimitValue.clone() : highLimitValue;
             }

+ 31 - 20
src/Cameras/babylon.camera.ts

@@ -73,16 +73,16 @@
         public upVector = Vector3.Up();
 
         @serialize()
-        public orthoLeft: number = null;
+        public orthoLeft: Nullable<number> = null;
 
         @serialize()
-        public orthoRight: number = null;
+        public orthoRight: Nullable<number> = null;
 
         @serialize()
-        public orthoBottom: number = null;
+        public orthoBottom: Nullable<number> = null;
 
         @serialize()
-        public orthoTop: number = null;
+        public orthoTop: Nullable<number> = null;
 
         @serialize()
         public fov = 0.8;
@@ -120,7 +120,7 @@
 
         public _cameraRigParams: any;
         public _rigCameras = new Array<Camera>();
-        public _rigPostProcess: PostProcess;
+        public _rigPostProcess: Nullable<PostProcess>;
         protected _webvrViewMatrix = Matrix.Identity();
         public _skipRendering = false;
         public _alternateCamera: Camera;
@@ -325,7 +325,7 @@
             return this._rigCameras;
         }
 
-        public get rigPostProcess(): PostProcess {
+        public get rigPostProcess(): Nullable<PostProcess> {
             return this._rigPostProcess;
         }
 
@@ -356,7 +356,7 @@
             }
         }
 
-        public attachPostProcess(postProcess: PostProcess, insertAt: number = null): number {
+        public attachPostProcess(postProcess: PostProcess, insertAt: Nullable<number> = null): number {
             if (!postProcess.isReusable() && this._postProcesses.indexOf(postProcess) > -1) {
                 Tools.Error("You're trying to reuse a post process not defined as reusable.");
                 return 0;
@@ -603,7 +603,10 @@
             // Remove from scene
             this.getScene().removeCamera(this);
             while (this._rigCameras.length > 0) {
-                this._rigCameras.pop().dispose();
+                let camera = this._rigCameras.pop();
+                if (camera) {
+                    camera.dispose();
+                }                
             }
 
             // Postprocesses
@@ -636,30 +639,30 @@
         }
 
         // ---- Camera rigs section ----
-        public get leftCamera(): FreeCamera {
+        public get leftCamera(): Nullable<FreeCamera> {
             if (this._rigCameras.length < 1) {
-                return undefined;
+                return null;
             }
             return (<FreeCamera>this._rigCameras[0]);
         }
 
-        public get rightCamera(): FreeCamera {
+        public get rightCamera(): Nullable<FreeCamera> {
             if (this._rigCameras.length < 2) {
-                return undefined;
+                return null;
             }
             return (<FreeCamera>this._rigCameras[1]);
         }
 
-        public getLeftTarget(): Vector3 {
+        public getLeftTarget(): Nullable<Vector3> {
             if (this._rigCameras.length < 1) {
-                return undefined;
+                return null;
             }
             return (<TargetCamera>this._rigCameras[0]).getTarget();
         }
 
-        public getRightTarget(): Vector3 {
+        public getRightTarget(): Nullable<Vector3> {
             if (this._rigCameras.length < 2) {
-                return undefined;
+                return null;
             }
             return (<TargetCamera>this._rigCameras[1]).getTarget();
         }
@@ -670,7 +673,11 @@
             }
 
             while (this._rigCameras.length > 0) {
-                this._rigCameras.pop().dispose();
+                let camera = this._rigCameras.pop();
+
+                if (camera) {
+                    camera.dispose();
+                }
             }
             this.cameraRigMode = mode;
             this._cameraRigParams = {};
@@ -681,8 +688,12 @@
 
             // create the rig cameras, unless none
             if (this.cameraRigMode !== Camera.RIG_MODE_NONE) {
-                this._rigCameras.push(this.createRigCamera(this.name + "_L", 0));
-                this._rigCameras.push(this.createRigCamera(this.name + "_R", 1));
+                let leftCamera = this.createRigCamera(this.name + "_L", 0);
+                let rightCamera = this.createRigCamera(this.name + "_R", 1);
+                if (leftCamera && rightCamera) {
+                    this._rigCameras.push(leftCamera);
+                    this._rigCameras.push(rightCamera);
+                }
             }
 
             switch (this.cameraRigMode) {
@@ -808,7 +819,7 @@
         /**
          * needs to be overridden by children so sub has required properties to be copied
          */
-        public createRigCamera(name: string, cameraIndex: number): Camera {
+        public createRigCamera(name: string, cameraIndex: number): Nullable<Camera> {
             return null;
         }
 

+ 9 - 4
src/Cameras/babylon.followCamera.ts

@@ -18,9 +18,9 @@ module BABYLON {
         public maxCameraSpeed: number = 20;
 
         @serializeAsMeshReference("lockedTargetId")
-        public lockedTarget: AbstractMesh;
+        public lockedTarget: Nullable<AbstractMesh>;
 
-        constructor(name: string, position: Vector3, scene: Scene, lockedTarget?: AbstractMesh) {
+        constructor(name: string, position: Vector3, scene: Scene, lockedTarget: Nullable<AbstractMesh> = null) {
             super(name, position, scene);
 
             this.lockedTarget = lockedTarget;
@@ -72,7 +72,9 @@ module BABYLON {
 
         public _checkInputs(): void {
             super._checkInputs();
-            this.follow(this.lockedTarget);
+            if (this.lockedTarget) {
+                this.follow(this.lockedTarget);
+            }
         }
 
         public getClassName(): string {
@@ -84,12 +86,15 @@ module BABYLON {
 
         private _cartesianCoordinates: Vector3 = Vector3.Zero();
 
-        constructor(name: string, public alpha: number, public beta: number, public radius: number, public target: AbstractMesh, scene: Scene) {
+        constructor(name: string, public alpha: number, public beta: number, public radius: number, public target: Nullable<AbstractMesh>, scene: Scene) {
             super(name, Vector3.Zero(), scene);
             this.follow();
         }
 
         private follow(): void {
+            if (!this.target) {
+                return;
+            }
             this._cartesianCoordinates.x = this.radius * Math.cos(this.alpha) * Math.cos(this.beta);
             this._cartesianCoordinates.y = this.radius * Math.sin(this.beta);
             this._cartesianCoordinates.z = this.radius * Math.sin(this.alpha) * Math.cos(this.beta);

+ 230 - 109
src/Engine/babylon.engine.ts

@@ -10,8 +10,16 @@
         gl.compileShader(shader);
 
         if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
-            throw new Error(gl.getShaderInfoLog(shader));
+            let log = gl.getShaderInfoLog(shader);
+            if (log) {
+                throw new Error(log);
+            }
+        }
+
+        if (!shader) {
+            throw new Error("Something went wrong while compile the shader.");
         }
+
         return shader;
     };
 
@@ -108,8 +116,8 @@
         }
     }
 
-    var partialLoad = (url: string, index: number, loadedImages: any, scene: Scene,
-        onfinish: (images: HTMLImageElement[]) => void, onErrorCallBack: (message?: string, exception?: any) => void = null) => {
+    var partialLoad = (url: string, index: number, loadedImages: any, scene: Nullable<Scene>,
+        onfinish: (images: HTMLImageElement[]) => void, onErrorCallBack: Nullable<(message?: string, exception?: any) => void> = null) => {
 
         var img: HTMLImageElement;
 
@@ -142,8 +150,8 @@
         }
     }
 
-    var cascadeLoad = (rootUrl: string, scene: Scene,
-        onfinish: (images: HTMLImageElement[]) => void, files: string[], onError: (message?: string, exception?: any) => void = null) => {
+    var cascadeLoad = (rootUrl: string, scene: Nullable<Scene>,
+        onfinish: (images: HTMLImageElement[]) => void, files: string[], onError: Nullable<(message?: string, exception?: any) => void> = null) => {
 
         var loadedImages: any = [];
         loadedImages._internalCount = 0;
@@ -269,7 +277,7 @@
     export class Engine {
         public static Instances = new Array<Engine>();
 
-        public static get LastCreatedEngine(): Engine {
+        public static get LastCreatedEngine(): Nullable<Engine> {
             if (Engine.Instances.length === 0) {
                 return null;
             }
@@ -277,7 +285,7 @@
             return Engine.Instances[Engine.Instances.length - 1];
         }
 
-        public static get LastCreatedScene(): Scene {
+        public static get LastCreatedScene(): Nullable<Scene> {
             var lastCreatedEngine = Engine.LastCreatedEngine;
             if (!lastCreatedEngine) {
                 return null;
@@ -589,7 +597,7 @@
 
         // Private Members
         private _gl: WebGLRenderingContext;
-        private _renderingCanvas: HTMLCanvasElement;
+        private _renderingCanvas: Nullable<HTMLCanvasElement>;
         private _windowIsBackground = false;
         private _webGLVersion = 1.0;
 
@@ -624,9 +632,9 @@
         private _onVRDisplayPointerUnrestricted: () => void;
 
         // VRDisplay connection
-        private _onVrDisplayConnect: (display: any) => void;
-        private _onVrDisplayDisconnect: () => void;
-        private _onVrDisplayPresentChange: () => void;
+        private _onVrDisplayConnect: Nullable<(display: any) => void>;
+        private _onVrDisplayDisconnect: Nullable<() => void>;
+        private _onVrDisplayPresentChange: Nullable<() => void>;
         public onVRDisplayChangedObservable = new Observable<IDisplayChangedEventArgs>();
         public onVRRequestPresentComplete = new Observable<boolean>();
         public onVRRequestPresentStart = new Observable<Engine>();
@@ -685,27 +693,27 @@
         // Cache
         private _internalTexturesCache = new Array<InternalTexture>();
         protected _activeTexture: number;
-        protected _activeTexturesCache: { [key: string]: WebGLTexture } = {};
-        protected _currentEffect: Effect;
-        protected _currentProgram: WebGLProgram;
+        protected _activeTexturesCache: { [key: string]: Nullable<WebGLTexture> } = {};
+        protected _currentEffect: Nullable<Effect>;
+        protected _currentProgram: Nullable<WebGLProgram>;
         private _compiledEffects: { [key: string]: Effect } = {}
         private _vertexAttribArraysEnabled: boolean[] = [];
-        protected _cachedViewport: Viewport;
-        private _cachedVertexArrayObject: WebGLVertexArrayObject;
+        protected _cachedViewport: Nullable<Viewport>;
+        private _cachedVertexArrayObject: Nullable<WebGLVertexArrayObject>;
         protected _cachedVertexBuffers: any;
-        protected _cachedIndexBuffer: WebGLBuffer;
-        protected _cachedEffectForVertexBuffers: Effect;
-        protected _currentRenderTarget: InternalTexture;
+        protected _cachedIndexBuffer: Nullable<WebGLBuffer>;
+        protected _cachedEffectForVertexBuffers: Nullable<Effect>;
+        protected _currentRenderTarget: Nullable<InternalTexture>;
         private _uintIndicesCurrentlySet = false;
-        private _currentBoundBuffer = new Array<WebGLBuffer>();
-        protected _currentFramebuffer: WebGLFramebuffer;
+        private _currentBoundBuffer = new Array<Nullable<WebGLBuffer>>();
+        protected _currentFramebuffer: Nullable<WebGLFramebuffer>;
         private _currentBufferPointers = new Array<BufferPointer>();
         private _currentInstanceLocations = new Array<number>();
         private _currentInstanceBuffers = new Array<WebGLBuffer>();
         private _textureUnits: Int32Array;
 
-        private _workingCanvas: HTMLCanvasElement;
-        private _workingContext: CanvasRenderingContext2D;
+        private _workingCanvas: Nullable<HTMLCanvasElement>;
+        private _workingContext: Nullable<CanvasRenderingContext2D>;
         private _rescalePostProcess: PassPostProcess;
 
         private _dummyFramebuffer: WebGLFramebuffer;
@@ -716,24 +724,24 @@
         private _vaoRecordInProgress = false;
         private _mustWipeVertexAttributes = false;
 
-        private _emptyTexture: InternalTexture;
-        private _emptyCubeTexture: InternalTexture;
+        private _emptyTexture: Nullable<InternalTexture>;
+        private _emptyCubeTexture: Nullable<InternalTexture>;
 
         private _frameHandler: number;
 
         // Hardware supported Compressed Textures
         private _texturesSupported = new Array<string>();
-        private _textureFormatInUse: string;
+        private _textureFormatInUse: Nullable<string>;
 
         public get texturesSupported(): Array<string> {
             return this._texturesSupported;
         }
 
-        public get textureFormatInUse(): string {
+        public get textureFormatInUse(): Nullable<string> {
             return this._textureFormatInUse;
         }
 
-        public get currentViewport(): Viewport {
+        public get currentViewport(): Nullable<Viewport> {
             return this._cachedViewport;
         }
 
@@ -762,7 +770,7 @@
          * @param options - further options to be sent to the getContext function
          */
         constructor(canvasOrContext: HTMLCanvasElement | WebGLRenderingContext, antialias?: boolean, options?: EngineOptions, adaptToDeviceRatio = false) {
-            var canvas: HTMLCanvasElement;
+            let canvas: Nullable<HTMLCanvasElement> = null;
             Engine.Instances.push(this);
 
             if (!canvasOrContext) {
@@ -801,7 +809,7 @@
 
                 this._deterministicLockstep = options.deterministicLockstep;
                 this._lockstepMaxSteps = options.lockstepMaxSteps;
-                this._doNotHandleContextLost = options.doNotHandleContextLost;
+                this._doNotHandleContextLost = options.doNotHandleContextLost ? true : false;
 
                 // GL
                 if (!options.disableWebGL2Support) {
@@ -919,7 +927,7 @@
             this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, window.devicePixelRatio || 1.0) : 1.0;
             this.resize();
 
-            this._isStencilEnable = options.stencil;
+            this._isStencilEnable = options.stencil ? true : false;
             this._initGLContext();
 
             if (canvas) {
@@ -936,7 +944,7 @@
                     }
 
                     // Pointer lock
-                    if (this.isFullscreen && this._pointerLockRequested) {
+                    if (this.isFullscreen && this._pointerLockRequested && canvas) {
                         canvas.requestPointerLock = canvas.requestPointerLock ||
                             canvas.msRequestPointerLock ||
                             canvas.mozRequestPointerLock ||
@@ -968,7 +976,9 @@
                 document.addEventListener("webkitpointerlockchange", this._onPointerLockChange, false);
 
                 this._onVRDisplayPointerRestricted = () => {
-                    canvas.requestPointerLock();
+                    if (canvas) {
+                        canvas.requestPointerLock();
+                    }
                 }
 
                 this._onVRDisplayPointerUnrestricted = () => {
@@ -1178,7 +1188,10 @@
 
             if (this._gl.getShaderPrecisionFormat) {
                 var highp = this._gl.getShaderPrecisionFormat(this._gl.FRAGMENT_SHADER, this._gl.HIGH_FLOAT);
-                this._caps.highPrecisionShaderSupported = highp.precision !== 0;
+
+                if (highp) {
+                    this._caps.highPrecisionShaderSupported = highp.precision !== 0;
+                }
             }
 
             // Depth buffer
@@ -1204,7 +1217,11 @@
             }
 
             this._workingCanvas = document.createElement("canvas");
-            this._workingContext = this._workingCanvas.getContext("2d");
+            let context = this._workingCanvas.getContext("2d");
+
+            if (context) {
+                this._workingContext = context;
+            }
         }
 
         public resetTextureCache() {
@@ -1250,11 +1267,14 @@
             return this._gl.drawingBufferHeight;
         }
 
-        public getRenderingCanvas(): HTMLCanvasElement {
+        public getRenderingCanvas(): Nullable<HTMLCanvasElement> {
             return this._renderingCanvas;
         }
 
-        public getRenderingCanvasClientRect(): ClientRect {
+        public getRenderingCanvasClientRect(): Nullable<ClientRect> {
+            if (!this._renderingCanvas) {
+                return null;
+            }
             return this._renderingCanvas.getBoundingClientRect();
         }
 
@@ -1462,11 +1482,13 @@
                 Tools.ExitFullscreen();
             } else {
                 this._pointerLockRequested = requestPointerLock;
-                Tools.RequestFullscreen(this._renderingCanvas);
+                if (this._renderingCanvas) {
+                    Tools.RequestFullscreen(this._renderingCanvas);
+                }
             }
         }
 
-        public clear(color: Color4, backBuffer: boolean, depth: boolean, stencil: boolean = false): void {
+        public clear(color: Nullable<Color4>, backBuffer: boolean, depth: boolean, stencil: boolean = false): void {
             this.applyStates();
 
             var mode = 0;
@@ -1531,7 +1553,7 @@
          * The x, y, width & height are directly passed to the WebGL call
          * @return the current viewport Object (if any) that is being replaced by this call. You can restore this viewport later on to go back to the original state.
          */
-        public setDirectViewport(x: number, y: number, width: number, height: number): Viewport {
+        public setDirectViewport(x: number, y: number, width: number, height: number): Nullable<Viewport> {
             let currentViewport = this._cachedViewport;
             this._cachedViewport = null;
 
@@ -1567,8 +1589,8 @@
         public resize(): void {
             // We're not resizing the size of the canvas while in VR mode & presenting
             if (!(this._vrDisplay && this._vrDisplay.isPresenting)) {
-                var width = navigator.isCocoonJS ? window.innerWidth : this._renderingCanvas.clientWidth;
-                var height = navigator.isCocoonJS ? window.innerHeight : this._renderingCanvas.clientHeight;
+                var width = this._renderingCanvas ? this._renderingCanvas.clientWidth : window.innerWidth;
+                var height = this._renderingCanvas ? this._renderingCanvas.clientHeight : window.innerHeight;
 
                 this.setSize(width / this._hardwareScalingLevel, height / this._hardwareScalingLevel);
             }
@@ -1580,6 +1602,10 @@
          * @param {number} height - the new canvas' height
          */
         public setSize(width: number, height: number): void {
+            if (!this._renderingCanvas) {
+                return;
+            }
+
             if (this._renderingCanvas.width === width && this._renderingCanvas.height === height) {
                 return;
             }
@@ -1712,6 +1738,9 @@
             this.bindUnboundFramebuffer(texture._MSAAFramebuffer ? texture._MSAAFramebuffer : texture._framebuffer);
             var gl = this._gl;
             if (texture.isCube) {
+                if (faceIndex === undefined) {
+                    faceIndex = 0;
+                }
                 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture._webGLTexture, 0);
             }
 
@@ -1724,7 +1753,7 @@
             this.wipeCaches();
         }
 
-        private bindUnboundFramebuffer(framebuffer: WebGLFramebuffer) {
+        private bindUnboundFramebuffer(framebuffer: Nullable<WebGLFramebuffer>) {
             if (this._currentFramebuffer !== framebuffer) {
                 this._gl.bindFramebuffer(this._gl.FRAMEBUFFER, framebuffer);
                 this._currentFramebuffer = framebuffer;
@@ -1791,6 +1820,11 @@
         // UBOs
         public createUniformBuffer(elements: number[] | Float32Array): WebGLBuffer {
             var ubo = this._gl.createBuffer();
+
+            if (!ubo) {
+                throw new Error("Unable to create uniform buffer");
+            }
+
             this.bindUniformBuffer(ubo);
 
             if (elements instanceof Float32Array) {
@@ -1807,6 +1841,11 @@
 
         public createDynamicUniformBuffer(elements: number[] | Float32Array): WebGLBuffer {
             var ubo = this._gl.createBuffer();
+
+            if (!ubo) {
+                throw new Error("Unable to create dynamic uniform buffer");
+            }
+
             this.bindUniformBuffer(ubo);
 
             if (elements instanceof Float32Array) {
@@ -1854,6 +1893,11 @@
 
         public createVertexBuffer(vertices: number[] | Float32Array): WebGLBuffer {
             var vbo = this._gl.createBuffer();
+
+            if (!vbo) {
+                throw new Error("Unable to create vertex buffer");
+            }
+
             this.bindArrayBuffer(vbo);
 
             if (vertices instanceof Float32Array) {
@@ -1869,6 +1913,11 @@
 
         public createDynamicVertexBuffer(vertices: number[] | Float32Array): WebGLBuffer {
             var vbo = this._gl.createBuffer();
+
+            if (!vbo) {
+                throw new Error("Unable to create dynamic vertex buffer");
+            }
+
             this.bindArrayBuffer(vbo);
 
             if (vertices instanceof Float32Array) {
@@ -1927,6 +1976,11 @@
 
         public createIndexBuffer(indices: IndicesArray, updatable?: boolean): WebGLBuffer {
             var vbo = this._gl.createBuffer();
+
+            if (!vbo) {
+                throw new Error("Unable to create index buffer");
+            }
+
             this.bindIndexBuffer(vbo);
 
             // Check for 32 bits indices
@@ -1965,14 +2019,14 @@
             return vbo;
         }
 
-        public bindArrayBuffer(buffer: WebGLBuffer): void {
+        public bindArrayBuffer(buffer: Nullable<WebGLBuffer>): void {
             if (!this._vaoRecordInProgress) {
                 this._unbindVertexArrayObject();
             }
             this.bindBuffer(buffer, this._gl.ARRAY_BUFFER);
         }
 
-        public bindUniformBuffer(buffer?: WebGLBuffer): void {
+        public bindUniformBuffer(buffer: Nullable<WebGLBuffer>): void {
             this._gl.bindBuffer(this._gl.UNIFORM_BUFFER, buffer);
         }
 
@@ -1986,14 +2040,14 @@
             this._gl.uniformBlockBinding(shaderProgram, uniformLocation, index);
         };
 
-        private bindIndexBuffer(buffer: WebGLBuffer): void {
+        private bindIndexBuffer(buffer: Nullable<WebGLBuffer>): void {
             if (!this._vaoRecordInProgress) {
                 this._unbindVertexArrayObject();
             }
             this.bindBuffer(buffer, this._gl.ELEMENT_ARRAY_BUFFER);
         }
 
-        private bindBuffer(buffer: WebGLBuffer, target: number): void {
+        private bindBuffer(buffer: Nullable<WebGLBuffer>, target: number): void {
             if (this._vaoRecordInProgress || this._currentBoundBuffer[target] !== buffer) {
                 this._gl.bindBuffer(target, buffer);
                 this._currentBoundBuffer[target] = buffer;
@@ -2197,6 +2251,10 @@
         public createInstancesBuffer(capacity: number): WebGLBuffer {
             var buffer = this._gl.createBuffer();
 
+            if (!buffer) {
+                throw new Error("Unable to create instance buffer");
+            }
+
             buffer.capacity = capacity;
 
             this.bindArrayBuffer(buffer);
@@ -2372,8 +2430,13 @@
             return this._createShaderProgram(vertexShader, fragmentShader, context);
         }
 
-        private _createShaderProgram(vertexShader: WebGLShader, fragmentShader: WebGLShader, context?: WebGLRenderingContext): WebGLProgram {
+        private _createShaderProgram(vertexShader: WebGLShader, fragmentShader: WebGLShader, context: WebGLRenderingContext): WebGLProgram {
             var shaderProgram = context.createProgram();
+
+            if (!shaderProgram) {
+                throw new Error("Unable to create program");
+            }
+
             context.attachShader(shaderProgram, vertexShader);
             context.attachShader(shaderProgram, fragmentShader);
 
@@ -2395,7 +2458,7 @@
             return shaderProgram;
         }
 
-        public getUniforms(shaderProgram: WebGLProgram, uniformsNames: string[]): WebGLUniformLocation[] {
+        public getUniforms(shaderProgram: WebGLProgram, uniformsNames: string[]): Nullable<WebGLUniformLocation>[] {
             var results = [];
 
             for (var index = 0; index < uniformsNames.length; index++) {
@@ -2760,7 +2823,7 @@
          * Current families are astc, dxt, pvrtc, etc2, & etc1.
          * @returns The extension selected.
          */
-        public setTextureFormatToUse(formatsAvailable: Array<string>): string {
+        public setTextureFormatToUse(formatsAvailable: Array<string>): Nullable<string> {
             for (var i = 0, len1 = this.texturesSupported.length; i < len1; i++) {
                 for (var j = 0, len2 = formatsAvailable.length; j < len2; j++) {
                     if (this._texturesSupported[i] === formatsAvailable[j].toLowerCase()) {
@@ -2770,11 +2833,18 @@
             }
             // actively set format to nothing, to allow this to be called more than once
             // and possibly fail the 2nd time
-            return this._textureFormatInUse = null;
+            this._textureFormatInUse = null;
+            return null;
         }
 
         public _createTexture(): WebGLTexture {
-            return this._gl.createTexture();
+            let texture = this._gl.createTexture();
+
+            if (!texture) {
+                throw new Error("Unable to create texture");
+            }
+
+            return texture;
         }
 
         /**
@@ -2796,7 +2866,9 @@
          *
          * @returns {WebGLTexture} for assignment back into BABYLON.Texture
          */
-        public createTexture(urlArg: string, noMipmap: boolean, invertY: boolean, scene: Scene, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null, buffer: ArrayBuffer | HTMLImageElement = null, fallBack?: InternalTexture, format?: number): InternalTexture {
+        public createTexture(urlArg: Nullable<string>, noMipmap: boolean, invertY: boolean, scene: Nullable<Scene>, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, 
+                            onLoad: Nullable<() => void> = null, onError: Nullable<() => void> = null, 
+                            buffer: Nullable<ArrayBuffer | HTMLImageElement> = null, fallBack: Nullable<InternalTexture> = null, format: Nullable<number> = null): InternalTexture {
             var url = String(urlArg); // assign a new string, so that the original is still available in case of fallback
             var fromData = url.substr(0, 5) === "data:";
             var fromBlob = url.substr(0, 5) === "blob:";
@@ -2848,7 +2920,7 @@
                 }
             };
 
-            var callback: (arrayBuffer: any) => void;
+            var callback: Nullable<(arrayBuffer: any) => void> = null;
 
             // processing for non-image formats
             if (isKTX || isTGA || isDDS) {
@@ -2887,10 +2959,14 @@
 
                 if (!buffer) {
                     Tools.LoadFile(url, data => {
-                        callback(data);
-                    }, null, scene ? scene.database : null, true, onerror);
+                        if (callback) {
+                            callback(data);
+                        }
+                    }, undefined, scene ? scene.database : undefined, true, onerror);
                 } else {
-                    callback(buffer);
+                    if (callback) {
+                        callback(buffer);
+                    }
                 }
                 // image format processing
             } else {
@@ -2947,7 +3023,7 @@
             return texture;
         }
 
-        private _rescaleTexture(source: InternalTexture, destination: InternalTexture, scene: Scene, internalFormat: number, onComplete: () => void): void {
+        private _rescaleTexture(source: InternalTexture, destination: InternalTexture, scene: Nullable<Scene>, internalFormat: number, onComplete: () => void): void {
             let rtt = this.createRenderTargetTexture({
                 width: destination.width,
                 height: destination.height,
@@ -3011,7 +3087,7 @@
             return internalFormat;
         }
 
-        public updateRawTexture(texture: InternalTexture, data: ArrayBufferView, format: number, invertY: boolean, compression: string = null): void {
+        public updateRawTexture(texture: InternalTexture, data: ArrayBufferView, format: number, invertY: boolean, compression: Nullable<string> = null): void {
             var internalFormat = this._getInternalFormat(format);
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
             this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
@@ -3041,7 +3117,7 @@
             texture.isReady = true;
         }
 
-        public createRawTexture(data: ArrayBufferView, width: number, height: number, format: number, generateMipMaps: boolean, invertY: boolean, samplingMode: number, compression: string = null): InternalTexture {
+        public createRawTexture(data: ArrayBufferView, width: number, height: number, format: number, generateMipMaps: boolean, invertY: boolean, samplingMode: number, compression: Nullable<string> = null): InternalTexture {
             var texture = new InternalTexture(this, InternalTexture.DATASOURCE_RAW);
             texture.baseWidth = width;
             texture.baseHeight = height;
@@ -3165,7 +3241,13 @@
                 if (!this._videoTextureSupported) {
                     if (!texture._workingCanvas) {
                         texture._workingCanvas = document.createElement("canvas");
-                        texture._workingContext = texture._workingCanvas.getContext("2d");
+                        let context = texture._workingCanvas.getContext("2d");
+
+                        if (!context) {
+                            throw new Error("Unable to get 2d context");
+                        }
+
+                        texture._workingContext = context;
                         texture._workingCanvas.width = texture.width;
                         texture._workingCanvas.height = texture.height;
                     }
@@ -3225,7 +3307,7 @@
             var width = size.width || size;
             var height = size.height || size;
 
-            var filters = getSamplingParameters(fullOptions.samplingMode, fullOptions.generateMipMaps, gl);
+            var filters = getSamplingParameters(fullOptions.samplingMode, fullOptions.generateMipMaps ? true : false, gl);
 
             if (fullOptions.type === Engine.TEXTURETYPE_FLOAT && !this._caps.textureFloat) {
                 fullOptions.type = Engine.TEXTURETYPE_UNSIGNED_INT;
@@ -3244,7 +3326,7 @@
             this.bindUnboundFramebuffer(framebuffer);
             gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture._webGLTexture, 0);
 
-            texture._depthStencilBuffer = this._setupFramebufferDepthAttachments(fullOptions.generateStencilBuffer, fullOptions.generateDepthBuffer, width, height);
+            texture._depthStencilBuffer = this._setupFramebufferDepthAttachments(fullOptions.generateStencilBuffer ? true : false, fullOptions.generateDepthBuffer, width, height);
 
             if (fullOptions.generateMipMaps) {
                 this._gl.generateMipmap(this._gl.TEXTURE_2D);
@@ -3262,11 +3344,11 @@
             texture.height = height;
             texture.isReady = true;
             texture.samples = 1;
-            texture.generateMipMaps = fullOptions.generateMipMaps;
+            texture.generateMipMaps = fullOptions.generateMipMaps ? true : false;
             texture.samplingMode = fullOptions.samplingMode;
             texture.type = fullOptions.type;
             texture._generateDepthBuffer = fullOptions.generateDepthBuffer;
-            texture._generateStencilBuffer = fullOptions.generateStencilBuffer;
+            texture._generateStencilBuffer = fullOptions.generateStencilBuffer ? true : false;
 
             this.resetTextureCache();
 
@@ -3431,8 +3513,8 @@
             return textures;
         }
 
-        private _setupFramebufferDepthAttachments(generateStencilBuffer: boolean, generateDepthBuffer: boolean, width: number, height: number, samples = 1): WebGLRenderbuffer {
-            var depthStencilBuffer: WebGLRenderbuffer = null;
+        private _setupFramebufferDepthAttachments(generateStencilBuffer: boolean, generateDepthBuffer: boolean, width: number, height: number, samples = 1): Nullable<WebGLRenderbuffer> {
+            var depthStencilBuffer: Nullable<WebGLRenderbuffer> = null;
             var gl = this._gl;
 
             // Create the depth/stencil buffer
@@ -3464,8 +3546,8 @@
             return depthStencilBuffer;
         }
 
-        public updateRenderTargetTextureSampleCount(texture: InternalTexture, samples: number): number {
-            if (this.webGLVersion < 2) {
+        public updateRenderTargetTextureSampleCount(texture: Nullable<InternalTexture>, samples: number): number {
+            if (this.webGLVersion < 2 || !texture) {
                 return 1;
             }
 
@@ -3491,10 +3573,21 @@
             }
 
             if (samples > 1) {
-                texture._MSAAFramebuffer = gl.createFramebuffer();
+                let framebuffer = gl.createFramebuffer();
+
+                if (!framebuffer) {
+                    throw new Error("Unable to create multi sampled framebuffer");
+                }
+
+                texture._MSAAFramebuffer = framebuffer;
                 this.bindUnboundFramebuffer(texture._MSAAFramebuffer);
 
                 var colorRenderbuffer = gl.createRenderbuffer();
+
+                if (!colorRenderbuffer) {
+                    throw new Error("Unable to create multi sampled framebuffer");
+                }
+
                 gl.bindRenderbuffer(gl.RENDERBUFFER, colorRenderbuffer);
                 gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.RGBA8, texture.width, texture.height);
 
@@ -3535,7 +3628,7 @@
             if (options !== undefined) {
                 generateMipMaps = options.generateMipMaps === undefined ? true : options.generateMipMaps;
                 generateDepthBuffer = options.generateDepthBuffer === undefined ? true : options.generateDepthBuffer;
-                generateStencilBuffer = generateDepthBuffer && options.generateStencilBuffer;
+                generateStencilBuffer = (generateDepthBuffer && options.generateStencilBuffer) ? true : false;
 
                 if (options.samplingMode !== undefined) {
                     samplingMode = options.samplingMode;
@@ -3589,7 +3682,7 @@
             return texture;
         }
 
-        public createPrefilteredCubeTexture(rootUrl: string, scene: Scene, scale: number, offset: number, onLoad: (internalTexture: InternalTexture) => void, onError: (message?: string, exception?: any) => void = null, format?: number, forcedExtension: any = null): InternalTexture {
+        public createPrefilteredCubeTexture(rootUrl: string, scene: Nullable<Scene>, scale: number, offset: number, onLoad: (internalTexture: Nullable<InternalTexture>) => void, onError: Nullable<(message?: string, exception?: any) => void> = null, format?: number, forcedExtension: any = null): InternalTexture {
             var callback = (loadData: any) => {
                 if (!loadData) {
                     if (onLoad) {
@@ -3674,7 +3767,7 @@
             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: (message?: string, exception?: any) => void = null, format?: number, forcedExtension: any = null): InternalTexture {
+        public createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad: Nullable<(data?: any) => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, format?: number, forcedExtension: any = null): InternalTexture {
             var gl = this._gl;
 
             var texture = new InternalTexture(this, InternalTexture.DATASOURCE_CUBE);
@@ -3728,7 +3821,7 @@
                     texture.width = ktx.pixelWidth;
                     texture.height = ktx.pixelHeight;
                     texture.isReady = true;
-                }, null, null, true, onerror);
+                }, undefined, undefined, true, onerror);
             } else if (isDDS) {
                 Tools.LoadFile(rootUrl, data => {
                     var info = Internals.DDSTools.GetDDSInfo(data);
@@ -3761,13 +3854,20 @@
                     if (onLoad) {
                         onLoad({ isDDS: true, width: info.width, info, data, texture });
                     }
-                }, null, null, true, onerror);
+                }, undefined, undefined, true, onerror);
             } else {
+                if (!files) {
+                    throw new Error("Cannot load cubemap because files were not defined");
+                }
+
                 cascadeLoad(rootUrl, scene, imgs => {
                     var width = this.needPOTTextures ? Tools.GetExponentOfTwo(imgs[0].width, this._caps.maxCubemapTextureSize) : imgs[0].width;
                     var height = width;
 
                     this._prepareWorkingCanvas();
+                    if (!this._workingCanvas || !this._workingContext) {
+                        return;
+                    }
                     this._workingCanvas.width = width;
                     this._workingCanvas.height = height;
 
@@ -3801,7 +3901,9 @@
                     texture.width = width;
                     texture.height = height;
                     texture.isReady = true;
-                    texture.format = format;
+                    if (format) {
+                        texture.format = format;
+                    }
 
                     texture.onLoadedObservable.notifyObservers(texture);
                     texture.onLoadedObservable.clear();
@@ -3817,7 +3919,7 @@
             return texture;
         }
 
-        public updateRawCubeTexture(texture: InternalTexture, data: ArrayBufferView[], format: number, type: number, invertY: boolean, compression: string = null, level = 0): void {
+        public updateRawCubeTexture(texture: InternalTexture, data: ArrayBufferView[], format: number, type: number, invertY: boolean, compression: Nullable<string> = null, level = 0): void {
             texture._bufferViewArray = data;
             texture.format = format;
             texture.type = type;
@@ -3866,7 +3968,7 @@
             texture.isReady = true;
         }
 
-        public createRawCubeTexture(data: ArrayBufferView[], size: number, format: number, type: number, generateMipMaps: boolean, invertY: boolean, samplingMode: number, compression: string = null): InternalTexture {
+        public createRawCubeTexture(data: Nullable<ArrayBufferView[]>, size: number, format: number, type: number, generateMipMaps: boolean, invertY: boolean, samplingMode: number, compression: Nullable<string> = null): InternalTexture {
             var gl = this._gl;
             var texture = new InternalTexture(this, InternalTexture.DATASOURCE_CUBERAW);
             texture.isCube = true;
@@ -3934,8 +4036,8 @@
         public createRawCubeTextureFromUrl(url: string, scene: Scene, size: number, format: number, type: number, noMipmap: boolean,
             callback: (ArrayBuffer: ArrayBuffer) => ArrayBufferView[],
             mipmmapGenerator: ((faces: ArrayBufferView[]) => ArrayBufferView[][]),
-            onLoad: () => void = null,
-            onError: (message?: string, exception?: any) => void = null,
+            onLoad: Nullable<() => void> = null,
+            onError: Nullable<(message?: string, exception?: any) => void> = null,
             samplingMode = Texture.TRILINEAR_SAMPLINGMODE,
             invertY = false): InternalTexture {
 
@@ -4006,7 +4108,7 @@
             return texture;
         };
 
-        private _prepareWebGLTextureContinuation(texture: InternalTexture, scene: Scene, noMipmap: boolean, isCompressed: boolean, samplingMode: number): void {
+        private _prepareWebGLTextureContinuation(texture: InternalTexture, scene: Nullable<Scene>, noMipmap: boolean, isCompressed: boolean, samplingMode: number): void {
             var gl = this._gl;
             if (!gl) {
                 return;
@@ -4032,7 +4134,7 @@
             texture.onLoadedObservable.clear();
         }
 
-        private _prepareWebGLTexture(texture: InternalTexture, scene: Scene, width: number, height: number, invertY: boolean, noMipmap: boolean, isCompressed: boolean,
+        private _prepareWebGLTexture(texture: InternalTexture, scene: Nullable<Scene>, width: number, height: number, invertY: boolean, noMipmap: boolean, isCompressed: boolean,
             processFunction: (width: number, height: number, continuationCallback: () => void) => boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE): void {
             var potWidth = this.needPOTTextures ? Tools.GetExponentOfTwo(width, this.getCaps().maxTextureSize) : width;
             var potHeight = this.needPOTTextures ? Tools.GetExponentOfTwo(height, this.getCaps().maxTextureSize) : height;
@@ -4166,7 +4268,7 @@
             }
         }
 
-        public _bindTextureDirectly(target: number, texture: InternalTexture): void {
+        public _bindTextureDirectly(target: number, texture: Nullable<InternalTexture>): void {
             if (this._activeTexturesCache[this._activeTexture] !== texture) {
                 this._gl.bindTexture(target, texture ? texture._webGLTexture : null);
                 this._activeTexturesCache[this._activeTexture] = texture;
@@ -4236,7 +4338,7 @@
                 this.activateTexture((<any>this._gl)["TEXTURE" + channel]);
             }
 
-            if (internalTexture.isCube) {
+            if (internalTexture && internalTexture.isCube) {
                 this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, internalTexture);
 
                 if (internalTexture._cachedCoordinatesMode !== texture.coordinatesMode) {
@@ -4251,7 +4353,7 @@
             } else {
                 this._bindTextureDirectly(this._gl.TEXTURE_2D, internalTexture);
 
-                if (internalTexture._cachedWrapU !== texture.wrapU) {
+                if (internalTexture && internalTexture._cachedWrapU !== texture.wrapU) {
                     internalTexture._cachedWrapU = texture.wrapU;
 
                     switch (texture.wrapU) {
@@ -4267,7 +4369,7 @@
                     }
                 }
 
-                if (internalTexture._cachedWrapV !== texture.wrapV) {
+                if (internalTexture && internalTexture._cachedWrapV !== texture.wrapV) {
                     internalTexture._cachedWrapV = texture.wrapV;
                     switch (texture.wrapV) {
                         case Texture.WRAP_ADDRESSMODE:
@@ -4463,8 +4565,6 @@
                 this._gl.deleteFramebuffer(this._dummyFramebuffer);
             }
 
-            this._gl = null;
-
             //WebVR
             this.disableVR();
 
@@ -4473,13 +4573,15 @@
             window.removeEventListener("focus", this._onFocus);
             window.removeEventListener('vrdisplaypointerrestricted', this._onVRDisplayPointerRestricted);
             window.removeEventListener('vrdisplaypointerunrestricted', this._onVRDisplayPointerUnrestricted);
-            this._renderingCanvas.removeEventListener("focus", this._onCanvasFocus);
-            this._renderingCanvas.removeEventListener("blur", this._onCanvasBlur);
-            this._renderingCanvas.removeEventListener("pointerout", this._onCanvasBlur);
+            if (this._renderingCanvas) {
+                this._renderingCanvas.removeEventListener("focus", this._onCanvasFocus);
+                this._renderingCanvas.removeEventListener("blur", this._onCanvasBlur);
+                this._renderingCanvas.removeEventListener("pointerout", this._onCanvasBlur);
 
-            if (!this._doNotHandleContextLost) {
-                this._renderingCanvas.removeEventListener("webglcontextlost", this._onContextLost);
-                this._renderingCanvas.removeEventListener("webglcontextrestored", this._onContextRestored);
+                if (!this._doNotHandleContextLost) {
+                    this._renderingCanvas.removeEventListener("webglcontextlost", this._onContextLost);
+                    this._renderingCanvas.removeEventListener("webglcontextrestored", this._onContextRestored);
+                }
             }
             document.removeEventListener("fullscreenchange", this._onFullscreenChange);
             document.removeEventListener("mozfullscreenchange", this._onFullscreenChange);
@@ -4492,10 +4594,15 @@
 
             if (this._onVrDisplayConnect) {
                 window.removeEventListener('vrdisplayconnect', this._onVrDisplayConnect);
-                window.removeEventListener('vrdisplaydisconnect', this._onVrDisplayDisconnect);
-                window.removeEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
-                this._onVrDisplayConnect = undefined;
-                this._onVrDisplayDisconnect = undefined;
+                if (this._onVrDisplayDisconnect) {
+                    window.removeEventListener('vrdisplaydisconnect', this._onVrDisplayDisconnect);
+                }
+
+                if (this._onVrDisplayPresentChange) {
+                    window.removeEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
+                }
+                this._onVrDisplayConnect = null;
+                this._onVrDisplayDisconnect = null;
             }
 
             // Remove from Instances
@@ -4507,7 +4614,7 @@
 
             this._workingCanvas = null;
             this._workingContext = null;
-            this._currentBufferPointers = null;
+            this._currentBufferPointers = [];
             this._renderingCanvas = null;
             this._currentProgram = null;
 
@@ -4541,7 +4648,7 @@
         }
 
         public get loadingScreen(): ILoadingScreen {
-            if (!this._loadingScreen && DefaultLoadingScreen)
+            if (!this._loadingScreen && DefaultLoadingScreen && this._renderingCanvas)
                 this._loadingScreen = new DefaultLoadingScreen(this._renderingCanvas)
             return this._loadingScreen;
         }
@@ -4559,22 +4666,34 @@
         }
 
         public attachContextLostEvent(callback: ((event: WebGLContextEvent) => void)): void {
-            this._renderingCanvas.addEventListener("webglcontextlost", callback, false);
+            if (this._renderingCanvas) {
+                this._renderingCanvas.addEventListener("webglcontextlost", callback, false);
+            }
         }
 
         public attachContextRestoredEvent(callback: ((event: WebGLContextEvent) => void)): void {
-            this._renderingCanvas.addEventListener("webglcontextrestored", callback, false);
+            if (this._renderingCanvas) {
+                this._renderingCanvas.addEventListener("webglcontextrestored", callback, false);
+            }
         }
 
-        public getVertexShaderSource(program: WebGLProgram): string {
+        public getVertexShaderSource(program: WebGLProgram): Nullable<string> {
             var shaders = this._gl.getAttachedShaders(program);
 
+            if (!shaders) {
+                return null;
+            }
+
             return this._gl.getShaderSource(shaders[0]);
         }
 
-        public getFragmentShaderSource(program: WebGLProgram): string {
+        public getFragmentShaderSource(program: WebGLProgram): Nullable<string> {
             var shaders = this._gl.getAttachedShaders(program);
 
+            if (!shaders) {
+                return null;
+            }
+
             return this._gl.getShaderSource(shaders[1]);
         }
 
@@ -4600,7 +4719,13 @@
         public _readTexturePixels(texture: InternalTexture, width: number, height: number, faceIndex = -1): ArrayBufferView {
             let gl = this._gl;
             if (!this._dummyFramebuffer) {
-                this._dummyFramebuffer = gl.createFramebuffer();
+                let dummy = gl.createFramebuffer();
+
+                if (!dummy) {
+                    throw new Error("Unable to create dummy framebuffer");
+                }
+
+                this._dummyFramebuffer = dummy;
             }
             gl.bindFramebuffer(gl.FRAMEBUFFER, this._dummyFramebuffer);
 
@@ -4759,10 +4884,6 @@
         // Statics
         public static isSupported(): boolean {
             try {
-                // Avoid creating an unsized context for CocoonJS, since size determined on first creation.  Is not resizable
-                if (navigator.isCocoonJS) {
-                    return true;
-                }
                 var tempcanvas = document.createElement("canvas");
                 var gl = tempcanvas.getContext("webgl") || tempcanvas.getContext("experimental-webgl");
 

+ 43 - 23
src/Materials/Textures/babylon.baseTexture.ts

@@ -12,7 +12,9 @@
                 return;
             }
             this._hasAlpha = value;
-            this._scene.markAllMaterialsAsDirty(Material.TextureDirtyFlag);
+            if (this._scene) {
+                this._scene.markAllMaterialsAsDirty(Material.TextureDirtyFlag);
+            }
         }
         public get hasAlpha(): boolean {
             return this._hasAlpha;
@@ -34,7 +36,9 @@
                 return;
             }
             this._coordinatesMode = value;
-            this._scene.markAllMaterialsAsDirty(Material.TextureDirtyFlag);
+            if (this._scene) {
+                this._scene.markAllMaterialsAsDirty(Material.TextureDirtyFlag);
+            }
         }
         public get coordinatesMode(): number {
             return this._coordinatesMode;
@@ -103,33 +107,35 @@
 
         public delayLoadState = Engine.DELAYLOADSTATE_NONE;
 
-        private _scene: Scene;
-        public _texture: InternalTexture;
-        private _uid: string;
+        private _scene: Nullable<Scene>;
+        public _texture: Nullable<InternalTexture>;
+        private _uid: Nullable<string>;
 
         public get isBlocking(): boolean {
             return true;
         }
 
-        constructor(scene: Scene) {
+        constructor(scene: Nullable<Scene>) {
             this._scene = scene || Engine.LastCreatedScene;
-            this._scene.textures.push(this);
+            if (this._scene) {
+                this._scene.textures.push(this);
+            }
             this._uid = null;
         }
 
-        public getScene(): Scene {
+        public getScene(): Nullable<Scene> {
             return this._scene;
         }
 
-        public getTextureMatrix(): Matrix {
+        public getTextureMatrix(): Nullable<Matrix> {
             return null;
         }
 
-        public getReflectionTextureMatrix(): Matrix {
+        public getReflectionTextureMatrix(): Nullable<Matrix> {
             return null;
         }
 
-        public getInternalTexture(): InternalTexture {
+        public getInternalTexture(): Nullable<InternalTexture> {
             return this._texture;
         }
 
@@ -151,11 +157,11 @@
         }
 
         public getSize(): ISize {
-            if (this._texture.width) {
+            if (this._texture && this._texture.width) {
                 return new Size(this._texture.width, this._texture.height);
             }
 
-            if (this._texture._size) {
+            if (this._texture && this._texture._size) {
                 return new Size(this._texture._size, this._texture._size);
             }
 
@@ -180,7 +186,11 @@
             return false;
         }
 
-        public _getFromCache(url: string, noMipmap: boolean, sampling?: number): InternalTexture {
+        public _getFromCache(url: Nullable<string>, noMipmap: boolean, sampling?: number): Nullable<InternalTexture> {
+            if (!this._scene) {
+                return null
+            }
+
             var texturesCache = this._scene.getEngine().getLoadedTexturesCache();
             for (var index = 0; index < texturesCache.length; index++) {
                 var texturesCacheEntry = texturesCache[index];
@@ -203,7 +213,7 @@
         public delayLoad(): void {
         }
 
-        public clone(): BaseTexture {
+        public clone(): Nullable<BaseTexture> {
             return null;
         }
 
@@ -223,13 +233,19 @@
             return (this._texture.format !== undefined) ? this._texture.format : Engine.TEXTUREFORMAT_RGBA;
         }
 
-        public readPixels(faceIndex = 0): ArrayBufferView {
+        public readPixels(faceIndex = 0): Nullable<ArrayBufferView> {
             if (!this._texture) {
                 return null;
             }
 
             var size = this.getSize();
-            var engine = this.getScene().getEngine();
+            let scene = this.getScene();
+
+            if (!scene) {
+                return null;
+            }
+
+            var engine = scene.getEngine();
 
             if (this._texture.isCube) {
                 return engine._readTexturePixels(this._texture, size.width, size.height, faceIndex);
@@ -245,7 +261,7 @@
             }
         }
 
-        public get sphericalPolynomial(): SphericalPolynomial {
+        public get sphericalPolynomial(): Nullable<SphericalPolynomial> {
             if (!this._texture || !Internals.CubeMapToSphericalPolynomialTools || !this.isReady()) {
                 return null;
             }
@@ -258,27 +274,27 @@
             return this._texture._sphericalPolynomial;
         }
 
-        public set sphericalPolynomial(value: SphericalPolynomial) {
+        public set sphericalPolynomial(value: Nullable<SphericalPolynomial>) {
             if (this._texture) {
                 this._texture._sphericalPolynomial = value;
             }
         }
 
-        public get _lodTextureHigh(): BaseTexture {
+        public get _lodTextureHigh(): Nullable<BaseTexture> {
             if (this._texture) {
                 return this._texture._lodTextureHigh;
             }
             return null;
         }
 
-        public get _lodTextureMid(): BaseTexture {
+        public get _lodTextureMid(): Nullable<BaseTexture> {
             if (this._texture) {
                 return this._texture._lodTextureMid;
             }
             return null;
         }
 
-        public get _lodTextureLow(): BaseTexture {
+        public get _lodTextureLow(): Nullable<BaseTexture> {
             if (this._texture) {
                 return this._texture._lodTextureLow;
             }
@@ -286,8 +302,12 @@
         }
 
         public dispose(): void {
+            if (!this._scene) {
+                return;
+            }
+            
             // Animations
-            this.getScene().stopAnimation(this);
+            this._scene.stopAnimation(this);
 
             // Remove from scene
             this._scene._removePendingData(this);

+ 21 - 19
src/Materials/Textures/babylon.internalTexture.ts

@@ -29,37 +29,37 @@ module BABYLON {
 
         // Private
         public _dataSource = InternalTexture.DATASOURCE_UNKNOWN;
-        public _buffer: ArrayBuffer | HTMLImageElement;
+        public _buffer: Nullable<ArrayBuffer | HTMLImageElement>;
         public _bufferView: ArrayBufferView;
-        public _bufferViewArray: ArrayBufferView[];
+        public _bufferViewArray: Nullable<ArrayBufferView[]>;
         public _size: number;
         public _extension: string;
-        public _files: string[];
+        public _files: Nullable<string[]>;
         public _workingCanvas: HTMLCanvasElement;
         public _workingContext: CanvasRenderingContext2D;
-        public _framebuffer: WebGLFramebuffer;
-        public _depthStencilBuffer: WebGLRenderbuffer;
-        public _MSAAFramebuffer: WebGLFramebuffer;
-        public _MSAARenderBuffer: WebGLRenderbuffer;
-        public _cachedCoordinatesMode: number;
-        public _cachedWrapU: number;
-        public _cachedWrapV: number;
-        public _cachedAnisotropicFilteringLevel: number;
+        public _framebuffer: Nullable<WebGLFramebuffer>;
+        public _depthStencilBuffer: Nullable<WebGLRenderbuffer>;
+        public _MSAAFramebuffer: Nullable<WebGLFramebuffer>;
+        public _MSAARenderBuffer: Nullable<WebGLRenderbuffer>;
+        public _cachedCoordinatesMode: Nullable<number>;
+        public _cachedWrapU: Nullable<number>;
+        public _cachedWrapV: Nullable<number>;
+        public _cachedAnisotropicFilteringLevel: Nullable<number>;
         public _isDisabled: boolean;
-        public _compression: string;
+        public _compression: Nullable<string>;
         public _generateStencilBuffer: boolean;
         public _generateDepthBuffer: boolean;
-        public _sphericalPolynomial: BABYLON.SphericalPolynomial;
+        public _sphericalPolynomial: Nullable<SphericalPolynomial>;
         public _lodGenerationScale: number;
         public _lodGenerationOffset: number;
         // The following three fields helps sharing generated fixed LODs for texture filtering
         // In environment not supporting the textureLOD extension like EDGE. They are for internal use only.
         // They are at the level of the gl texture to benefit from the cache.
-        public _lodTextureHigh: BABYLON.BaseTexture;
-        public _lodTextureMid: BABYLON.BaseTexture;
-        public _lodTextureLow: BABYLON.BaseTexture;
+        public _lodTextureHigh: BaseTexture;
+        public _lodTextureMid: BaseTexture;
+        public _lodTextureLow: BaseTexture;
 
-        public _webGLTexture: WebGLTexture;
+        public _webGLTexture: Nullable<WebGLTexture>;
         public _references: number = 1;
         private _engine: Engine;
 
@@ -101,7 +101,7 @@ module BABYLON {
                 case InternalTexture.DATASOURCE_URL:
                     proxy = this._engine.createTexture(this.url, !this.generateMipMaps, this.invertY, null, this.samplingMode, () => {
                         this.isReady = true;
-                    }, null, this._buffer, null, this.format); 
+                    }, null, this._buffer, undefined, this.format); 
                     proxy._swapAndDie(this);
                     return;
 
@@ -159,7 +159,9 @@ module BABYLON {
 
                 case InternalTexture.DATASOURCE_CUBEPREFILTERED:
                     proxy = this._engine.createPrefilteredCubeTexture(this.url, null, this._lodGenerationScale, this._lodGenerationOffset, (proxy) => {
-                        proxy._swapAndDie(this);
+                        if (proxy) {
+                            proxy._swapAndDie(this);
+                        }
                         
                         this.isReady = true;
                     }, null, this.format, this._extension);

+ 93 - 27
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -25,7 +25,7 @@
         /**
         * Use this list to define the list of mesh you want to render.
         */
-        public renderList = new Array<AbstractMesh>();
+        public renderList: Nullable<Array<AbstractMesh>> = new Array<AbstractMesh>();
         public renderParticles = true;
         public renderSprites = false;
         public coordinatesMode = Texture.PROJECTION_MODE;
@@ -34,7 +34,7 @@
         public useCameraPostProcesses: boolean;
         public ignoreCameraViewport: boolean = false;
 
-        private _postProcessManager: PostProcessManager;
+        private _postProcessManager: Nullable<PostProcessManager>;
         private _postProcesses: PostProcess[];
 
         // Events
@@ -116,14 +116,18 @@
             return this._renderTargetOptions;
         }
 
-        constructor(name: string, size: any, scene: Scene, generateMipMaps?: boolean, doNotChangeAspectRatio: boolean = true, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, public isCube = false, samplingMode = Texture.TRILINEAR_SAMPLINGMODE, generateDepthBuffer = true, generateStencilBuffer = false, isMulti = false) {
+        constructor(name: string, size: any, scene: Nullable<Scene>, generateMipMaps?: boolean, doNotChangeAspectRatio: boolean = true, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, public isCube = false, samplingMode = Texture.TRILINEAR_SAMPLINGMODE, generateDepthBuffer = true, generateStencilBuffer = false, isMulti = false) {
             super(null, scene, !generateMipMaps);
             scene = this.getScene();
 
+            if (!scene) {
+                return;
+            }
+
             this.name = name;
             this.isRenderTarget = true;
             this._size = size;
-            this._generateMipMaps = generateMipMaps;
+            this._generateMipMaps = generateMipMaps ? true : false;
             this._doNotChangeAspectRatio = doNotChangeAspectRatio;
 
             // Rendering groups
@@ -165,7 +169,13 @@
                 return;
             }
 
-            this._samples = this.getScene().getEngine().updateRenderTargetTextureSampleCount(this._texture, value);
+            let scene = this.getScene();
+
+            if (!scene) {
+                return;
+            }
+
+            this._samples = scene.getEngine().updateRenderTargetTextureSampleCount(this._texture, value);
         }
 
         public resetRefreshCounter(): void {
@@ -184,7 +194,12 @@
 
         public addPostProcess(postProcess: PostProcess): void {
             if (!this._postProcessManager) {
-                this._postProcessManager = new PostProcessManager(this.getScene());
+                let scene = this.getScene();
+                
+                if (!scene) {
+                    return;
+                }                
+                this._postProcessManager = new PostProcessManager(scene);
                 this._postProcesses = new Array<PostProcess>();
             }
 
@@ -200,7 +215,6 @@
             if (dispose) {
                 for (var postProcess of this._postProcesses) {
                     postProcess.dispose();
-                    postProcess = null;
                 }
             }
 
@@ -264,17 +278,28 @@
 
         public resize(size: any) {
             this.releaseInternalTexture();
+            let scene = this.getScene();
+            
+            if (!scene) {
+                return;
+            } 
+
             if (this.isCube) {
-                this._texture = this.getScene().getEngine().createRenderTargetCubeTexture(size, this._renderTargetOptions);
+                this._texture = scene.getEngine().createRenderTargetCubeTexture(size, this._renderTargetOptions);
             } else {
-                this._texture = this.getScene().getEngine().createRenderTargetTexture(size, this._renderTargetOptions);
+                this._texture = scene.getEngine().createRenderTargetTexture(size, this._renderTargetOptions);
             }
 
             this._size = size;
         }
 
-        public render(useCameraPostProcess?: boolean, dumpForDebug?: boolean) {
+        public render(useCameraPostProcess: boolean = false, dumpForDebug: boolean = false) {
             var scene = this.getScene();
+
+            if (!scene) {
+                return;
+            }
+
             var engine = scene.getEngine();
 
             if (this.useCameraPostProcesses !== undefined) {
@@ -285,7 +310,10 @@
                 this.renderList = [];
                 for (var index = 0; index < this._waitingRenderList.length; index++) {
                     var id = this._waitingRenderList[index];
-                    this.renderList.push(scene.getMeshByID(id));
+                    let mesh = scene.getMeshByID(id);
+                    if (mesh) {
+                        this.renderList.push(mesh);
+                    }
                 }
 
                 delete this._waitingRenderList;
@@ -293,9 +321,19 @@
 
             // Is predicate defined?
             if (this.renderListPredicate) {
-                this.renderList.splice(0); // Clear previous renderList
+                if (this.renderList) {
+                    this.renderList.splice(0); // Clear previous renderList
+                } else {
+                    this.renderList = [];
+                }
 
-                var sceneMeshes = this.getScene().meshes;
+                var scene = this.getScene();
+                
+                if (!scene) {
+                    return;
+                }
+
+                var sceneMeshes = scene.meshes;
 
                 for (var index = 0; index < sceneMeshes.length; index++) {
                     var mesh = sceneMeshes[index];
@@ -309,7 +347,7 @@
 
             // Set custom projection.
             // Needs to be before binding to prevent changing the aspect ratio.
-            let camera: Camera;
+            let camera: Nullable<Camera>;
             if (this.activeCamera) {
                 camera = this.activeCamera;
                 engine.setViewport(this.activeCamera.viewport, this._size, this._size);
@@ -320,7 +358,9 @@
             }
             else {
                 camera = scene.activeCamera;
-                engine.setViewport(scene.activeCamera.viewport, this._size, this._size);
+                if (camera) {
+                    engine.setViewport(camera.viewport, this._size, this._size);
+                }
             }
 
             // Prepare renderingManager
@@ -342,7 +382,7 @@
                     mesh._preActivateForIntermediateRendering(sceneRenderId);
 
                     let isMasked;
-                    if (!this.renderList) {
+                    if (!this.renderList && camera) {
                         isMasked = ((mesh.layerMask & camera.layerMask) === 0);
                     } else {
                         isMasked = false;
@@ -385,24 +425,37 @@
 
             this.onAfterUnbindObservable.notifyObservers(this);
 
-            if (this.activeCamera && this.activeCamera !== scene.activeCamera) {
-                scene.setTransformMatrix(scene.activeCamera.getViewMatrix(), scene.activeCamera.getProjectionMatrix(true));
+            if (scene.activeCamera) {
+                if (this.activeCamera && this.activeCamera !== scene.activeCamera) {
+                    scene.setTransformMatrix(scene.activeCamera.getViewMatrix(), scene.activeCamera.getProjectionMatrix(true));
+                }
+                engine.setViewport(scene.activeCamera.viewport);
             }
-            engine.setViewport(scene.activeCamera.viewport);
 
             scene.resetCachedMaterial();
         }
 
         private renderToTarget(faceIndex: number, currentRenderList: AbstractMesh[], currentRenderListLength: number, useCameraPostProcess: boolean, dumpForDebug: boolean): void {
             var scene = this.getScene();
+            
+            if (!scene) {
+                return;
+            }
+
             var engine = scene.getEngine();
 
+            if (!this._texture) {
+                return;
+            }
+
             // Bind
             if (this._postProcessManager) {
                 this._postProcessManager._prepareFrame(this._texture, this._postProcesses);
             }
             else if (!useCameraPostProcess || !scene.postProcessManager._prepareFrame(this._texture)) {
-                engine.bindFramebuffer(this._texture, this.isCube ? faceIndex : undefined, undefined, undefined, this.ignoreCameraViewport);
+                if (this._texture) {
+                    engine.bindFramebuffer(this._texture, this.isCube ? faceIndex : undefined, undefined, undefined, this.ignoreCameraViewport);
+                }
             }
 
             this.onBeforeRenderObservable.notifyObservers(faceIndex);
@@ -464,9 +517,9 @@
          * @param transparentSortCompareFn The transparent queue comparison function use to sort.
          */
         public setRenderingOrder(renderingGroupId: number,
-            opaqueSortCompareFn: (a: SubMesh, b: SubMesh) => number = null,
-            alphaTestSortCompareFn: (a: SubMesh, b: SubMesh) => number = null,
-            transparentSortCompareFn: (a: SubMesh, b: SubMesh) => number = null): void {
+            opaqueSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null,
+            alphaTestSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null,
+            transparentSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null): void {
 
             this._renderingManager.setRenderingOrder(renderingGroupId,
                 opaqueSortCompareFn,
@@ -505,7 +558,9 @@
 
             // RenderTarget Texture
             newTexture.coordinatesMode = this.coordinatesMode;
-            newTexture.renderList = this.renderList.slice(0);
+            if (this.renderList) {
+                newTexture.renderList = this.renderList.slice(0);
+            }
 
             return newTexture;
         }
@@ -520,8 +575,10 @@
             serializationObject.renderTargetSize = this.getRenderSize();
             serializationObject.renderList = [];
 
-            for (var index = 0; index < this.renderList.length; index++) {
-                serializationObject.renderList.push(this.renderList[index].id);
+            if (this.renderList) {
+                for (var index = 0; index < this.renderList.length; index++) {
+                    serializationObject.renderList.push(this.renderList[index].id);
+                }
             }
 
             return serializationObject;
@@ -529,7 +586,11 @@
 
         // This will remove the attached framebuffer objects. The texture will not be able to be used as render target anymore
         public disposeFramebufferObjects(): void {
-            this.getScene().getEngine()._releaseFramebufferObjects(this.getInternalTexture());
+            let objBuffer = this.getInternalTexture();
+            let scene = this.getScene();
+            if (objBuffer && scene) {
+                scene.getEngine()._releaseFramebufferObjects(objBuffer);
+            }
         }
 
         public dispose(): void {
@@ -544,6 +605,11 @@
 
             // Remove from custom render targets
             var scene = this.getScene();
+
+            if (!scene) {
+                return;
+            }
+
             var index = scene.customRenderTargets.indexOf(this);
 
             if (index >= 0) {

+ 56 - 19
src/Materials/Textures/babylon.texture.ts

@@ -37,7 +37,7 @@
 
         // Members
         @serialize()
-        public url: string;
+        public url: Nullable<string>;
 
         @serialize()
         public uOffset = 0;
@@ -85,10 +85,10 @@
         public _samplingMode: number;
         private _buffer: any;
         private _deleteBuffer: boolean;
-        protected _format: number;
-        private _delayedOnLoad: () => void;
-        private _delayedOnError: () => void;
-        private _onLoadObservable: Observable<Texture>;
+        protected _format: Nullable<number>;
+        private _delayedOnLoad: Nullable<() => void>;
+        private _delayedOnError: Nullable<() => void>;
+        private _onLoadObservable: Nullable<Observable<Texture>>;
 
         protected _isBlocking: boolean = true;
         public set isBlocking(value: boolean) {
@@ -103,20 +103,25 @@
             return this._samplingMode;
         }
 
-        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) {
+        constructor(url: Nullable<string>, scene: Nullable<Scene>, noMipmap: boolean = false, invertY: boolean = true, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: Nullable<() => void> = null, onError: Nullable<(message?: string, esception?: any) => void> = null, buffer: any = null, deleteBuffer: boolean = false, format?: number) {
             super(scene);
 
-            this.name = url;
+            this.name = url || "";
             this.url = url;
             this._noMipmap = noMipmap;
             this._invertY = invertY;
             this._samplingMode = samplingMode;
             this._buffer = buffer;
             this._deleteBuffer = deleteBuffer;
-            this._format = format;
+            if (format) {
+                this._format = format;
+            }
 
             scene = this.getScene();
 
+            if (!scene) {
+                return;
+            }
             scene.getEngine().onBeforeTextureInitObservable.notifyObservers(this);
 
             let load = () => {
@@ -127,7 +132,7 @@
                     onLoad();
                 }
 
-                if (!this.isBlocking) {
+                if (!this.isBlocking && scene) {
                     scene.resetCachedMaterial();
                 }
             }
@@ -142,7 +147,7 @@
 
             if (!this._texture) {
                 if (!scene.useDelayedTextureLoading) {
-                    this._texture = scene.getEngine().createTexture(this.url, noMipmap, invertY, scene, this._samplingMode, load, onError, this._buffer, null, this._format);
+                    this._texture = scene.getEngine().createTexture(this.url, noMipmap, invertY, scene, this._samplingMode, load, onError, this._buffer, undefined, this._format);
                     if (deleteBuffer) {
                         delete this._buffer;
                     }
@@ -172,19 +177,32 @@
                 return;
             }
 
+            let scene = this.getScene();
+
+            if (!scene) {
+                return;
+            }
+            
             this.delayLoadState = Engine.DELAYLOADSTATE_LOADED;
             this._texture = this._getFromCache(this.url, this._noMipmap, this._samplingMode);
 
             if (!this._texture) {
-                this._texture = this.getScene().getEngine().createTexture(this.url, this._noMipmap, this._invertY, this.getScene(), this._samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
+                this._texture = scene.getEngine().createTexture(this.url, this._noMipmap, this._invertY, scene, this._samplingMode, this._delayedOnLoad, this._delayedOnError, this._buffer, null, this._format);
                 if (this._deleteBuffer) {
                     delete this._buffer;
                 }
             } else {
                 if (this._texture.isReady) {
-                    Tools.SetImmediate(() => this._delayedOnLoad());
+                    Tools.SetImmediate(() => {
+                        if (!this._delayedOnLoad) {
+                            return;
+                        }
+                        this._delayedOnLoad();
+                    });
                 } else {
-                    this._texture.onLoadedObservable.add(this._delayedOnLoad);
+                    if (this._delayedOnLoad) {
+                        this._texture.onLoadedObservable.add(this._delayedOnLoad);
+                    }
                 }
             }
         }
@@ -194,8 +212,14 @@
                 return;
             }
 
+            let scene = this.getScene();
+            
+            if (!scene) {
+                return;
+            }            
+
             this._samplingMode = samplingMode;
-            this.getScene().getEngine().updateTextureSamplingMode(samplingMode, this._texture);
+            scene.getEngine().updateTextureSamplingMode(samplingMode, this._texture);
         }
 
         private _prepareRowForTextureGeneration(x: number, y: number, z: number, t: Vector3): void {
@@ -255,7 +279,13 @@
             this._cachedTextureMatrix.m[4] = this._t2.x; this._cachedTextureMatrix.m[5] = this._t2.y; this._cachedTextureMatrix.m[6] = this._t2.z;
             this._cachedTextureMatrix.m[8] = this._t0.x; this._cachedTextureMatrix.m[9] = this._t0.y; this._cachedTextureMatrix.m[10] = this._t0.z;
 
-            this.getScene().markAllMaterialsAsDirty(Material.TextureDirtyFlag, (mat) => {
+            let scene = this.getScene();
+            
+            if (!scene) {
+                return this._cachedTextureMatrix;
+            }
+
+            scene.markAllMaterialsAsDirty(Material.TextureDirtyFlag, (mat) => {
                 return mat.hasTexture(this);
             });
 
@@ -264,6 +294,11 @@
 
         public getReflectionTextureMatrix(): Matrix {
             let scene = this.getScene();
+
+            if (!scene) {
+                return this._cachedTextureMatrix;
+            }
+
             if (
                 this.uOffset === this._cachedUOffset &&
                 this.vOffset === this._cachedVOffset &&
@@ -327,7 +362,7 @@
 
         public clone(): Texture {
             return SerializationHelper.Clone(() => {
-                return new Texture(this._texture.url, this.getScene(), this._noMipmap, this._invertY, this._samplingMode);
+                return new Texture(this._texture ? this._texture.url : null, this.getScene(), this._noMipmap, this._invertY, this._samplingMode);
             }, this);
         }
 
@@ -366,11 +401,12 @@
         }
 
         // Statics
-        public static CreateFromBase64String(data: string, name: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, onLoad: () => void = null, onError: () => void = null, format: number = Engine.TEXTUREFORMAT_RGBA): Texture {
+        public static CreateFromBase64String(data: string, name: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE, 
+                                            onLoad: Nullable<() => void> = null, onError: Nullable<() => void> = null, format: number = Engine.TEXTUREFORMAT_RGBA): Texture {
             return new Texture("data:" + name, scene, noMipmap, invertY, samplingMode, onLoad, onError, data, false, format);
         }
 
-        public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): BaseTexture {
+        public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): Nullable<BaseTexture> {
             if (parsedTexture.customType) {
                 var customTexture = Tools.Instantiate(parsedTexture.customType);
                 // Update Sampling Mode
@@ -435,7 +471,8 @@
             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: (message?: string, exception?: any) => 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: Nullable<() => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, format: number = Engine.TEXTUREFORMAT_RGBA): Texture {
             if (name.substr(0, 5) !== "data:") {
                 name = "data:" + name;
             }

+ 5 - 5
src/Materials/babylon.uniformBuffer.ts

@@ -2,10 +2,10 @@ module BABYLON {
 
     export class UniformBuffer {
         private _engine: Engine;
-        private _buffer: WebGLBuffer;
+        private _buffer: Nullable<WebGLBuffer>;
         private _data: number[];
         private _bufferData: Float32Array;
-        private _dynamic: boolean;
+        private _dynamic?: boolean;
         private _uniformLocations: { [key:string]:number; };
         private _uniformSizes: { [key:string]:number; };
         private _uniformLocationPointer: number;
@@ -182,7 +182,7 @@ module BABYLON {
          * update the underlying WebGL uniform buffer to the GPU.
          */
         public isDynamic(): boolean {
-            return this._dynamic;
+            return this._dynamic !== undefined;
         }
 
         /**
@@ -195,7 +195,7 @@ module BABYLON {
         /**
          * The underlying WebGL Uniform buffer.
          */
-        public getBuffer(): WebGLBuffer {
+        public getBuffer(): Nullable<WebGLBuffer> {
             return this._buffer;
         }
 
@@ -600,7 +600,7 @@ module BABYLON {
         public bindToEffect(effect: Effect, name: string): void {
             this._currentEffect = effect;
 
-            if (this._noUBO) {
+            if (this._noUBO || !this._buffer) {
                 return;
             }
             

+ 1 - 1
src/Mesh/babylon.abstractMesh.ts

@@ -335,7 +335,7 @@
         public actionManager: ActionManager;
 
         // Physics
-        public physicsImpostor: BABYLON.PhysicsImpostor;
+        public physicsImpostor: Nullable<PhysicsImpostor>;
 
         // Collisions
         private _checkCollisions = false;

+ 2 - 2
src/PostProcess/babylon.passPostProcess.ts

@@ -1,7 +1,7 @@
 module BABYLON {
     export class PassPostProcess extends PostProcess {    
-        constructor(name: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT) {
-            super(name, "pass", null, null, options, camera, samplingMode, engine, reusable, null, textureType);
+        constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT) {
+            super(name, "pass", null, null, options, camera, samplingMode, engine, reusable, undefined, textureType);
         }
     }
 } 

+ 15 - 13
src/PostProcess/babylon.postProcess.ts

@@ -137,7 +137,8 @@
             return this._texelSize;
         }
 
-        constructor(public name: string, fragmentUrl: string, parameters: string[], samplers: string[], options: number | PostProcessOptions, camera: Camera, samplingMode: number = Texture.NEAREST_SAMPLINGMODE, engine?: Engine, reusable?: boolean, defines?: string, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT, vertexUrl: string = "postprocess", indexParameters?: any, blockCompilation = false) {
+        constructor(public name: string, fragmentUrl: string, parameters: Nullable<string[]>, samplers: Nullable<string[]>, options: number | PostProcessOptions, camera: Nullable<Camera>, 
+                    samplingMode: number = Texture.NEAREST_SAMPLINGMODE, engine?: Engine, reusable?: boolean, defines?: string, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT, vertexUrl: string = "postprocess", indexParameters?: any, blockCompilation = false) {
             if (camera != null) {
                 this._camera = camera;
                 this._scene = camera.getScene();
@@ -146,7 +147,7 @@
 
                 this._scene.postProcesses.push(this);
             }
-            else {
+            else if (engine) {
                 this._engine = engine;
                 this._engine.postProcesses.push(this);
             }
@@ -195,7 +196,7 @@
                 uniforms || this._parameters,
                 samplers || this._samplers, 
                 defines !== undefined ? defines : "",
-                null,
+                undefined,
                 onCompiled,
                 onError,
                 indexParameters || this._indexParameters
@@ -212,18 +213,19 @@
         }
 
         public activate(camera: Camera, sourceTexture?: InternalTexture, forceDepthStencil?: boolean): void {            
-            if (!this._shareOutputWithPostProcess && !this._forcedOutputTexture) {
-                camera = camera || this._camera;
+            camera = camera || this._camera;
+            
+            var scene = camera.getScene();
+            var engine = scene.getEngine();
+            var maxSize = engine.getCaps().maxTextureSize;
 
-                var scene = camera.getScene();
-                var engine = scene.getEngine();
-                var maxSize = engine.getCaps().maxTextureSize;
+            var requiredWidth = ((sourceTexture ? sourceTexture.width : this._engine.getRenderWidth(true)) * <number>this._options) | 0;
+            var requiredHeight = ((sourceTexture ? sourceTexture.height : this._engine.getRenderHeight(true)) * <number>this._options) | 0;
 
-                var requiredWidth = ((sourceTexture ? sourceTexture.width : this._engine.getRenderWidth(true)) * <number>this._options) | 0;
-                var requiredHeight = ((sourceTexture ? sourceTexture.height : this._engine.getRenderHeight(true)) * <number>this._options) | 0;
+            var desiredWidth = ((<PostProcessOptions>this._options).width || requiredWidth);
+            var desiredHeight = (<PostProcessOptions>this._options).height || requiredHeight;
 
-                var desiredWidth = ((<PostProcessOptions>this._options).width || requiredWidth);
-                var desiredHeight = (<PostProcessOptions>this._options).height || requiredHeight;
+            if (!this._shareOutputWithPostProcess && !this._forcedOutputTexture) {
 
                 if (this.adaptScaleToCurrentViewport) {
                     let currentViewport = engine.currentViewport;
@@ -330,7 +332,7 @@
             return this.width / this.height;
         }
         
-        public apply(): Effect {
+        public apply(): Nullable<Effect> {
             // Check
             if (!this._effect || !this._effect.isReady())
                 return null;

+ 1 - 1
src/PostProcess/babylon.postProcessManager.ts

@@ -48,7 +48,7 @@
         }
         
         // Methods
-        public _prepareFrame(sourceTexture?: InternalTexture, postProcesses?: PostProcess[]): boolean {
+        public _prepareFrame(sourceTexture: Nullable<InternalTexture> = null, postProcesses: Nullable<PostProcess[]> = null): boolean {
             var postProcesses = postProcesses || this._scene.activeCamera._postProcesses;
 
             if (postProcesses.length === 0 || !this._scene.postProcessesEnabled) {

+ 21 - 17
src/Rendering/babylon.renderingGroup.ts

@@ -8,8 +8,8 @@
         private _particleSystems = new SmartArray<IParticleSystem>(256);
         private _spriteManagers = new SmartArray<SpriteManager>(256);        
 
-        private _opaqueSortCompareFn: (a: SubMesh, b: SubMesh) => number;
-        private _alphaTestSortCompareFn: (a: SubMesh, b: SubMesh) => number;
+        private _opaqueSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number>;
+        private _alphaTestSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number>;
         private _transparentSortCompareFn: (a: SubMesh, b: SubMesh) => number;
         
         private _renderOpaque: (subMeshes: SmartArray<SubMesh>) => void;
@@ -24,7 +24,7 @@
          * Set the opaque sort comparison function.
          * If null the sub meshes will be render in the order they were created 
          */
-        public set opaqueSortCompareFn(value: (a: SubMesh, b: SubMesh) => number) {
+        public set opaqueSortCompareFn(value: Nullable<(a: SubMesh, b: SubMesh) => number>) {
             this._opaqueSortCompareFn = value;
             if (value) {
                 this._renderOpaque = this.renderOpaqueSorted;
@@ -38,7 +38,7 @@
          * Set the alpha test sort comparison function.
          * If null the sub meshes will be render in the order they were created 
          */
-        public set alphaTestSortCompareFn(value: (a: SubMesh, b: SubMesh) => number) {
+        public set alphaTestSortCompareFn(value: Nullable<(a: SubMesh, b: SubMesh) => number>) {
             this._alphaTestSortCompareFn = value;
             if (value) {
                 this._renderAlphaTest = this.renderAlphaTestSorted;
@@ -52,7 +52,7 @@
          * Set the transparent sort comparison function.
          * If null the sub meshes will be render in the order they were created 
          */
-        public set transparentSortCompareFn(value: (a: SubMesh, b: SubMesh) => number) {
+        public set transparentSortCompareFn(value: Nullable<(a: SubMesh, b: SubMesh) => number>) {
             if (value) {
                 this._transparentSortCompareFn = value;
             }
@@ -70,9 +70,9 @@
          * @param transparentSortCompareFn The transparent sort comparison function. If null back to front + alpha index sort is applied
          */
         constructor(public index: number, scene: Scene,
-            opaqueSortCompareFn: (a: SubMesh, b: SubMesh) => number = null,
-            alphaTestSortCompareFn: (a: SubMesh, b: SubMesh) => number = null,
-            transparentSortCompareFn: (a: SubMesh, b: SubMesh) => number = null) {
+            opaqueSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null,
+            alphaTestSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null,
+            transparentSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null) {
             this._scene = scene;
 
             this.opaqueSortCompareFn = opaqueSortCompareFn;
@@ -85,7 +85,7 @@
          * @param customRenderFunction Used to override the default render behaviour of the group.
          * @returns true if rendered some submeshes.
          */
-        public render(customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>) => void, renderSprites: boolean, renderParticles: boolean, activeMeshes: AbstractMesh[]): void {
+        public render(customRenderFunction: Nullable<(opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>) => void>, renderSprites: boolean, renderParticles: boolean, activeMeshes: Nullable<AbstractMesh[]>): void {
             if (customRenderFunction) {
                 customRenderFunction(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, this._depthOnlySubMeshes);
                 return;
@@ -154,7 +154,7 @@
          * @param subMeshes The submeshes to render
          */
         private renderOpaqueSorted(subMeshes: SmartArray<SubMesh>): void {
-            return RenderingGroup.renderSorted(subMeshes, this._opaqueSortCompareFn, this._scene.activeCamera.globalPosition, false);
+            return RenderingGroup.renderSorted(subMeshes, this._opaqueSortCompareFn, this._scene.activeCamera, false);
         }
 
         /**
@@ -162,7 +162,7 @@
          * @param subMeshes The submeshes to render
          */
         private renderAlphaTestSorted(subMeshes: SmartArray<SubMesh>): void {
-            return RenderingGroup.renderSorted(subMeshes, this._alphaTestSortCompareFn, this._scene.activeCamera.globalPosition, false);
+            return RenderingGroup.renderSorted(subMeshes, this._alphaTestSortCompareFn, this._scene.activeCamera, false);
         }
 
         /**
@@ -170,7 +170,7 @@
          * @param subMeshes The submeshes to render
          */
         private renderTransparentSorted(subMeshes: SmartArray<SubMesh>): void {
-            return RenderingGroup.renderSorted(subMeshes, this._transparentSortCompareFn, this._scene.activeCamera.globalPosition, true);
+            return RenderingGroup.renderSorted(subMeshes, this._transparentSortCompareFn, this._scene.activeCamera, true);
         }
 
         /**
@@ -180,9 +180,10 @@
          * @param cameraPosition The camera position use to preprocess the submeshes to help sorting
          * @param transparent Specifies to activate blending if true
          */
-        private static renderSorted(subMeshes: SmartArray<SubMesh>, sortCompareFn: (a: SubMesh, b: SubMesh) => number, cameraPosition: Vector3, transparent: boolean): void {
+        private static renderSorted(subMeshes: SmartArray<SubMesh>, sortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number>, camera: Nullable<Camera>, transparent: boolean): void {
             let subIndex = 0;
             let subMesh: SubMesh;
+            let cameraPosition = camera ? camera.globalPosition : Vector3.Zero();
             for (; subIndex < subMeshes.length; subIndex++) {
                 subMesh = subMeshes.data[subIndex];
                 subMesh._alphaIndex = subMesh.getMesh().alphaIndex;
@@ -190,7 +191,10 @@
             }
 
             let sortedArray = subMeshes.data.slice(0, subMeshes.length);
-            sortedArray.sort(sortCompareFn);
+
+            if (sortCompareFn) {
+                sortedArray.sort(sortCompareFn);
+            }
 
             for (subIndex = 0; subIndex < sortedArray.length; subIndex++) {
                 subMesh = sortedArray[subIndex];
@@ -345,7 +349,7 @@
             this._particleSystems.push(particleSystem);
         }
 
-        private _renderParticles(activeMeshes: AbstractMesh[]): void {
+        private _renderParticles(activeMeshes: Nullable<AbstractMesh[]>): void {
             if (this._particleSystems.length === 0) {
                 return;
             }
@@ -356,7 +360,7 @@
             for (var particleIndex = 0; particleIndex < this._scene._activeParticleSystems.length; particleIndex++) {
                 var particleSystem = this._scene._activeParticleSystems.data[particleIndex];
 
-                if ((activeCamera.layerMask & particleSystem.layerMask) === 0) {
+                if ((activeCamera && activeCamera.layerMask & particleSystem.layerMask) === 0) {
                     continue;
                 }
 
@@ -379,7 +383,7 @@
             for (var id = 0; id < this._spriteManagers.length; id++) {
                 var spriteManager = this._spriteManagers.data[id];
 
-                if (((activeCamera.layerMask & spriteManager.layerMask) !== 0)) {
+                if (((activeCamera && activeCamera.layerMask & spriteManager.layerMask) !== 0)) {
                     spriteManager.render();
                 }
             }

+ 13 - 13
src/Rendering/babylon.renderingManager.ts

@@ -33,10 +33,10 @@
         private _currentIndex: number;
 
         private _autoClearDepthStencil: { [id:number]: RenderingManageAutoClearOptions } = {};
-        private _customOpaqueSortCompareFn: { [id:number]: (a: SubMesh, b: SubMesh) => number } = {};
-        private _customAlphaTestSortCompareFn: { [id:number]: (a: SubMesh, b: SubMesh) => number } = {};
-        private _customTransparentSortCompareFn: { [id:number]: (a: SubMesh, b: SubMesh) => number } = {};
-        private _renderinGroupInfo: RenderingGroupInfo = null;
+        private _customOpaqueSortCompareFn: { [id:number]: Nullable<(a: SubMesh, b: SubMesh) => number> } = {};
+        private _customAlphaTestSortCompareFn: { [id:number]: Nullable<(a: SubMesh, b: SubMesh) => number> } = {};
+        private _customTransparentSortCompareFn: { [id:number]: Nullable<(a: SubMesh, b: SubMesh) => number> } = {};
+        private _renderinGroupInfo: Nullable<RenderingGroupInfo> = null;
 
         constructor(scene: Scene) {
             this._scene = scene;
@@ -55,12 +55,12 @@
             this._depthStencilBufferAlreadyCleaned = true;
         }
 
-        public render(customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>) => void,
-            activeMeshes: AbstractMesh[], renderParticles: boolean, renderSprites: boolean): void {          
+        public render(customRenderFunction: Nullable<(opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>) => void>,
+            activeMeshes: Nullable<AbstractMesh[]>, renderParticles: boolean, renderSprites: boolean): void {          
                   
             // Check if there's at least on observer on the onRenderingGroupObservable and initialize things to fire it
             let observable = this._scene.onRenderingGroupObservable.hasObservers() ? this._scene.onRenderingGroupObservable : null;
-            let info: RenderingGroupInfo = null;
+            let info: Nullable<RenderingGroupInfo> = null;
             if (observable) {
                 if (!this._renderinGroupInfo) {
                     this._renderinGroupInfo = new RenderingGroupInfo();
@@ -90,7 +90,7 @@
                 let renderingGroupMask = 0;
 
                 // Fire PRECLEAR stage
-                if (observable) {
+                if (observable && info) {
                     renderingGroupMask = Math.pow(2, index);
                     info.renderStage = RenderingGroupInfo.STAGE_PRECLEAR;
                     info.renderingGroupId = index;
@@ -105,7 +105,7 @@
                     }
                 }
 
-                if (observable) {
+                if (observable && info) {
                     // Fire PREOPAQUE stage
                     info.renderStage = RenderingGroupInfo.STAGE_PREOPAQUE;
                     observable.notifyObservers(info, renderingGroupMask);
@@ -118,7 +118,7 @@
                     renderingGroup.render(customRenderFunction, renderSprites, renderParticles, activeMeshes);
 
                 // Fire POSTTRANSPARENT stage
-                if (observable) {
+                if (observable && info) {
                     info.renderStage = RenderingGroupInfo.STAGE_POSTTRANSPARENT;
                     observable.notifyObservers(info, renderingGroupMask);
                 }
@@ -190,9 +190,9 @@
          * @param transparentSortCompareFn The transparent queue comparison function use to sort.
          */
         public setRenderingOrder(renderingGroupId: number,
-            opaqueSortCompareFn: (a: SubMesh, b: SubMesh) => number = null,
-            alphaTestSortCompareFn: (a: SubMesh, b: SubMesh) => number = null,
-            transparentSortCompareFn: (a: SubMesh, b: SubMesh) => number = null) {
+            opaqueSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null,
+            alphaTestSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null,
+            transparentSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null) {
 
             this._customOpaqueSortCompareFn[renderingGroupId] = opaqueSortCompareFn;
             this._customAlphaTestSortCompareFn[renderingGroupId] = alphaTestSortCompareFn;

+ 27 - 19
src/Tools/babylon.database.ts

@@ -2,7 +2,7 @@ module BABYLON {
     export class Database {
         private callbackManifestChecked: (check: boolean) => any;
         private currentSceneUrl: string;
-        private db: IDBDatabase;
+        private db: Nullable<IDBDatabase>;
         private _enableSceneOffline: boolean;
         private _enableTexturesOffline: boolean;
         private manifestVersionFound: number;
@@ -163,14 +163,16 @@ module BABYLON {
                     // Initialization of the DB. Creating Scenes & Textures stores
                     request.onupgradeneeded = (event: IDBVersionChangeEvent) => {
                         this.db = (<any>(event.target)).result;
-                        try {
-                            this.db.createObjectStore("scenes", { keyPath: "sceneUrl" });
-                            this.db.createObjectStore("versions", { keyPath: "sceneUrl" });
-                            this.db.createObjectStore("textures", { keyPath: "textureUrl" });
-                        }
-                        catch (ex) {
-                            Tools.Error("Error while creating object stores. Exception: " + ex.message);
-                            handleError();
+                        if (this.db) {
+                            try {
+                                this.db.createObjectStore("scenes", { keyPath: "sceneUrl" });
+                                this.db.createObjectStore("versions", { keyPath: "sceneUrl" });
+                                this.db.createObjectStore("textures", { keyPath: "textureUrl" });
+                            }
+                            catch (ex) {
+                                Tools.Error("Error while creating object stores. Exception: " + ex.message);
+                                handleError();
+                            }
                         }
                     };
                 }
@@ -264,7 +266,9 @@ module BABYLON {
                         }
                     }
 
-                    image.src = blobTextureURL;
+                    if (blobTextureURL) {
+                        image.src = blobTextureURL;
+                    }
                 };
 
                 if (Database.IsUASupportingBlobStorage) { // Create XHR
@@ -275,7 +279,7 @@ module BABYLON {
                     xhr.responseType = "blob";
 
                     xhr.addEventListener("load",() => {
-                        if (xhr.status === 200) {
+                        if (xhr.status === 200 && this.db) {
                             // Blob as response (XHR2)
                             blob = xhr.response;
 
@@ -348,7 +352,7 @@ module BABYLON {
         }
 
         private _loadVersionFromDBAsync(url: string, callback: (version: number) => void, updateInDBCallback: () => void) {
-            if (this.isSupported) {
+            if (this.isSupported && this.db) {
                 var version: any;
                 try {
                     var transaction = this.db.transaction(["versions"]);
@@ -397,7 +401,7 @@ module BABYLON {
         }
 
         private _saveVersionIntoDBAsync(url: string, callback: (version: number) => void) {
-            if (this.isSupported && !this.hasReachedQuota) {
+            if (this.isSupported && !this.hasReachedQuota && this.db) {
                 try {
                     // Open a transaction to the database
                     var transaction = this.db.transaction(["versions"], "readwrite");
@@ -438,7 +442,7 @@ module BABYLON {
             }
         }
 
-        public loadFileFromDB(url: string, sceneLoaded: (data: any) => void, progressCallBack: (data: any) => void, errorCallback: () => void, useArrayBuffer?: boolean) {
+        public loadFileFromDB(url: string, sceneLoaded: (data: any) => void, progressCallBack?: (data: any) => void, errorCallback?: () => void, useArrayBuffer?: boolean) {
             var completeUrl = Database.ReturnFullUrlLocation(url);
 
             var saveAndLoadFile = () => {
@@ -456,13 +460,15 @@ module BABYLON {
                     }
                 }
                 else {
-                    errorCallback();
+                    if (errorCallback) {
+                        errorCallback();
+                    }
                 }
             });
         }
 
         private _loadFileFromDBAsync(url: string, callback: (data?: any) => void, notInDBCallback: () => void, useArrayBuffer?: boolean) {
-            if (this.isSupported) {
+            if (this.isSupported && this.db) {
                 var targetStore: string;
                 if (url.indexOf(".babylon") !== -1) {
                     targetStore = "scenes";
@@ -504,7 +510,7 @@ module BABYLON {
             }
         }
 
-        private _saveFileIntoDBAsync(url: string, callback: (data?: any) => void, progressCallback: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any, useArrayBuffer?: boolean) {
+        private _saveFileIntoDBAsync(url: string, callback: (data?: any) => void, progressCallback?: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any, useArrayBuffer?: boolean) {
             if (this.isSupported) {
                 var targetStore: string;
                 if (url.indexOf(".babylon") !== -1) {
@@ -523,7 +529,9 @@ module BABYLON {
                     xhr.responseType = "arraybuffer";
                 }
 
-                xhr.onprogress = progressCallback;
+                if (progressCallback) {
+                    xhr.onprogress = progressCallback;
+                }
 
                 xhr.addEventListener("load",() => {
                     if (xhr.status === 200 || Tools.ValidateXHRData(xhr, !useArrayBuffer ? 1 : 6)) {
@@ -531,7 +539,7 @@ module BABYLON {
                         //fileData = xhr.responseText;
                         fileData = !useArrayBuffer ? xhr.responseText : xhr.response;
 
-                        if (!this.hasReachedQuota) {
+                        if (!this.hasReachedQuota && this.db) {
                             // Open a transaction to the database
                             var transaction = this.db.transaction([targetStore], "readwrite");
 

+ 42 - 26
src/Tools/babylon.tools.ts

@@ -136,6 +136,7 @@
                     pot = Tools.NearestPOT(value);
                     break;
                 case Engine.SCALEMODE_CEILING:
+                default:
                     pot = Tools.CeilingPOT(value);
                     break;
             }
@@ -202,7 +203,7 @@
             return "data:image/png;base64," + output;
         }
 
-        public static ExtractMinAndMaxIndexed(positions: number[] | Float32Array, indices: IndicesArray, indexStart: number, indexCount: number, bias: Vector2 = null): { minimum: Vector3; maximum: Vector3 } {
+        public static ExtractMinAndMaxIndexed(positions: number[] | Float32Array, indices: IndicesArray, indexStart: number, indexCount: number, bias: Nullable<Vector2> = null): { minimum: Vector3; maximum: Vector3 } {
             var minimum = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             var maximum = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 
@@ -228,7 +229,7 @@
             };
         }
 
-        public static ExtractMinAndMax(positions: number[] | Float32Array, start: number, count: number, bias: Vector2 = null, stride?: number): { minimum: Vector3; maximum: Vector3 } {
+        public static ExtractMinAndMax(positions: number[] | Float32Array, start: number, count: number, bias: Nullable<Vector2> = null, stride?: number): { minimum: Vector3; maximum: Vector3 } {
             var minimum = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             var maximum = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 
@@ -258,7 +259,7 @@
             };
         }
 
-        public static Vector2ArrayFeeder(array: Array<Vector2> | Float32Array): (i: number) => Vector2 {
+        public static Vector2ArrayFeeder(array: Array<Vector2> | Float32Array): (i: number) => Nullable<Vector2> {
             return (index: number) => {
                 let isFloatArray = ((<Float32Array>array).BYTES_PER_ELEMENT !== undefined);
                 let length = isFloatArray ? array.length / 2 : array.length;
@@ -276,7 +277,7 @@
             };
         }
 
-        public static ExtractMinAndMaxVector2(feeder: (index: number) => Vector2, bias: Vector2 = null): { minimum: Vector2; maximum: Vector2 } {
+        public static ExtractMinAndMaxVector2(feeder: (index: number) => Vector2, bias: Nullable<Vector2> = null): { minimum: Vector2; maximum: Vector2 } {
             var minimum = new Vector2(Number.MAX_VALUE, Number.MAX_VALUE);
             var maximum = new Vector2(-Number.MAX_VALUE, -Number.MAX_VALUE);
 
@@ -302,9 +303,9 @@
             };
         }
 
-        public static MakeArray(obj: any, allowsNullUndefined?: boolean): Array<any> {
+        public static MakeArray(obj: any, allowsNullUndefined?: boolean): Nullable<Array<any>> {
             if (allowsNullUndefined !== true && (obj === undefined || obj == null))
-                return undefined;
+                return null;
 
             return Array.isArray(obj) ? obj : [obj];
         }
@@ -402,7 +403,7 @@
             return url;
         }
 
-        public static LoadImage(url: any, onLoad: (img: HTMLImageElement) => void, onError: (message?: string, exception?: any) => void, database: Database): HTMLImageElement {
+        public static LoadImage(url: any, onLoad: (img: HTMLImageElement) => void, onError: (message?: string, exception?: any) => void, database: Nullable<Database>): HTMLImageElement {
             if (url instanceof ArrayBuffer) {
                 url = Tools.EncodeArrayBufferTobase64(url);
             }
@@ -437,7 +438,9 @@
             };
 
             var loadFromIndexedDB = () => {
-                database.loadImageFromDB(url, img);
+                if (database) {
+                    database.loadImageFromDB(url, img);
+                }
             };
 
 
@@ -464,7 +467,7 @@
                             img.src = blobURL;
                         }
                         catch (e) {
-                            img.src = null;
+                            img.src = "";
                         }
                     }
                     else {
@@ -478,7 +481,7 @@
         }
 
         //ANY
-        public static LoadFile(url: string, callback: (data: any) => void, progressCallBack?: (data: any) => void, database?: Database, useArrayBuffer?: boolean, onError?: (request: XMLHttpRequest, exception?: any) => void): void {
+        public static LoadFile(url: string, callback: (data: any) => void, progressCallBack?: (data: any) => void, database?: Database, useArrayBuffer?: boolean, onError?: (request?: XMLHttpRequest, exception?: any) => void): void {
             url = Tools.CleanUrl(url);
 
             url = Tools.PreprocessUrl(url);
@@ -492,12 +495,14 @@
                     request.responseType = "arraybuffer";
                 }
 
-                request.onprogress = progressCallBack;
+                if (progressCallBack) {
+                    request.onprogress = progressCallBack;
+                }
 
                 request.onreadystatechange = () => {
                     // In case of undefined state in some browsers.
                     if (request.readyState === (XMLHttpRequest.DONE || 4)) {
-                        request.onreadystatechange = null;//some browsers have issues where onreadystatechange can be called multiple times with the same value
+                        request.onreadystatechange = () => {};//some browsers have issues where onreadystatechange can be called multiple times with the same value
 
                         if (request.status >= 200 && request.status < 300 || (!Tools.IsWindowObjectExist() && (request.status === 0))) {
                             callback(!useArrayBuffer ? request.responseText : request.response);
@@ -516,7 +521,9 @@
             };
 
             var loadFromIndexedDB = () => {
-                database.loadFileFromDB(url, callback, progressCallBack, noIndexedDB, useArrayBuffer);
+                if (database) {
+                    database.loadFileFromDB(url, callback, progressCallBack, noIndexedDB, useArrayBuffer);
+                }
             };
 
             if (url.indexOf("file:") !== -1) {
@@ -580,7 +587,7 @@
             reader.readAsDataURL(fileToLoad);
         }
 
-        public static ReadFile(fileToLoad: File, callback: (data: any) => void, progressCallBack: (this: MSBaseReader, ev: ProgressEvent) => any, useArrayBuffer?: boolean): void {
+        public static ReadFile(fileToLoad: File, callback: (data: any) => void, progressCallBack?: (this: MSBaseReader, ev: ProgressEvent) => any, useArrayBuffer?: boolean): void {
             var reader = new FileReader();
             reader.onerror = e => {
                 Tools.Log("Error while reading file: " + fileToLoad.name);
@@ -590,7 +597,10 @@
                 //target doesn't have result from ts 1.3
                 callback((<any>e.target)['result']);
             };
-            reader.onprogress = progressCallBack;
+
+            if (progressCallBack) {
+                reader.onprogress = progressCallBack;
+            }
             if (!useArrayBuffer) {
                 // Asynchronous read
                 reader.readAsText(fileToLoad);
@@ -740,13 +750,15 @@
             screenshotCanvas.height = height;
             var context = screenshotCanvas.getContext('2d');
 
-            // Copy the pixels to a 2D canvas
-            var imageData = context.createImageData(width, height);
-            var castData = <any>(imageData.data);
-            castData.set(data);
-            context.putImageData(imageData, 0, 0);
+            if (context) {
+                // Copy the pixels to a 2D canvas
+                var imageData = context.createImageData(width, height);
+                var castData = <any>(imageData.data);
+                castData.set(data);
+                context.putImageData(imageData, 0, 0);
 
-            Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
+                Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
+            }
         }
 
         static EncodeScreenshotCanvasData(successCallback?: (data: string) => void, mimeType: string = "image/png") {
@@ -766,7 +778,9 @@
                     window.document.body.appendChild(a);
 
                     a.addEventListener("click", () => {
-                        a.parentElement.removeChild(a);
+                        if (a.parentElement) {
+                            a.parentElement.removeChild(a);
+                        }
                     });
                     a.click();
 
@@ -833,7 +847,9 @@
             var offsetX = Math.max(0, width - newWidth) / 2;
             var offsetY = Math.max(0, height - newHeight) / 2;
 
-            renderContext.drawImage(engine.getRenderingCanvas(), offsetX, offsetY, newWidth, newHeight);
+            if (renderContext) {
+                renderContext.drawImage(engine.getRenderingCanvas(), offsetX, offsetY, newWidth, newHeight);
+            }
 
             Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
         }
@@ -875,7 +891,7 @@
             }
 
             var scene = camera.getScene();
-            var previousCamera: Camera = null;
+            var previousCamera: Nullable<Camera> = null;
 
             if (scene.activeCamera !== camera) {
                 previousCamera = scene.activeCamera;
@@ -1200,7 +1216,7 @@
             return name;
         }
 
-        public static First<T>(array: Array<T>, predicate: (item: T) => boolean): T {
+        public static First<T>(array: Array<T>, predicate: (item: T) => boolean): Nullable<T> {
             for (let el of array) {
                 if (predicate(el)) {
                     return el;
@@ -1216,7 +1232,7 @@
          * @param object the object to get the class name from
          * @return a string that can have two forms: "moduleName.className" if module was specified when the class' Name was registered or "className" if there was not module specified.
          */
-        public static getFullClassName(object: any, isType: boolean = false): string {
+        public static getFullClassName(object: any, isType: boolean = false): Nullable<string> {
             let className = null;
             let moduleName = null;
 

+ 2 - 3
src/babylon.mixins.ts

@@ -34,7 +34,7 @@ interface WebGLRenderingContext {
     vertexAttribDivisor(index: number, divisor: number): void;
 
     createVertexArray(): any;
-    bindVertexArray(vao: WebGLVertexArrayObject): void;
+    bindVertexArray(vao: Nullable<WebGLVertexArrayObject>): void;
     deleteVertexArray(vao: WebGLVertexArrayObject): void;
 
     blitFramebuffer(srcX0: number, srcY0: number, srcX1: number, srcY1: number, dstX0: number, dstY0: number, dstX1: number, dstY1: number, mask: number, filter: number): void;
@@ -119,7 +119,7 @@ interface WebGLBuffer {
 }
 
 interface WebGLProgram {
-    __SPECTOR_rebuildProgram(vertexSourceCode: string, fragmentSourceCode: string, onCompiled: (program: WebGLProgram) => void, onError: (message: string) => void): void;
+    __SPECTOR_rebuildProgram: Nullable<(vertexSourceCode: string, fragmentSourceCode: string, onCompiled: (program: WebGLProgram) => void, onError: (message: string) => void) => void>;
 }
 
 interface MouseEvent {
@@ -139,7 +139,6 @@ interface MSStyleCSSProperties {
 interface Navigator {
     getVRDisplays: () => any;
     mozGetVRDevices: (any: any) => any;
-    isCocoonJS: boolean;
     getUserMedia: any;
     webkitGetUserMedia: any;
     mozGetUserMedia: any;

+ 18 - 12
src/babylon.node.ts

@@ -24,7 +24,7 @@ module BABYLON {
         public doNotSerialize = false;
 
         public animations = new Array<Animation>();
-        private _ranges: { [name: string]: AnimationRange; } = {};
+        private _ranges: { [name: string]: Nullable<AnimationRange> } = {};
 
         public onReady: (node: Node) => void;
 
@@ -38,10 +38,10 @@ module BABYLON {
         private _scene: Scene;
         public _cache: any;
 
-        private _parentNode: Node;
+        private _parentNode: Nullable<Node>;
         private _children: Node[];
 
-        public set parent(parent: Node) {
+        public set parent(parent: Nullable<Node>) {
             if (this._parentNode === parent) {
                 return;
             }
@@ -63,7 +63,7 @@ module BABYLON {
             }
         }
 
-        public get parent(): Node {
+        public get parent(): Nullable<Node> {
             return this._parentNode;
         }
 
@@ -139,7 +139,7 @@ module BABYLON {
             return this._behaviors;
         }
 
-        public getBehaviorByName(name: string): Behavior<Node> {
+        public getBehaviorByName(name: string): Nullable<Behavior<Node>> {
             for (var behavior of this._behaviors) {
                 if (behavior.name === name) {
                     return behavior;
@@ -181,7 +181,9 @@ module BABYLON {
         }
 
         public _markSyncedWithParent() {
-            this._parentRenderId = this.parent._currentRenderId;
+            if (this.parent) {
+                this._parentRenderId = this.parent._currentRenderId;
+            }
         }
 
         public isSynchronizedWithParent(): boolean {
@@ -343,7 +345,7 @@ module BABYLON {
             }
         }
 
-        public getAnimationByName(name: string): Animation {
+        public getAnimationByName(name: string): Nullable<Animation> {
             for (var i = 0; i < this.animations.length; i++) {
                 var animation = this.animations[i];
 
@@ -373,10 +375,10 @@ module BABYLON {
                     this.animations[i].deleteRange(name, deleteFrames);
                 }
             }
-            this._ranges[name] = undefined; // said much faster than 'delete this._range[name]' 
+            this._ranges[name] = null; // said much faster than 'delete this._range[name]' 
         }
 
-        public getAnimationRange(name: string): AnimationRange {
+        public getAnimationRange(name: string): Nullable<AnimationRange> {
             return this._ranges[name];
         }
 
@@ -384,7 +386,7 @@ module BABYLON {
             var range = this.getAnimationRange(name);
 
             if (!range) {
-                return null;
+                return;
             }
 
             this._scene.beginAnimation(this, range.from, range.to, loop, speedRatio, onAnimationEnd);
@@ -393,10 +395,14 @@ module BABYLON {
         public serializeAnimationRanges(): any {
             var serializationRanges = [];
             for (var name in this._ranges) {
+                var localRange = this._ranges[name];
+                if (!localRange) {
+                    continue;
+                }
                 var range: any = {};
                 range.name = name;
-                range.from = this._ranges[name].from;
-                range.to = this._ranges[name].to;
+                range.from = localRange.from;
+                range.to = localRange.to;
                 serializationRanges.push(range);
             }
             return serializationRanges;

+ 172 - 134
src/babylon.scene.ts

@@ -48,7 +48,7 @@
         /**
          * The camera currently used for the rendering pass
          */
-        camera: Camera;
+        camera: Nullable<Camera>;
 
         /**
          * The ID of the renderingGroup being processed
@@ -218,11 +218,13 @@
 
         private _onBeforeRenderObserver: Observer<Scene>;
         /** A function to be executed before rendering this scene */
-        public set beforeRender(callback: () => void) {
+        public set beforeRender(callback: Nullable<() => void>) {
             if (this._onBeforeRenderObserver) {
                 this.onBeforeRenderObservable.remove(this._onBeforeRenderObserver);
             }
-            this._onBeforeRenderObserver = this.onBeforeRenderObservable.add(callback);
+            if (callback) {
+                this._onBeforeRenderObserver = this.onBeforeRenderObservable.add(callback);
+            }
         }
 
         /**
@@ -233,11 +235,14 @@
 
         private _onAfterRenderObserver: Observer<Scene>;
         /** A function to be executed after rendering this scene */
-        public set afterRender(callback: () => void) {
+        public set afterRender(callback: Nullable<() => void>) {
             if (this._onAfterRenderObserver) {
                 this.onAfterRenderObservable.remove(this._onAfterRenderObserver);
             }
-            this._onAfterRenderObserver = this.onAfterRenderObservable.add(callback);
+
+            if (callback) {
+                this._onAfterRenderObserver = this.onAfterRenderObservable.add(callback);
+            }
         }
 
         /**
@@ -363,7 +368,7 @@
         public onPointerPick: (evt: PointerEvent, pickInfo: PickingInfo) => void;
 
         // Gamepads
-        private _gamepadManager: GamepadManager;
+        private _gamepadManager: Nullable<GamepadManager>;
 
         public get gamepadManager(): GamepadManager {
             if (!this._gamepadManager) {
@@ -398,7 +403,7 @@
         public static ExclusiveDoubleClickMode = false;
 
         private _initClickEvent: (obs1: Observable<PointerInfoPre>, obs2: Observable<PointerInfo>, evt: PointerEvent, cb: (clickInfo: ClickInfo, pickResult: PickingInfo) => void) => void;
-        private _initActionManager: (act: ActionManager, clickInfo: ClickInfo) => ActionManager;
+        private _initActionManager: (act: Nullable<ActionManager>, clickInfo: ClickInfo) => Nullable<ActionManager>;
         private _delayedSimpleClick: (btn: number, clickInfo: ClickInfo, cb: (clickInfo: ClickInfo, pickResult: PickingInfo) => void) => void;
         private _delayedSimpleClickTimeout: number;
         private _previousDelayedSimpleClickTimeout: number;
@@ -406,13 +411,13 @@
 
         private _previousButtonPressed: number;
         private _previousHasSwiped = false;
-        private _currentPickResult: PickingInfo = null;
-        private _previousPickResult: PickingInfo = null;
+        private _currentPickResult: Nullable<PickingInfo> = null;
+        private _previousPickResult: Nullable<PickingInfo> = null;
         private _totalPointersPressed = 0;
         private _doubleClickOccured = false;
 
         /** Define this parameter if you are using multiple cameras and you want to specify which one should be used for pointer position */
-        public cameraToUseForPointers: Camera = null;
+        public cameraToUseForPointers: Nullable<Camera> = null;
         private _pointerX: number;
         private _pointerY: number;
         private _unTranslatedPointerX: number;
@@ -557,7 +562,7 @@
         /** All of the active cameras added to this scene. */
         public activeCameras = new Array<Camera>();
         /** The current active camera */
-        public activeCamera: Camera;
+        public activeCamera: Nullable<Camera>;
 
         // Meshes
         /**
@@ -736,9 +741,9 @@
         private _animationTime: number = 0;
         public animationTimeScale: number = 1;
 
-        public _cachedMaterial: Material;
-        public _cachedEffect: Effect;
-        public _cachedVisibility: number;
+        public _cachedMaterial: Nullable<Material>;
+        public _cachedEffect: Nullable<Effect>;
+        public _cachedVisibility: Nullable<number>;
 
         private _renderId = 0;
         private _executeWhenReadyTimeoutId = -1;
@@ -749,7 +754,7 @@
         private _alternateViewUpdateFlag = -1;
         private _alternateProjectionUpdateFlag = -1;
 
-        public _toBeDisposed = new SmartArray<IDisposable>(256);
+        public _toBeDisposed = new SmartArray<Nullable<IDisposable>>(256);
         private _pendingData = new Array();
 
         private _activeMeshes = new SmartArray<AbstractMesh>(256);
@@ -760,7 +765,7 @@
         private _softwareSkinnedMeshes = new SmartArray<Mesh>(32);
 
         private _renderingManager: RenderingManager;
-        private _physicsEngine: PhysicsEngine;
+        private _physicsEngine: Nullable<PhysicsEngine>;
 
         public _activeAnimatables = new Array<Animatable>();
 
@@ -794,19 +799,19 @@
 
         private _selectionOctree: Octree<AbstractMesh>;
 
-        private _pointerOverMesh: AbstractMesh;
-        private _pointerOverSprite: Sprite;
+        private _pointerOverMesh: Nullable<AbstractMesh>;
+        private _pointerOverSprite: Nullable<Sprite>;
 
         private _debugLayer: DebugLayer;
 
-        private _depthRenderer: DepthRenderer;
-        private _geometryBufferRenderer: GeometryBufferRenderer;
+        private _depthRenderer: Nullable<DepthRenderer>;
+        private _geometryBufferRenderer: Nullable<GeometryBufferRenderer>;
 
-        private _pickedDownMesh: AbstractMesh;
-        private _pickedUpMesh: AbstractMesh;
-        private _pickedDownSprite: Sprite;
+        private _pickedDownMesh: Nullable<AbstractMesh>;
+        private _pickedUpMesh: Nullable<AbstractMesh>;
+        private _pickedDownSprite: Nullable<Sprite>;
         private _externalData: StringDictionary<Object>;
-        private _uid: string;
+        private _uid: Nullable<string>;
 
         /**
          * @constructor
@@ -882,7 +887,7 @@
          * The mesh that is currently under the pointer.
          * @return {BABYLON.AbstractMesh} mesh under the pointer/mouse cursor or null if none.
          */
-        public get meshUnderPointer(): AbstractMesh {
+        public get meshUnderPointer(): Nullable<AbstractMesh> {
             return this._pointerOverMesh;
         }
 
@@ -902,15 +907,15 @@
             return this._pointerY;
         }
 
-        public getCachedMaterial(): Material {
+        public getCachedMaterial(): Nullable<Material> {
             return this._cachedMaterial;
         }
 
-        public getCachedEffect(): Effect {
+        public getCachedEffect(): Nullable<Effect> {
             return this._cachedEffect;
         }
 
-        public getCachedVisibility(): number {
+        public getCachedVisibility(): Nullable<number> {
             return this._cachedVisibility;
         }
 
@@ -1046,13 +1051,13 @@
         }
 
         private _createUbo(): void {
-            this._sceneUbo = new UniformBuffer(this._engine, null, true);
+            this._sceneUbo = new UniformBuffer(this._engine, undefined, true);
             this._sceneUbo.addUniform("viewProjection", 16);
             this._sceneUbo.addUniform("view", 16);
         }
 
         private _createAlternateUbo(): void {
-            this._alternateSceneUbo = new UniformBuffer(this._engine, null, true);
+            this._alternateSceneUbo = new UniformBuffer(this._engine, undefined, true);
             this._alternateSceneUbo.addUniform("viewProjection", 16);
             this._alternateSceneUbo.addUniform("view", 16);
         }
@@ -1069,7 +1074,7 @@
             return this._processPointerMove(pickResult, evt);
         }
 
-        private _processPointerMove(pickResult: PickingInfo, evt: PointerEvent): Scene {
+        private _processPointerMove(pickResult: Nullable<PickingInfo>, evt: PointerEvent): Scene {
             
             var canvas = this._engine.getRenderingCanvas();
 
@@ -1078,7 +1083,7 @@
 
                 this.setPointerOverMesh(pickResult.pickedMesh);
 
-                if (this._pointerOverMesh.actionManager && this._pointerOverMesh.actionManager.hasPointerTriggers) {
+                if (this._pointerOverMesh && this._pointerOverMesh.actionManager && this._pointerOverMesh.actionManager.hasPointerTriggers) {
                     if (this._pointerOverMesh.actionManager.hoverCursor) {
                         canvas.style.cursor = this._pointerOverMesh.actionManager.hoverCursor;
                     } else {
@@ -1090,11 +1095,11 @@
             } else {
                 this.setPointerOverMesh(null);
                 // Sprites
-                pickResult = this.pickSprite(this._unTranslatedPointerX, this._unTranslatedPointerY, this._spritePredicate, false, this.cameraToUseForPointers);
+                pickResult = this.pickSprite(this._unTranslatedPointerX, this._unTranslatedPointerY, this._spritePredicate, false, this.cameraToUseForPointers || undefined);
 
                 if (pickResult && pickResult.hit && pickResult.pickedSprite) {
                     this.setPointerOverSprite(pickResult.pickedSprite);
-                    if (this._pointerOverSprite.actionManager && this._pointerOverSprite.actionManager.hoverCursor) {
+                    if (this._pointerOverSprite && this._pointerOverSprite.actionManager && this._pointerOverSprite.actionManager.hoverCursor) {
                         canvas.style.cursor = this._pointerOverSprite.actionManager.hoverCursor;
                     } else {
                         canvas.style.cursor = this.hoverCursor;
@@ -1106,14 +1111,16 @@
                 }
             }
 
-            if (this.onPointerMove) {
-                this.onPointerMove(evt, pickResult);
-            }
+            if (pickResult) {
+                if (this.onPointerMove) {
+                    this.onPointerMove(evt, pickResult);
+                }
 
-            if (this.onPointerObservable.hasObservers()) {
-                let type = evt.type === "mousewheel" || evt.type === "DOMMouseScroll" ? PointerEventTypes.POINTERWHEEL : PointerEventTypes.POINTERMOVE;
-                let pi = new PointerInfo(type, evt, pickResult);
-                this.onPointerObservable.notifyObservers(pi, type);
+                if (this.onPointerObservable.hasObservers()) {
+                    let type = evt.type === "mousewheel" || evt.type === "DOMMouseScroll" ? PointerEventTypes.POINTERWHEEL : PointerEventTypes.POINTERMOVE;
+                    let pi = new PointerInfo(type, evt, pickResult);
+                    this.onPointerObservable.notifyObservers(pi, type);
+                }
             }
 
             return this;            
@@ -1129,7 +1136,7 @@
             return this._processPointerDown(pickResult, evt);
         }        
 
-        private _processPointerDown(pickResult: PickingInfo, evt: PointerEvent): Scene {
+        private _processPointerDown(pickResult: Nullable<PickingInfo>, evt: PointerEvent): Scene {
             if (pickResult && pickResult.hit && pickResult.pickedMesh) {
                 this._pickedDownMesh = pickResult.pickedMesh;
                 var actionManager = pickResult.pickedMesh.actionManager;
@@ -1169,14 +1176,16 @@
                 }
             }
 
-            if (this.onPointerDown) {
-                this.onPointerDown(evt, pickResult);
-            }
+            if (pickResult) {
+                if (this.onPointerDown) {
+                    this.onPointerDown(evt, pickResult);
+                }
 
-            if (this.onPointerObservable.hasObservers()) {
-                let type = PointerEventTypes.POINTERDOWN;
-                let pi = new PointerInfo(type, evt, pickResult);
-                this.onPointerObservable.notifyObservers(pi, type);
+                if (this.onPointerObservable.hasObservers()) {
+                    let type = PointerEventTypes.POINTERDOWN;
+                    let pi = new PointerInfo(type, evt, pickResult);
+                    this.onPointerObservable.notifyObservers(pi, type);
+                }
             }
 
             return this;
@@ -1262,7 +1271,7 @@
         * @param attachMove defines if you want to attach events to pointermove
         */
         public attachControl(attachUp = true, attachDown = true, attachMove = true) {
-            this._initActionManager = (act: ActionManager, clickInfo: ClickInfo): ActionManager => {
+            this._initActionManager = (act: Nullable<ActionManager>, clickInfo: ClickInfo): Nullable<ActionManager> => {
                 if (!this._meshPickProceed) {
                     let pickResult = this.pick(this._unTranslatedPointerX, this._unTranslatedPointerY, this.pointerDownPredicate, false, this.cameraToUseForPointers);
                     this._currentPickResult = pickResult;
@@ -1288,7 +1297,7 @@
             this._initClickEvent = (obs1: Observable<PointerInfoPre>, obs2: Observable<PointerInfo>, evt: PointerEvent, cb: (clickInfo: ClickInfo, pickResult: PickingInfo) => void): void => {
                 let clickInfo = new ClickInfo();
                 this._currentPickResult = null;
-                let act;
+                let act: Nullable<ActionManager> = null;
 
                 let checkPicking = obs1.hasSpecificMask(PointerEventTypes.POINTERPICK) || obs2.hasSpecificMask(PointerEventTypes.POINTERPICK)
                     || obs1.hasSpecificMask(PointerEventTypes.POINTERTAP) || obs2.hasSpecificMask(PointerEventTypes.POINTERTAP)
@@ -1322,6 +1331,7 @@
                             if (new Date().getTime() - this._previousStartingPointerTime > Scene.DoubleClickDelay ||
                                 btn !== this._previousButtonPressed) {
                                 clickInfo.singleClick = true;
+
                                 cb(clickInfo, this._currentPickResult);
                             }
                         }
@@ -1372,6 +1382,7 @@
                                             clearTimeout(this._previousDelayedSimpleClickTimeout);
                                         }
                                         this._previousDelayedSimpleClickTimeout = this._delayedSimpleClickTimeout;
+
                                         cb(clickInfo, this._previousPickResult);
                                     }
                                     else {
@@ -1472,7 +1483,7 @@
                 // Sprites
                 this._pickedDownSprite = null;
                 if (this.spriteManagers.length > 0) {
-                    pickResult = this.pickSprite(this._unTranslatedPointerX, this._unTranslatedPointerY, this._spritePredicate, false, this.cameraToUseForPointers);
+                    pickResult = this.pickSprite(this._unTranslatedPointerX, this._unTranslatedPointerY, this._spritePredicate, false, this.cameraToUseForPointers || undefined);
 
                     if (pickResult && pickResult.hit && pickResult.pickedSprite) {
                         if (pickResult.pickedSprite.actionManager) {
@@ -1562,20 +1573,22 @@
 
                     // Sprites
                     if (this.spriteManagers.length > 0) {
-                        pickResult = this.pickSprite(this._unTranslatedPointerX, this._unTranslatedPointerY, this._spritePredicate, false, this.cameraToUseForPointers);
-
-                        if (pickResult.hit && pickResult.pickedSprite) {
-                            if (pickResult.pickedSprite.actionManager) {
-                                pickResult.pickedSprite.actionManager.processTrigger(ActionManager.OnPickUpTrigger, ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, this, evt));
-                                if (pickResult.pickedSprite.actionManager) {
-                                    if (Math.abs(this._startingPointerPosition.x - this._pointerX) < Scene.DragMovementThreshold && Math.abs(this._startingPointerPosition.y - this._pointerY) < Scene.DragMovementThreshold) {
-                                        pickResult.pickedSprite.actionManager.processTrigger(ActionManager.OnPickTrigger, ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, this, evt));
+                        let spritePickResult = this.pickSprite(this._unTranslatedPointerX, this._unTranslatedPointerY, this._spritePredicate, false, this.cameraToUseForPointers || undefined);
+
+                        if (spritePickResult) {
+                            if (spritePickResult.hit && spritePickResult.pickedSprite) {
+                                if (spritePickResult.pickedSprite.actionManager) {
+                                    spritePickResult.pickedSprite.actionManager.processTrigger(ActionManager.OnPickUpTrigger, ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, this, evt));
+                                    if (spritePickResult.pickedSprite.actionManager) {
+                                        if (Math.abs(this._startingPointerPosition.x - this._pointerX) < Scene.DragMovementThreshold && Math.abs(this._startingPointerPosition.y - this._pointerY) < Scene.DragMovementThreshold) {
+                                            spritePickResult.pickedSprite.actionManager.processTrigger(ActionManager.OnPickTrigger, ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, this, evt));
+                                        }
                                     }
                                 }
                             }
-                        }
-                        if (this._pickedDownSprite && this._pickedDownSprite.actionManager && this._pickedDownSprite !== pickResult.pickedSprite) {
-                            this._pickedDownSprite.actionManager.processTrigger(ActionManager.OnPickOutTrigger, ActionEvent.CreateNewFromSprite(this._pickedDownSprite, this, evt));
+                            if (this._pickedDownSprite && this._pickedDownSprite.actionManager && this._pickedDownSprite !== spritePickResult.pickedSprite) {
+                                this._pickedDownSprite.actionManager.processTrigger(ActionManager.OnPickOutTrigger, ActionEvent.CreateNewFromSprite(this._pickedDownSprite, this, evt));
+                            }
                         }
                     }
                     this._previousPickResult = this._currentPickResult;
@@ -1844,7 +1857,7 @@
             return animatable;
         }
 
-        public getAnimatableByTarget(target: any): Animatable {
+        public getAnimatableByTarget(target: any): Nullable<Animatable> {
             for (var index = 0; index < this._activeAnimatables.length; index++) {
                 if (this._activeAnimatables[index].target === target) {
                     return this._activeAnimatables[index];
@@ -1929,7 +1942,7 @@
                 Frustum.GetPlanesToRef(this._transformMatrix, this._frustumPlanes);
             }
 
-            if (this.activeCamera._alternateCamera) {
+            if (this.activeCamera && this.activeCamera._alternateCamera) {
                 let otherCamera = this.activeCamera._alternateCamera;
                 otherCamera.getViewMatrix().multiplyToRef(otherCamera.getProjectionMatrix(), Tmp.Matrix[0]);
                 Frustum.GetRightPlaneToRef(Tmp.Matrix[0], this._frustumPlanes[3]); // Replace right plane by second camera right plane
@@ -2088,7 +2101,10 @@
          */
         public switchActiveCamera(newCamera: Camera, attachControl = true) {
             var canvas = this._engine.getRenderingCanvas();
-            this.activeCamera.detachControl(canvas);
+
+            if (this.activeCamera) {
+                this.activeCamera.detachControl(canvas);
+            }
             this.activeCamera = newCamera;
             if (attachControl) {
                 newCamera.attachControl(canvas);
@@ -2101,7 +2117,7 @@
          * @return {BABYLON.Camera|null} the new active camera or null if none found.
          * @see activeCamera
          */
-        public setActiveCameraByID(id: string): Camera {
+        public setActiveCameraByID(id: string): Nullable<Camera> {
             var camera = this.getCameraByID(id);
 
             if (camera) {
@@ -2118,7 +2134,7 @@
          * @return {BABYLON.Camera|null} the new active camera or null if none found.
          * @see activeCamera
          */
-        public setActiveCameraByName(name: string): Camera {
+        public setActiveCameraByName(name: string): Nullable<Camera> {
             var camera = this.getCameraByName(name);
 
             if (camera) {
@@ -2134,7 +2150,7 @@
          * @param {string} the material's ID
          * @return {BABYLON.Material|null} the material or null if none found.
          */
-        public getMaterialByID(id: string): Material {
+        public getMaterialByID(id: string): Nullable<Material> {
             for (var index = 0; index < this.materials.length; index++) {
                 if (this.materials[index].id === id) {
                     return this.materials[index];
@@ -2149,7 +2165,7 @@
          * @param {string} the material's name
          * @return {BABYLON.Material|null} the material or null if none found.
          */
-        public getMaterialByName(name: string): Material {
+        public getMaterialByName(name: string): Nullable<Material> {
             for (var index = 0; index < this.materials.length; index++) {
                 if (this.materials[index].name === name) {
                     return this.materials[index];
@@ -2159,7 +2175,7 @@
             return null;
         }
 
-        public getLensFlareSystemByName(name: string): LensFlareSystem {
+        public getLensFlareSystemByName(name: string): Nullable<LensFlareSystem> {
             for (var index = 0; index < this.lensFlareSystems.length; index++) {
                 if (this.lensFlareSystems[index].name === name) {
                     return this.lensFlareSystems[index];
@@ -2169,7 +2185,7 @@
             return null;
         }
 
-        public getLensFlareSystemByID(id: string): LensFlareSystem {
+        public getLensFlareSystemByID(id: string): Nullable<LensFlareSystem> {
             for (var index = 0; index < this.lensFlareSystems.length; index++) {
                 if (this.lensFlareSystems[index].id === id) {
                     return this.lensFlareSystems[index];
@@ -2179,7 +2195,7 @@
             return null;
         }
 
-        public getCameraByID(id: string): Camera {
+        public getCameraByID(id: string): Nullable<Camera> {
             for (var index = 0; index < this.cameras.length; index++) {
                 if (this.cameras[index].id === id) {
                     return this.cameras[index];
@@ -2189,7 +2205,7 @@
             return null;
         }
 
-        public getCameraByUniqueID(uniqueId: number): Camera {
+        public getCameraByUniqueID(uniqueId: number): Nullable<Camera> {
             for (var index = 0; index < this.cameras.length; index++) {
                 if (this.cameras[index].uniqueId === uniqueId) {
                     return this.cameras[index];
@@ -2204,7 +2220,7 @@
          * @param {string} the camera's name
          * @return {BABYLON.Camera|null} the camera or null if none found.
          */
-        public getCameraByName(name: string): Camera {
+        public getCameraByName(name: string): Nullable<Camera> {
             for (var index = 0; index < this.cameras.length; index++) {
                 if (this.cameras[index].name === name) {
                     return this.cameras[index];
@@ -2219,7 +2235,7 @@
          * @param {string} the bone's id
          * @return {BABYLON.Bone|null} the bone or null if not found
          */
-        public getBoneByID(id: string): Bone {
+        public getBoneByID(id: string): Nullable<Bone> {
             for (var skeletonIndex = 0; skeletonIndex < this.skeletons.length; skeletonIndex++) {
                 var skeleton = this.skeletons[skeletonIndex];
                 for (var boneIndex = 0; boneIndex < skeleton.bones.length; boneIndex++) {
@@ -2237,7 +2253,7 @@
         * @param {string} the bone's name
         * @return {BABYLON.Bone|null} the bone or null if not found
         */
-        public getBoneByName(name: string): Bone {
+        public getBoneByName(name: string): Nullable<Bone> {
             for (var skeletonIndex = 0; skeletonIndex < this.skeletons.length; skeletonIndex++) {
                 var skeleton = this.skeletons[skeletonIndex];
                 for (var boneIndex = 0; boneIndex < skeleton.bones.length; boneIndex++) {
@@ -2255,7 +2271,7 @@
          * @param {string} the light's name
          * @return {BABYLON.Light|null} the light or null if none found.
          */
-        public getLightByName(name: string): Light {
+        public getLightByName(name: string): Nullable<Light> {
             for (var index = 0; index < this.lights.length; index++) {
                 if (this.lights[index].name === name) {
                     return this.lights[index];
@@ -2270,7 +2286,7 @@
          * @param {string} the light's id
          * @return {BABYLON.Light|null} the light or null if none found.
          */
-        public getLightByID(id: string): Light {
+        public getLightByID(id: string): Nullable<Light> {
             for (var index = 0; index < this.lights.length; index++) {
                 if (this.lights[index].id === id) {
                     return this.lights[index];
@@ -2285,7 +2301,7 @@
          * @param {number} the light's unique id
          * @return {BABYLON.Light|null} the light or null if none found.
          */
-        public getLightByUniqueID(uniqueId: number): Light {
+        public getLightByUniqueID(uniqueId: number): Nullable<Light> {
             for (var index = 0; index < this.lights.length; index++) {
                 if (this.lights[index].uniqueId === uniqueId) {
                     return this.lights[index];
@@ -2301,7 +2317,7 @@
          * @param id {number} the particle system id
          * @return {BABYLON.IParticleSystem|null} the corresponding system or null if none found.
          */
-        public getParticleSystemByID(id: string): IParticleSystem {
+        public getParticleSystemByID(id: string): Nullable<IParticleSystem> {
             for (var index = 0; index < this.particleSystems.length; index++) {
                 if (this.particleSystems[index].id === id) {
                     return this.particleSystems[index];
@@ -2316,7 +2332,7 @@
          * @param {string} the geometry's id
          * @return {BABYLON.Geometry|null} the geometry or null if none found.
          */
-        public getGeometryByID(id: string): Geometry {
+        public getGeometryByID(id: string): Nullable<Geometry> {
             for (var index = 0; index < this._geometries.length; index++) {
                 if (this._geometries[index].id === id) {
                     return this._geometries[index];
@@ -2380,7 +2396,7 @@
          * @param {string} id - the id to search for
          * @return {BABYLON.AbstractMesh|null} the mesh found or null if not found at all.
          */
-        public getMeshByID(id: string): AbstractMesh {
+        public getMeshByID(id: string): Nullable<AbstractMesh> {
             for (var index = 0; index < this.meshes.length; index++) {
                 if (this.meshes[index].id === id) {
                     return this.meshes[index];
@@ -2401,7 +2417,7 @@
          * @param {number} uniqueId - the unique id to search for
          * @return {BABYLON.AbstractMesh|null} the mesh found or null if not found at all.
          */
-        public getMeshByUniqueID(uniqueId: number): AbstractMesh {
+        public getMeshByUniqueID(uniqueId: number): Nullable<AbstractMesh> {
             for (var index = 0; index < this.meshes.length; index++) {
                 if (this.meshes[index].uniqueId === uniqueId) {
                     return this.meshes[index];
@@ -2416,7 +2432,7 @@
          * @param {string} id - the id to search for
          * @return {BABYLON.AbstractMesh|null} the mesh found or null if not found at all.
          */
-        public getLastMeshByID(id: string): AbstractMesh {
+        public getLastMeshByID(id: string): Nullable<AbstractMesh> {
             for (var index = this.meshes.length - 1; index >= 0; index--) {
                 if (this.meshes[index].id === id) {
                     return this.meshes[index];
@@ -2431,7 +2447,7 @@
          * @param {string} id - the id to search for
          * @return {BABYLON.Node|null} the node found or null if not found at all.
          */
-        public getLastEntryByID(id: string): Node {
+        public getLastEntryByID(id: string): Nullable<Node> {
             var index: number;
             for (index = this.meshes.length - 1; index >= 0; index--) {
                 if (this.meshes[index].id === id) {
@@ -2454,7 +2470,7 @@
             return null;
         }
 
-        public getNodeByID(id: string): Node {
+        public getNodeByID(id: string): Nullable<Node> {
             var mesh = this.getMeshByID(id);
 
             if (mesh) {
@@ -2478,7 +2494,7 @@
             return bone;
         }
 
-        public getNodeByName(name: string): Node {
+        public getNodeByName(name: string): Nullable<Node> {
             var mesh = this.getMeshByName(name);
 
             if (mesh) {
@@ -2502,7 +2518,7 @@
             return bone;
         }
 
-        public getMeshByName(name: string): AbstractMesh {
+        public getMeshByName(name: string): Nullable<AbstractMesh> {
             for (var index = 0; index < this.meshes.length; index++) {
                 if (this.meshes[index].name === name) {
                     return this.meshes[index];
@@ -2512,7 +2528,7 @@
             return null;
         }
 
-        public getSoundByName(name: string): Sound {
+        public getSoundByName(name: string): Nullable<Sound> {
             var index: number;
             if (AudioEngine) {
                 for (index = 0; index < this.mainSoundTrack.soundCollection.length; index++) {
@@ -2533,7 +2549,7 @@
             return null;
         }
 
-        public getLastSkeletonByID(id: string): Skeleton {
+        public getLastSkeletonByID(id: string): Nullable<Skeleton> {
             for (var index = this.skeletons.length - 1; index >= 0; index--) {
                 if (this.skeletons[index].id === id) {
                     return this.skeletons[index];
@@ -2543,7 +2559,7 @@
             return null;
         }
 
-        public getSkeletonById(id: string): Skeleton {
+        public getSkeletonById(id: string): Nullable<Skeleton> {
             for (var index = 0; index < this.skeletons.length; index++) {
                 if (this.skeletons[index].id === id) {
                     return this.skeletons[index];
@@ -2553,7 +2569,7 @@
             return null;
         }
 
-        public getSkeletonByName(name: string): Skeleton {
+        public getSkeletonByName(name: string): Nullable<Skeleton> {
             for (var index = 0; index < this.skeletons.length; index++) {
                 if (this.skeletons[index].name === name) {
                     return this.skeletons[index];
@@ -2563,7 +2579,7 @@
             return null;
         }
 
-        public getMorphTargetManagerById(id: number): MorphTargetManager {
+        public getMorphTargetManagerById(id: number): Nullable<MorphTargetManager> {
             for (var index = 0; index < this.morphTargetManagers.length; index++) {
                 if (this.morphTargetManagers[index].uniqueId === id) {
                     return this.morphTargetManagers[index];
@@ -2582,7 +2598,7 @@
          * @param name The name of the highlight layer to look for.
          * @return The highlight layer if found otherwise null.
          */
-        public getHighlightLayerByName(name: string): HighlightLayer {
+        public getHighlightLayerByName(name: string): Nullable<HighlightLayer> {
             for (var index = 0; index < this.highlightLayers.length; index++) {
                 if (this.highlightLayers[index].name === name) {
                     return this.highlightLayers[index];
@@ -2622,7 +2638,7 @@
          * @param key the unique key that identifies the data
          * @return the associated data, if present (can be null), or undefined if not present
          */
-        public getExternalData<T>(key: string): T {
+        public getExternalData<T>(key: string): Nullable<T> {
             if (!this._externalData) {
                 return null;
             }
@@ -2703,6 +2719,11 @@
             if (this._activeMeshesFrozen && this._activeMeshes.length) {
                 return;
             }
+
+            if (!this.activeCamera) {
+                return;
+            }
+
             this.activeCamera._activeMeshes.reset();
             this._activeMeshes.reset();
             this._renderingManager.reset();
@@ -2831,6 +2852,9 @@
         }
 
         public updateTransformMatrix(force?: boolean): void {
+            if (!this.activeCamera) {
+                return;
+            }
             this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix(force));
         }
 
@@ -3042,7 +3066,9 @@
             }
 
             // Update camera
-            this.activeCamera.update();
+            if (this.activeCamera) {
+                this.activeCamera.update();
+            }
             
             // rig cameras
             for (var index = 0; index < camera._rigCameras.length; index++) {
@@ -3069,7 +3095,7 @@
 
                         if (areIntersecting && currentIntersectionInProgress === -1) {
                             if (action.trigger === ActionManager.OnIntersectionEnterTrigger) {
-                                action._executeCurrent(ActionEvent.CreateNew(sourceMesh, null, otherMesh));
+                                action._executeCurrent(ActionEvent.CreateNew(sourceMesh, undefined, otherMesh));
                                 sourceMesh._intersectionsInProgress.push(otherMesh);
                             } else if (action.trigger === ActionManager.OnIntersectionExitTrigger) {
                                 sourceMesh._intersectionsInProgress.push(otherMesh);
@@ -3079,7 +3105,7 @@
 
                             //is this trigger an exit trigger? execute an event.
                             if (action.trigger === ActionManager.OnIntersectionExitTrigger) {
-                                action._executeCurrent(ActionEvent.CreateNew(sourceMesh, null, otherMesh));
+                                action._executeCurrent(ActionEvent.CreateNew(sourceMesh, undefined, otherMesh));
                             }
 
                             //if this is an exit trigger, or no exit trigger exists, remove the id from the intersection in progress array.
@@ -3116,7 +3142,7 @@
 
             // Actions
             if (this.actionManager) {
-                this.actionManager.processTrigger(ActionManager.OnEveryFrameTrigger, null);
+                this.actionManager.processTrigger(ActionManager.OnEveryFrameTrigger);
             }
 
             //Simplification Queue
@@ -3301,7 +3327,10 @@
 
             // Cleaning
             for (var index = 0; index < this._toBeDisposed.length; index++) {
-                this._toBeDisposed.data[index].dispose();
+                var data = this._toBeDisposed.data[index];
+                if (data) {
+                    data.dispose();
+                }
                 this._toBeDisposed[index] = null;
             }
 
@@ -3328,7 +3357,7 @@
                 return;
             }
 
-            var listeningCamera: Camera;
+            var listeningCamera: Nullable<Camera>;
             var audioEngine = Engine.audioEngine;
 
             if (this.activeCameras.length > 0) {
@@ -3464,7 +3493,7 @@
             this._depthRenderer = null;
         }
 
-        public enableGeometryBufferRenderer(ratio: number = 1): GeometryBufferRenderer {
+        public enableGeometryBufferRenderer(ratio: number = 1): Nullable<GeometryBufferRenderer> {
             if (this._geometryBufferRenderer) {
                 return this._geometryBufferRenderer;
             }
@@ -3649,11 +3678,6 @@
             }
 
             this._engine.wipeCaches();
-            this._engine = null;
-
-            this.defaultMaterial = null;
-            this.multiMaterials = null;
-            this.materials = null;
         }
 
         public get isDisposed(): boolean {
@@ -3712,7 +3736,7 @@
         }
 
         // Picking
-        public createPickingRay(x: number, y: number, world: Matrix, camera: Camera, cameraViewSpace = false): Ray {
+        public createPickingRay(x: number, y: number, world: Matrix, camera: Nullable<Camera>, cameraViewSpace = false): Ray {
             var engine = this._engine;
 
             if (!camera) {
@@ -3732,7 +3756,7 @@
             //       return BABYLON.Ray.CreateNew(x / window.devicePixelRatio, y / window.devicePixelRatio, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
         }
 
-        public createPickingRayInCameraSpace(x: number, y: number, camera: Camera): Ray {
+        public createPickingRayInCameraSpace(x: number, y: number, camera?: Camera): Nullable<Ray> {
             if (!BABYLON.PickingInfo) {
                 return null;
             }
@@ -3756,7 +3780,7 @@
             return Ray.CreateNew(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
         }
 
-        private _internalPick(rayFunction: (world: Matrix) => Ray, predicate: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): PickingInfo {
+        private _internalPick(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo> {
             if (!BABYLON.PickingInfo) {
                 return null;
             }
@@ -3794,7 +3818,7 @@
             return pickingInfo || new PickingInfo();
         }
 
-        private _internalMultiPick(rayFunction: (world: Matrix) => Ray, predicate: (mesh: AbstractMesh) => boolean): PickingInfo[] {
+        private _internalMultiPick(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean): Nullable<PickingInfo[]> {
             if (!BABYLON.PickingInfo) {
                 return null;
             }
@@ -3825,14 +3849,19 @@
         }
 
 
-        private _internalPickSprites(ray: Ray, predicate?: (sprite: Sprite) => boolean, fastCheck?: boolean, camera?: Camera): PickingInfo {
+        private _internalPickSprites(ray: Ray, predicate?: (sprite: Sprite) => boolean, fastCheck?: boolean, camera?: Camera): Nullable<PickingInfo> {
             if (!BABYLON.PickingInfo) {
                 return null;
             }
 
             var pickingInfo = null;
 
-            camera = camera || this.activeCamera;
+            if (!camera) {
+                if (!this.activeCamera) {
+                    return null;
+                }
+                camera = this.activeCamera;
+            }
 
             if (this.spriteManagers.length > 0) {
                 for (var spriteIndex = 0; spriteIndex < this.spriteManagers.length; spriteIndex++) {
@@ -3867,8 +3896,8 @@
          * @param fastCheck Launch a fast check only using the bounding boxes. Can be set to null.
          * @param camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used
          */
-        public pick(x: number, y: number, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean, camera?: Camera): PickingInfo {
-            return this._internalPick(world => this.createPickingRay(x, y, world, camera), predicate, fastCheck);
+        public pick(x: number, y: number, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean, camera?: Nullable<Camera>): Nullable<PickingInfo> {
+            return this._internalPick(world => this.createPickingRay(x, y, world, camera || null), predicate, fastCheck);
         }
 
         /** Launch a ray to try to pick a sprite in the scene
@@ -3878,8 +3907,14 @@
          * @param fastCheck Launch a fast check only using the bounding boxes. Can be set to null.
          * @param camera camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used
          */
-        public pickSprite(x: number, y: number, predicate?: (sprite: Sprite) => boolean, fastCheck?: boolean, camera?: Camera): PickingInfo {
-            return this._internalPickSprites(this.createPickingRayInCameraSpace(x, y, camera), predicate, fastCheck, camera);
+        public pickSprite(x: number, y: number, predicate?: (sprite: Sprite) => boolean, fastCheck?: boolean, camera?: Camera): Nullable<PickingInfo> {
+            let ray = this.createPickingRayInCameraSpace(x, y, camera);
+
+            if (!ray) {
+                return null;
+            }
+
+            return this._internalPickSprites(ray, predicate, fastCheck, camera);
         }
 
         /** Use the given ray to pick a mesh in the scene
@@ -3887,7 +3922,7 @@
          * @param predicate Predicate function used to determine eligible sprites. Can be set to null. In this case, a sprite must have isPickable set to true
          * @param fastCheck Launch a fast check only using the bounding boxes. Can be set to null.
          */
-        public pickWithRay(ray: Ray, predicate: (mesh: Mesh) => boolean, fastCheck?: boolean): PickingInfo {
+        public pickWithRay(ray: Ray, predicate: (mesh: Mesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo> {
             return this._internalPick(world => {
                 if (!this._pickWithRayInverseMatrix) {
                     this._pickWithRayInverseMatrix = Matrix.Identity();
@@ -3904,8 +3939,8 @@
          * @param predicate Predicate function used to determine eligible meshes. Can be set to null. In this case, a mesh must be enabled, visible and with isPickable set to true
          * @param camera camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used
          */
-        public multiPick(x: number, y: number, predicate?: (mesh: AbstractMesh) => boolean, camera?: Camera): PickingInfo[] {
-            return this._internalMultiPick(world => this.createPickingRay(x, y, world, camera), predicate);
+        public multiPick(x: number, y: number, predicate?: (mesh: AbstractMesh) => boolean, camera?: Camera): Nullable<PickingInfo[]> {
+            return this._internalMultiPick(world => this.createPickingRay(x, y, world, camera || null), predicate);
         }
 
         /**
@@ -3913,7 +3948,7 @@
          * @param ray Ray to use
          * @param predicate Predicate function used to determine eligible meshes. Can be set to null. In this case, a mesh must be enabled, visible and with isPickable set to true
          */
-        public multiPickWithRay(ray: Ray, predicate: (mesh: Mesh) => boolean): PickingInfo[] {
+        public multiPickWithRay(ray: Ray, predicate: (mesh: Mesh) => boolean): Nullable<PickingInfo[]> {
             return this._internalMultiPick(world => {
                 if (!this._pickWithRayInverseMatrix) {
                     this._pickWithRayInverseMatrix = Matrix.Identity();
@@ -3923,7 +3958,7 @@
             }, predicate);
         }
 
-        public setPointerOverMesh(mesh: AbstractMesh): void {
+        public setPointerOverMesh(mesh: Nullable<AbstractMesh>): void {
             if (this._pointerOverMesh === mesh) {
                 return;
             }
@@ -3938,11 +3973,11 @@
             }
         }
 
-        public getPointerOverMesh(): AbstractMesh {
+        public getPointerOverMesh(): Nullable<AbstractMesh> {
             return this._pointerOverMesh;
         }
 
-        public setPointerOverSprite(sprite: Sprite): void {
+        public setPointerOverSprite(sprite: Nullable<Sprite>): void {
             if (this._pointerOverSprite === sprite) {
                 return;
             }
@@ -3957,12 +3992,12 @@
             }
         }
 
-        public getPointerOverSprite(): Sprite {
+        public getPointerOverSprite(): Nullable<Sprite> {
             return this._pointerOverSprite;
         }
 
         // Physics
-        public getPhysicsEngine(): PhysicsEngine {
+        public getPhysicsEngine(): Nullable<PhysicsEngine> {
             return this._physicsEngine;
         }
 
@@ -3993,7 +4028,7 @@
             }
 
             this._physicsEngine.dispose();
-            this._physicsEngine = undefined;
+            this._physicsEngine = null;
         }
 
         public isPhysicsEnabled(): boolean {
@@ -4002,8 +4037,11 @@
 
         public deleteCompoundImpostor(compound: any): void {
             var mesh: AbstractMesh = compound.parts[0].mesh;
-            mesh.physicsImpostor.dispose(/*true*/);
-            mesh.physicsImpostor = null;
+
+            if (mesh.physicsImpostor) {
+                mesh.physicsImpostor.dispose(/*true*/);
+                mesh.physicsImpostor = null;
+            }
         }
 
         // Misc.
@@ -4099,7 +4137,7 @@
             }
         }
 
-        public createDefaultSkybox(environmentTexture?: BaseTexture, pbr = false, scale = 1000, blur = 0): Mesh {
+        public createDefaultSkybox(environmentTexture?: BaseTexture, pbr = false, scale = 1000, blur = 0): Nullable<Mesh> {
             if (environmentTexture) {
                 this.environmentTexture = environmentTexture;
             }
@@ -4187,9 +4225,9 @@
          * @param transparentSortCompareFn The transparent queue comparison function use to sort.
          */
         public setRenderingOrder(renderingGroupId: number,
-            opaqueSortCompareFn: (a: SubMesh, b: SubMesh) => number = null,
-            alphaTestSortCompareFn: (a: SubMesh, b: SubMesh) => number = null,
-            transparentSortCompareFn: (a: SubMesh, b: SubMesh) => number = null): void {
+            opaqueSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null,
+            alphaTestSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null,
+            transparentSortCompareFn: Nullable<(a: SubMesh, b: SubMesh) => number> = null): void {
 
             this._renderingManager.setRenderingOrder(renderingGroupId,
                 opaqueSortCompareFn,

+ 3 - 0
src/babylon.types.ts

@@ -0,0 +1,3 @@
+type Nullable<T> = T | null;
+type float = number;
+type int = number;