Browse Source

Merge pull request #3466 from BabylonJS/master

Nightly
David Catuhe 7 years ago
parent
commit
ded9b3b719
42 changed files with 21348 additions and 21241 deletions
  1. 6971 6981
      Playground/babylon.d.txt
  2. 4254 4264
      dist/preview release/babylon.d.ts
  3. 47 47
      dist/preview release/babylon.js
  4. 110 57
      dist/preview release/babylon.max.js
  5. 48 48
      dist/preview release/babylon.worker.js
  6. 9532 9542
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  7. 50 50
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  8. 110 57
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  9. 3 3
      dist/preview release/gui/babylon.gui.min.js
  10. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  11. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  12. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  13. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  14. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  15. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  16. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  17. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  18. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  19. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  20. 3 3
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  21. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  22. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  23. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  24. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  25. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  26. 55 55
      dist/preview release/viewer/babylon.viewer.js
  27. 3 1
      src/Animations/babylon.animationGroup.ts
  28. 1 1
      src/Engine/babylon.engine.ts
  29. 1 1
      src/Materials/Textures/babylon.renderTargetTexture.ts
  30. 1 1
      src/Materials/Textures/babylon.videoTexture.ts
  31. 10 9
      src/Materials/babylon.materialHelper.ts
  32. 3 3
      src/Mesh/babylon.abstractMesh.ts
  33. 3 2
      src/Mesh/babylon.geometry.ts
  34. 2 2
      src/Mesh/babylon.mesh.ts
  35. 3 5
      src/Mesh/babylon.subMesh.ts
  36. 1 1
      src/Mesh/babylon.transformNode.ts
  37. 12 5
      src/Rendering/babylon.renderingGroup.ts
  38. 11 4
      src/Rendering/babylon.renderingManager.ts
  39. 6 1
      src/Tools/babylon.sceneSerializer.ts
  40. 14 43
      src/babylon.mixins.ts
  41. 15 7
      src/babylon.node.ts
  42. 53 22
      src/babylon.scene.ts

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


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


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


+ 110 - 57
dist/preview release/babylon.max.js

@@ -12678,7 +12678,7 @@ var BABYLON;
             }
             }
         };
         };
         /** Use this array to turn off some WebGL2 features on known buggy browsers version */
         /** Use this array to turn off some WebGL2 features on known buggy browsers version */
-        Engine.WebGL2UniformBuffersExceptionList = ["Chrome/63"];
+        Engine.WebGL2UniformBuffersExceptionList = ["Firefox/58"];
         Engine.Instances = new Array();
         Engine.Instances = new Array();
         // Const statics
         // Const statics
         Engine._ALPHA_DISABLE = 0;
         Engine._ALPHA_DISABLE = 0;
@@ -12780,15 +12780,18 @@ var BABYLON;
                 if (this._parentNode === parent) {
                 if (this._parentNode === parent) {
                     return;
                     return;
                 }
                 }
-                if (this._parentNode) {
+                // Remove self from list of children of parent
+                if (this._parentNode && this._parentNode._children !== undefined && this._parentNode._children !== null) {
                     var index = this._parentNode._children.indexOf(this);
                     var index = this._parentNode._children.indexOf(this);
                     if (index !== -1) {
                     if (index !== -1) {
                         this._parentNode._children.splice(index, 1);
                         this._parentNode._children.splice(index, 1);
                     }
                     }
                 }
                 }
+                // Store new parent
                 this._parentNode = parent;
                 this._parentNode = parent;
+                // Add as child to new parent
                 if (this._parentNode) {
                 if (this._parentNode) {
-                    if (!this._parentNode._children) {
+                    if (this._parentNode._children === undefined || this._parentNode._children === null) {
                         this._parentNode._children = new Array();
                         this._parentNode._children = new Array();
                     }
                     }
                     this._parentNode._children.push(this);
                     this._parentNode._children.push(this);
@@ -12926,16 +12929,21 @@ var BABYLON;
         };
         };
         /**
         /**
          * Is this node enabled.
          * Is this node enabled.
-         * If the node has a parent and is enabled, the parent will be inspected as well.
+         * If the node has a parent, all ancestors will be checked and false will be returned if any are false (not enabled), otherwise will return true.
+         * @param {boolean} [checkAncestors=true] - Indicates if this method should check the ancestors. The default is to check the ancestors. If set to false, the method will return the value of this node without checking ancestors.
          * @return {boolean} whether this node (and its parent) is enabled.
          * @return {boolean} whether this node (and its parent) is enabled.
          * @see setEnabled
          * @see setEnabled
          */
          */
-        Node.prototype.isEnabled = function () {
-            if (!this._isEnabled) {
+        Node.prototype.isEnabled = function (checkAncestors) {
+            if (checkAncestors === void 0) { checkAncestors = true; }
+            if (checkAncestors === false) {
+                return this._isEnabled;
+            }
+            if (this._isEnabled === false) {
                 return false;
                 return false;
             }
             }
-            if (this.parent) {
-                return this.parent.isEnabled();
+            if (this.parent !== undefined && this.parent !== null) {
+                return this.parent.isEnabled(checkAncestors);
             }
             }
             return true;
             return true;
         };
         };
@@ -13903,7 +13911,7 @@ var BABYLON;
          * Returns the TransformNode.
          * Returns the TransformNode.
          */
          */
         TransformNode.prototype.setParent = function (node) {
         TransformNode.prototype.setParent = function (node) {
-            if (node == null) {
+            if (node === null) {
                 var rotation = BABYLON.Tmp.Quaternion[0];
                 var rotation = BABYLON.Tmp.Quaternion[0];
                 var position = BABYLON.Tmp.Vector3[0];
                 var position = BABYLON.Tmp.Vector3[0];
                 var scale = BABYLON.Tmp.Vector3[1];
                 var scale = BABYLON.Tmp.Vector3[1];
@@ -15636,7 +15644,7 @@ var BABYLON;
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             var index;
             var index;
             // Action manager
             // Action manager
-            if (this.actionManager) {
+            if (this.actionManager !== undefined && this.actionManager !== null) {
                 this.actionManager.dispose();
                 this.actionManager.dispose();
                 this.actionManager = null;
                 this.actionManager = null;
             }
             }
@@ -15687,7 +15695,7 @@ var BABYLON;
             }
             }
             // Octree
             // Octree
             var sceneOctree = this.getScene().selectionOctree;
             var sceneOctree = this.getScene().selectionOctree;
-            if (sceneOctree) {
+            if (sceneOctree !== undefined && sceneOctree !== null) {
                 var index = sceneOctree.dynamicContent.indexOf(this);
                 var index = sceneOctree.dynamicContent.indexOf(this);
                 if (index !== -1) {
                 if (index !== -1) {
                     sceneOctree.dynamicContent.splice(index, 1);
                     sceneOctree.dynamicContent.splice(index, 1);
@@ -17801,7 +17809,7 @@ var BABYLON;
             this._renderingGroups.length = 0;
             this._renderingGroups.length = 0;
         };
         };
         RenderingManager.prototype._prepareRenderingGroup = function (renderingGroupId) {
         RenderingManager.prototype._prepareRenderingGroup = function (renderingGroupId) {
-            if (!this._renderingGroups[renderingGroupId]) {
+            if (this._renderingGroups[renderingGroupId] === undefined) {
                 this._renderingGroups[renderingGroupId] = new BABYLON.RenderingGroup(renderingGroupId, this._scene, this._customOpaqueSortCompareFn[renderingGroupId], this._customAlphaTestSortCompareFn[renderingGroupId], this._customTransparentSortCompareFn[renderingGroupId]);
                 this._renderingGroups[renderingGroupId] = new BABYLON.RenderingGroup(renderingGroupId, this._scene, this._customOpaqueSortCompareFn[renderingGroupId], this._customAlphaTestSortCompareFn[renderingGroupId], this._customTransparentSortCompareFn[renderingGroupId]);
             }
             }
         };
         };
@@ -17815,11 +17823,18 @@ var BABYLON;
             this._prepareRenderingGroup(renderingGroupId);
             this._prepareRenderingGroup(renderingGroupId);
             this._renderingGroups[renderingGroupId].dispatchParticles(particleSystem);
             this._renderingGroups[renderingGroupId].dispatchParticles(particleSystem);
         };
         };
-        RenderingManager.prototype.dispatch = function (subMesh) {
-            var mesh = subMesh.getMesh();
+        /**
+         * @param subMesh The submesh to dispatch
+         * @param [mesh] Optional reference to the submeshes's mesh. Provide if you have an exiting reference to improve performance.
+         * @param [material] Optional reference to the submeshes's material. Provide if you have an exiting reference to improve performance.
+         */
+        RenderingManager.prototype.dispatch = function (subMesh, mesh, material) {
+            if (mesh === undefined) {
+                mesh = subMesh.getMesh();
+            }
             var renderingGroupId = mesh.renderingGroupId || 0;
             var renderingGroupId = mesh.renderingGroupId || 0;
             this._prepareRenderingGroup(renderingGroupId);
             this._prepareRenderingGroup(renderingGroupId);
-            this._renderingGroups[renderingGroupId].dispatch(subMesh);
+            this._renderingGroups[renderingGroupId].dispatch(subMesh, mesh, material);
         };
         };
         /**
         /**
          * Overrides the default sort function applied in the renderging group to prepare the meshes.
          * Overrides the default sort function applied in the renderging group to prepare the meshes.
@@ -18161,11 +18176,18 @@ var BABYLON;
         /**
         /**
          * Inserts the submesh in its correct queue depending on its material.
          * Inserts the submesh in its correct queue depending on its material.
          * @param subMesh The submesh to dispatch
          * @param subMesh The submesh to dispatch
+         * @param [mesh] Optional reference to the submeshes's mesh. Provide if you have an exiting reference to improve performance.
+         * @param [material] Optional reference to the submeshes's material. Provide if you have an exiting reference to improve performance.
          */
          */
-        RenderingGroup.prototype.dispatch = function (subMesh) {
-            var material = subMesh.getMaterial();
-            var mesh = subMesh.getMesh();
-            if (!material) {
+        RenderingGroup.prototype.dispatch = function (subMesh, mesh, material) {
+            // Get mesh and materials if not provided
+            if (mesh === undefined) {
+                mesh = subMesh.getMesh();
+            }
+            if (material === undefined) {
+                material = subMesh.getMaterial();
+            }
+            if (material === null || material === undefined) {
                 return;
                 return;
             }
             }
             if (material.needAlphaBlendingForMesh(mesh)) {
             if (material.needAlphaBlendingForMesh(mesh)) {
@@ -18183,7 +18205,7 @@ var BABYLON;
                 }
                 }
                 this._opaqueSubMeshes.push(subMesh); // Opaque
                 this._opaqueSubMeshes.push(subMesh); // Opaque
             }
             }
-            if (mesh._edgesRenderer) {
+            if (mesh._edgesRenderer !== null && mesh._edgesRenderer !== undefined) {
                 this._edgesRenderers.push(mesh._edgesRenderer);
                 this._edgesRenderers.push(mesh._edgesRenderer);
             }
             }
         };
         };
@@ -18677,6 +18699,7 @@ var BABYLON;
             this._activeRequests = new Array();
             this._activeRequests = new Array();
             this._pendingData = new Array();
             this._pendingData = new Array();
             this._isDisposed = false;
             this._isDisposed = false;
+            this.dispatchAllSubMeshesOfActiveMeshes = false;
             this._activeMeshes = new BABYLON.SmartArray(256);
             this._activeMeshes = new BABYLON.SmartArray(256);
             this._processedMaterials = new BABYLON.SmartArray(256);
             this._processedMaterials = new BABYLON.SmartArray(256);
             this._renderTargets = new BABYLON.SmartArrayNoDuplicate(256);
             this._renderTargets = new BABYLON.SmartArrayNoDuplicate(256);
@@ -20744,15 +20767,17 @@ var BABYLON;
             return this._externalData.remove(key);
             return this._externalData.remove(key);
         };
         };
         Scene.prototype._evaluateSubMesh = function (subMesh, mesh) {
         Scene.prototype._evaluateSubMesh = function (subMesh, mesh) {
-            if (mesh.alwaysSelectAsActiveMesh || mesh.subMeshes.length === 1 || subMesh.isInFrustum(this._frustumPlanes)) {
-                var material = subMesh.getMaterial();
+            if (this.dispatchAllSubMeshesOfActiveMeshes || mesh.alwaysSelectAsActiveMesh || mesh.subMeshes.length === 1 || subMesh.isInFrustum(this._frustumPlanes)) {
                 if (mesh.showSubMeshesBoundingBox) {
                 if (mesh.showSubMeshesBoundingBox) {
                     var boundingInfo = subMesh.getBoundingInfo();
                     var boundingInfo = subMesh.getBoundingInfo();
-                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
+                    if (boundingInfo !== null && boundingInfo !== undefined) {
+                        this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
+                    }
                 }
                 }
-                if (material) {
+                var material = subMesh.getMaterial();
+                if (material !== null && material !== undefined) {
                     // Render targets
                     // Render targets
-                    if (material.getRenderTargetTextures) {
+                    if (material.getRenderTargetTextures !== undefined) {
                         if (this._processedMaterials.indexOf(material) === -1) {
                         if (this._processedMaterials.indexOf(material) === -1) {
                             this._processedMaterials.push(material);
                             this._processedMaterials.push(material);
                             this._renderTargets.concatWithNoDuplicate(material.getRenderTargetTextures());
                             this._renderTargets.concatWithNoDuplicate(material.getRenderTargetTextures());
@@ -20760,13 +20785,19 @@ var BABYLON;
                     }
                     }
                     // Dispatch
                     // Dispatch
                     this._activeIndices.addCount(subMesh.indexCount, false);
                     this._activeIndices.addCount(subMesh.indexCount, false);
-                    this._renderingManager.dispatch(subMesh);
+                    this._renderingManager.dispatch(subMesh, mesh, material);
                 }
                 }
             }
             }
         };
         };
         Scene.prototype._isInIntermediateRendering = function () {
         Scene.prototype._isInIntermediateRendering = function () {
             return this._intermediateRendering;
             return this._intermediateRendering;
         };
         };
+        Scene.prototype.setActiveMeshCandidateProvider = function (provider) {
+            this._activeMeshCandidateProvider = provider;
+        };
+        Scene.prototype.getActiveMeshCandidateProvider = function () {
+            return this._activeMeshCandidateProvider;
+        };
         /**
         /**
          * Use this function to stop evaluating active meshes. The current list will be keep alive between frames
          * Use this function to stop evaluating active meshes. The current list will be keep alive between frames
          */
          */
@@ -20803,22 +20834,38 @@ var BABYLON;
             // Meshes
             // Meshes
             var meshes;
             var meshes;
             var len;
             var len;
-            if (this._selectionOctree) {
+            var checkIsEnabled = true;
+            // Determine mesh candidates
+            if (this._activeMeshCandidateProvider !== undefined) {
+                // Use _activeMeshCandidateProvider
+                meshes = this._activeMeshCandidateProvider.getMeshes(this);
+                checkIsEnabled = this._activeMeshCandidateProvider.checksIsEnabled === false;
+                if (meshes !== undefined) {
+                    len = meshes.length;
+                }
+                else {
+                    len = 0;
+                }
+            }
+            else if (this._selectionOctree !== undefined) {
+                // Octree
                 var selection = this._selectionOctree.select(this._frustumPlanes);
                 var selection = this._selectionOctree.select(this._frustumPlanes);
                 meshes = selection.data;
                 meshes = selection.data;
                 len = selection.length;
                 len = selection.length;
             }
             }
             else {
             else {
+                // Full scene traversal
                 len = this.meshes.length;
                 len = this.meshes.length;
                 meshes = this.meshes;
                 meshes = this.meshes;
             }
             }
-            for (var meshIndex = 0; meshIndex < len; meshIndex++) {
-                var mesh = meshes[meshIndex];
+            // Check each mesh
+            for (var meshIndex = 0, mesh, meshLOD; meshIndex < len; meshIndex++) {
+                mesh = meshes[meshIndex];
                 if (mesh.isBlocked) {
                 if (mesh.isBlocked) {
                     continue;
                     continue;
                 }
                 }
                 this._totalVertices.addCount(mesh.getTotalVertices(), false);
                 this._totalVertices.addCount(mesh.getTotalVertices(), false);
-                if (!mesh.isReady() || !mesh.isEnabled()) {
+                if (!mesh.isReady() || (checkIsEnabled && !mesh.isEnabled())) {
                     continue;
                     continue;
                 }
                 }
                 mesh.computeWorldMatrix();
                 mesh.computeWorldMatrix();
@@ -20827,8 +20874,8 @@ var BABYLON;
                     this._meshesForIntersections.pushNoDuplicate(mesh);
                     this._meshesForIntersections.pushNoDuplicate(mesh);
                 }
                 }
                 // Switch to current LOD
                 // Switch to current LOD
-                var meshLOD = mesh.getLOD(this.activeCamera);
-                if (!meshLOD) {
+                meshLOD = mesh.getLOD(this.activeCamera);
+                if (meshLOD === undefined || meshLOD === null) {
                     continue;
                     continue;
                 }
                 }
                 mesh._preActivate();
                 mesh._preActivate();
@@ -20862,7 +20909,7 @@ var BABYLON;
             }
             }
         };
         };
         Scene.prototype._activeMesh = function (sourceMesh, mesh) {
         Scene.prototype._activeMesh = function (sourceMesh, mesh) {
-            if (mesh.skeleton && this.skeletonsEnabled) {
+            if (this.skeletonsEnabled && mesh.skeleton !== null && mesh.skeleton !== undefined) {
                 if (this._activeSkeletons.pushNoDuplicate(mesh.skeleton)) {
                 if (this._activeSkeletons.pushNoDuplicate(mesh.skeleton)) {
                     mesh.skeleton.prepare();
                     mesh.skeleton.prepare();
                 }
                 }
@@ -20874,11 +20921,12 @@ var BABYLON;
                 var boundingInfo = sourceMesh.getBoundingInfo();
                 var boundingInfo = sourceMesh.getBoundingInfo();
                 this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
                 this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
             }
             }
-            if (mesh && mesh.subMeshes) {
+            if (mesh !== undefined && mesh !== null
+                && mesh.subMeshes !== undefined && mesh.subMeshes !== null && mesh.subMeshes.length > 0) {
                 // Submeshes Octrees
                 // Submeshes Octrees
                 var len;
                 var len;
                 var subMeshes;
                 var subMeshes;
-                if (mesh._submeshesOctree && mesh.useOctreeForRenderingSelection) {
+                if (mesh.useOctreeForRenderingSelection && mesh._submeshesOctree !== undefined && mesh._submeshesOctree !== null) {
                     var intersections = mesh._submeshesOctree.select(this._frustumPlanes);
                     var intersections = mesh._submeshesOctree.select(this._frustumPlanes);
                     len = intersections.length;
                     len = intersections.length;
                     subMeshes = intersections.data;
                     subMeshes = intersections.data;
@@ -20887,8 +20935,8 @@ var BABYLON;
                     subMeshes = mesh.subMeshes;
                     subMeshes = mesh.subMeshes;
                     len = subMeshes.length;
                     len = subMeshes.length;
                 }
                 }
-                for (var subIndex = 0; subIndex < len; subIndex++) {
-                    var subMesh = subMeshes[subIndex];
+                for (var subIndex = 0, subMesh; subIndex < len; subIndex++) {
+                    subMesh = subMeshes[subIndex];
                     this._evaluateSubMesh(subMesh, mesh);
                     this._evaluateSubMesh(subMesh, mesh);
                 }
                 }
             }
             }
@@ -23952,7 +24000,7 @@ var BABYLON;
          * Returns a positive integer : the total number of vertices within the mesh geometry or zero if the mesh has no geometry.
          * Returns a positive integer : the total number of vertices within the mesh geometry or zero if the mesh has no geometry.
          */
          */
         Mesh.prototype.getTotalVertices = function () {
         Mesh.prototype.getTotalVertices = function () {
-            if (!this._geometry) {
+            if (this._geometry === null || this._geometry === undefined) {
                 return 0;
                 return 0;
             }
             }
             return this._geometry.getTotalVertices();
             return this._geometry.getTotalVertices();
@@ -25419,7 +25467,7 @@ var BABYLON;
             }
             }
             serializationObject.scaling = this.scaling.asArray();
             serializationObject.scaling = this.scaling.asArray();
             serializationObject.localMatrix = this.getPivotMatrix().asArray();
             serializationObject.localMatrix = this.getPivotMatrix().asArray();
-            serializationObject.isEnabled = this.isEnabled();
+            serializationObject.isEnabled = this.isEnabled(false);
             serializationObject.isVisible = this.isVisible;
             serializationObject.isVisible = this.isVisible;
             serializationObject.infiniteDistance = this.infiniteDistance;
             serializationObject.infiniteDistance = this.infiniteDistance;
             serializationObject.pickable = this.isPickable;
             serializationObject.pickable = this.isPickable;
@@ -26639,7 +26687,10 @@ var BABYLON;
          */
          */
         SubMesh.prototype.getMaterial = function () {
         SubMesh.prototype.getMaterial = function () {
             var rootMaterial = this._renderingMesh.material;
             var rootMaterial = this._renderingMesh.material;
-            if (rootMaterial && rootMaterial.getSubMaterial) {
+            if (rootMaterial === null || rootMaterial === undefined) {
+                return this._mesh.getScene().defaultMaterial;
+            }
+            else if (rootMaterial.getSubMaterial) {
                 var multiMaterial = rootMaterial;
                 var multiMaterial = rootMaterial;
                 var effectiveMaterial = multiMaterial.getSubMaterial(this.materialIndex);
                 var effectiveMaterial = multiMaterial.getSubMaterial(this.materialIndex);
                 if (this._currentMaterial !== effectiveMaterial) {
                 if (this._currentMaterial !== effectiveMaterial) {
@@ -26648,9 +26699,6 @@ var BABYLON;
                 }
                 }
                 return effectiveMaterial;
                 return effectiveMaterial;
             }
             }
-            if (!rootMaterial) {
-                return this._mesh.getScene().defaultMaterial;
-            }
             return rootMaterial;
             return rootMaterial;
         };
         };
         // Methods
         // Methods
@@ -32057,8 +32105,9 @@ var BABYLON;
             // Update
             // Update
             mesh.computeWorldMatrix(true);
             mesh.computeWorldMatrix(true);
             // Octree
             // Octree
-            if (scene['_selectionOctree']) {
-                scene['_selectionOctree'].addMesh(mesh);
+            var sceneOctree = scene.selectionOctree;
+            if (sceneOctree !== undefined && sceneOctree !== null) {
+                sceneOctree.addMesh(mesh);
             }
             }
         };
         };
         Geometry._CleanMatricesWeights = function (parsedGeometry, mesh) {
         Geometry._CleanMatricesWeights = function (parsedGeometry, mesh) {
@@ -34557,25 +34606,24 @@ var BABYLON;
         MaterialHelper.BindLights = function (scene, mesh, effect, defines, maxSimultaneousLights, usePhysicalLightFalloff) {
         MaterialHelper.BindLights = function (scene, mesh, effect, defines, maxSimultaneousLights, usePhysicalLightFalloff) {
             if (maxSimultaneousLights === void 0) { maxSimultaneousLights = 4; }
             if (maxSimultaneousLights === void 0) { maxSimultaneousLights = 4; }
             if (usePhysicalLightFalloff === void 0) { usePhysicalLightFalloff = false; }
             if (usePhysicalLightFalloff === void 0) { usePhysicalLightFalloff = false; }
-            var lightIndex = 0;
-            for (var _i = 0, _a = mesh._lightSources; _i < _a.length; _i++) {
-                var light = _a[_i];
+            for (var i = 0, len = mesh._lightSources.length, light, iAsString; i < len; i++) {
+                light = mesh._lightSources[i];
+                iAsString = i.toString();
                 var scaledIntensity = light.getScaledIntensity();
                 var scaledIntensity = light.getScaledIntensity();
-                light._uniformBuffer.bindToEffect(effect, "Light" + lightIndex);
-                MaterialHelper.BindLightProperties(light, effect, lightIndex);
+                light._uniformBuffer.bindToEffect(effect, "Light" + i);
+                MaterialHelper.BindLightProperties(light, effect, i);
                 light.diffuse.scaleToRef(scaledIntensity, BABYLON.Tmp.Color3[0]);
                 light.diffuse.scaleToRef(scaledIntensity, BABYLON.Tmp.Color3[0]);
-                light._uniformBuffer.updateColor4("vLightDiffuse", BABYLON.Tmp.Color3[0], usePhysicalLightFalloff ? light.radius : light.range, lightIndex + "");
+                light._uniformBuffer.updateColor4("vLightDiffuse", BABYLON.Tmp.Color3[0], usePhysicalLightFalloff ? light.radius : light.range, iAsString);
                 if (defines["SPECULARTERM"]) {
                 if (defines["SPECULARTERM"]) {
                     light.specular.scaleToRef(scaledIntensity, BABYLON.Tmp.Color3[1]);
                     light.specular.scaleToRef(scaledIntensity, BABYLON.Tmp.Color3[1]);
-                    light._uniformBuffer.updateColor3("vLightSpecular", BABYLON.Tmp.Color3[1], lightIndex + "");
+                    light._uniformBuffer.updateColor3("vLightSpecular", BABYLON.Tmp.Color3[1], iAsString);
                 }
                 }
                 // Shadows
                 // Shadows
                 if (scene.shadowsEnabled) {
                 if (scene.shadowsEnabled) {
-                    this.BindLightShadow(light, scene, mesh, lightIndex + "", effect);
+                    this.BindLightShadow(light, scene, mesh, iAsString, effect);
                 }
                 }
                 light._uniformBuffer.update();
                 light._uniformBuffer.update();
-                lightIndex++;
-                if (lightIndex === maxSimultaneousLights)
+                if (i === maxSimultaneousLights)
                     break;
                     break;
             }
             }
         };
         };
@@ -42179,6 +42227,7 @@ var BABYLON;
                 if (this._speedRatio === value) {
                 if (this._speedRatio === value) {
                     return;
                     return;
                 }
                 }
+                this._speedRatio = value;
                 for (var index = 0; index < this._animatables.length; index++) {
                 for (var index = 0; index < this._animatables.length; index++) {
                     var animatable = this._animatables[index];
                     var animatable = this._animatables[index];
                     animatable.speedRatio = this._speedRatio;
                     animatable.speedRatio = this._speedRatio;
@@ -42298,7 +42347,7 @@ var BABYLON;
                 this.restart();
                 this.restart();
             }
             }
             else {
             else {
-                this.start(loop);
+                this.start(loop, this._speedRatio);
             }
             }
             return this;
             return this;
         };
         };
@@ -51808,7 +51857,7 @@ var BABYLON;
                         for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                         for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                             var subMesh = mesh.subMeshes[subIndex];
                             var subMesh = mesh.subMeshes[subIndex];
                             scene._activeIndices.addCount(subMesh.indexCount, false);
                             scene._activeIndices.addCount(subMesh.indexCount, false);
-                            this._renderingManager.dispatch(subMesh);
+                            this._renderingManager.dispatch(subMesh, mesh);
                         }
                         }
                     }
                     }
                 }
                 }
@@ -77635,6 +77684,10 @@ var BABYLON;
                 var multiMaterial = scene.multiMaterials[index];
                 var multiMaterial = scene.multiMaterials[index];
                 serializationObject.multiMaterials.push(multiMaterial.serialize());
                 serializationObject.multiMaterials.push(multiMaterial.serialize());
             }
             }
+            // Environment texture
+            if (scene.environmentTexture) {
+                serializationObject.environmentTexture = scene.environmentTexture.name;
+            }
             // Skeletons
             // Skeletons
             serializationObject.skeletons = [];
             serializationObject.skeletons = [];
             for (index = 0; index < scene.skeletons.length; index++) {
             for (index = 0; index < scene.skeletons.length; index++) {

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


File diff suppressed because it is too large
+ 9532 - 9542
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


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


+ 110 - 57
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -12678,7 +12678,7 @@ var BABYLON;
             }
             }
         };
         };
         /** Use this array to turn off some WebGL2 features on known buggy browsers version */
         /** Use this array to turn off some WebGL2 features on known buggy browsers version */
-        Engine.WebGL2UniformBuffersExceptionList = ["Chrome/63"];
+        Engine.WebGL2UniformBuffersExceptionList = ["Firefox/58"];
         Engine.Instances = new Array();
         Engine.Instances = new Array();
         // Const statics
         // Const statics
         Engine._ALPHA_DISABLE = 0;
         Engine._ALPHA_DISABLE = 0;
@@ -12780,15 +12780,18 @@ var BABYLON;
                 if (this._parentNode === parent) {
                 if (this._parentNode === parent) {
                     return;
                     return;
                 }
                 }
-                if (this._parentNode) {
+                // Remove self from list of children of parent
+                if (this._parentNode && this._parentNode._children !== undefined && this._parentNode._children !== null) {
                     var index = this._parentNode._children.indexOf(this);
                     var index = this._parentNode._children.indexOf(this);
                     if (index !== -1) {
                     if (index !== -1) {
                         this._parentNode._children.splice(index, 1);
                         this._parentNode._children.splice(index, 1);
                     }
                     }
                 }
                 }
+                // Store new parent
                 this._parentNode = parent;
                 this._parentNode = parent;
+                // Add as child to new parent
                 if (this._parentNode) {
                 if (this._parentNode) {
-                    if (!this._parentNode._children) {
+                    if (this._parentNode._children === undefined || this._parentNode._children === null) {
                         this._parentNode._children = new Array();
                         this._parentNode._children = new Array();
                     }
                     }
                     this._parentNode._children.push(this);
                     this._parentNode._children.push(this);
@@ -12926,16 +12929,21 @@ var BABYLON;
         };
         };
         /**
         /**
          * Is this node enabled.
          * Is this node enabled.
-         * If the node has a parent and is enabled, the parent will be inspected as well.
+         * If the node has a parent, all ancestors will be checked and false will be returned if any are false (not enabled), otherwise will return true.
+         * @param {boolean} [checkAncestors=true] - Indicates if this method should check the ancestors. The default is to check the ancestors. If set to false, the method will return the value of this node without checking ancestors.
          * @return {boolean} whether this node (and its parent) is enabled.
          * @return {boolean} whether this node (and its parent) is enabled.
          * @see setEnabled
          * @see setEnabled
          */
          */
-        Node.prototype.isEnabled = function () {
-            if (!this._isEnabled) {
+        Node.prototype.isEnabled = function (checkAncestors) {
+            if (checkAncestors === void 0) { checkAncestors = true; }
+            if (checkAncestors === false) {
+                return this._isEnabled;
+            }
+            if (this._isEnabled === false) {
                 return false;
                 return false;
             }
             }
-            if (this.parent) {
-                return this.parent.isEnabled();
+            if (this.parent !== undefined && this.parent !== null) {
+                return this.parent.isEnabled(checkAncestors);
             }
             }
             return true;
             return true;
         };
         };
@@ -13903,7 +13911,7 @@ var BABYLON;
          * Returns the TransformNode.
          * Returns the TransformNode.
          */
          */
         TransformNode.prototype.setParent = function (node) {
         TransformNode.prototype.setParent = function (node) {
-            if (node == null) {
+            if (node === null) {
                 var rotation = BABYLON.Tmp.Quaternion[0];
                 var rotation = BABYLON.Tmp.Quaternion[0];
                 var position = BABYLON.Tmp.Vector3[0];
                 var position = BABYLON.Tmp.Vector3[0];
                 var scale = BABYLON.Tmp.Vector3[1];
                 var scale = BABYLON.Tmp.Vector3[1];
@@ -15636,7 +15644,7 @@ var BABYLON;
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             if (disposeMaterialAndTextures === void 0) { disposeMaterialAndTextures = false; }
             var index;
             var index;
             // Action manager
             // Action manager
-            if (this.actionManager) {
+            if (this.actionManager !== undefined && this.actionManager !== null) {
                 this.actionManager.dispose();
                 this.actionManager.dispose();
                 this.actionManager = null;
                 this.actionManager = null;
             }
             }
@@ -15687,7 +15695,7 @@ var BABYLON;
             }
             }
             // Octree
             // Octree
             var sceneOctree = this.getScene().selectionOctree;
             var sceneOctree = this.getScene().selectionOctree;
-            if (sceneOctree) {
+            if (sceneOctree !== undefined && sceneOctree !== null) {
                 var index = sceneOctree.dynamicContent.indexOf(this);
                 var index = sceneOctree.dynamicContent.indexOf(this);
                 if (index !== -1) {
                 if (index !== -1) {
                     sceneOctree.dynamicContent.splice(index, 1);
                     sceneOctree.dynamicContent.splice(index, 1);
@@ -17801,7 +17809,7 @@ var BABYLON;
             this._renderingGroups.length = 0;
             this._renderingGroups.length = 0;
         };
         };
         RenderingManager.prototype._prepareRenderingGroup = function (renderingGroupId) {
         RenderingManager.prototype._prepareRenderingGroup = function (renderingGroupId) {
-            if (!this._renderingGroups[renderingGroupId]) {
+            if (this._renderingGroups[renderingGroupId] === undefined) {
                 this._renderingGroups[renderingGroupId] = new BABYLON.RenderingGroup(renderingGroupId, this._scene, this._customOpaqueSortCompareFn[renderingGroupId], this._customAlphaTestSortCompareFn[renderingGroupId], this._customTransparentSortCompareFn[renderingGroupId]);
                 this._renderingGroups[renderingGroupId] = new BABYLON.RenderingGroup(renderingGroupId, this._scene, this._customOpaqueSortCompareFn[renderingGroupId], this._customAlphaTestSortCompareFn[renderingGroupId], this._customTransparentSortCompareFn[renderingGroupId]);
             }
             }
         };
         };
@@ -17815,11 +17823,18 @@ var BABYLON;
             this._prepareRenderingGroup(renderingGroupId);
             this._prepareRenderingGroup(renderingGroupId);
             this._renderingGroups[renderingGroupId].dispatchParticles(particleSystem);
             this._renderingGroups[renderingGroupId].dispatchParticles(particleSystem);
         };
         };
-        RenderingManager.prototype.dispatch = function (subMesh) {
-            var mesh = subMesh.getMesh();
+        /**
+         * @param subMesh The submesh to dispatch
+         * @param [mesh] Optional reference to the submeshes's mesh. Provide if you have an exiting reference to improve performance.
+         * @param [material] Optional reference to the submeshes's material. Provide if you have an exiting reference to improve performance.
+         */
+        RenderingManager.prototype.dispatch = function (subMesh, mesh, material) {
+            if (mesh === undefined) {
+                mesh = subMesh.getMesh();
+            }
             var renderingGroupId = mesh.renderingGroupId || 0;
             var renderingGroupId = mesh.renderingGroupId || 0;
             this._prepareRenderingGroup(renderingGroupId);
             this._prepareRenderingGroup(renderingGroupId);
-            this._renderingGroups[renderingGroupId].dispatch(subMesh);
+            this._renderingGroups[renderingGroupId].dispatch(subMesh, mesh, material);
         };
         };
         /**
         /**
          * Overrides the default sort function applied in the renderging group to prepare the meshes.
          * Overrides the default sort function applied in the renderging group to prepare the meshes.
@@ -18161,11 +18176,18 @@ var BABYLON;
         /**
         /**
          * Inserts the submesh in its correct queue depending on its material.
          * Inserts the submesh in its correct queue depending on its material.
          * @param subMesh The submesh to dispatch
          * @param subMesh The submesh to dispatch
+         * @param [mesh] Optional reference to the submeshes's mesh. Provide if you have an exiting reference to improve performance.
+         * @param [material] Optional reference to the submeshes's material. Provide if you have an exiting reference to improve performance.
          */
          */
-        RenderingGroup.prototype.dispatch = function (subMesh) {
-            var material = subMesh.getMaterial();
-            var mesh = subMesh.getMesh();
-            if (!material) {
+        RenderingGroup.prototype.dispatch = function (subMesh, mesh, material) {
+            // Get mesh and materials if not provided
+            if (mesh === undefined) {
+                mesh = subMesh.getMesh();
+            }
+            if (material === undefined) {
+                material = subMesh.getMaterial();
+            }
+            if (material === null || material === undefined) {
                 return;
                 return;
             }
             }
             if (material.needAlphaBlendingForMesh(mesh)) {
             if (material.needAlphaBlendingForMesh(mesh)) {
@@ -18183,7 +18205,7 @@ var BABYLON;
                 }
                 }
                 this._opaqueSubMeshes.push(subMesh); // Opaque
                 this._opaqueSubMeshes.push(subMesh); // Opaque
             }
             }
-            if (mesh._edgesRenderer) {
+            if (mesh._edgesRenderer !== null && mesh._edgesRenderer !== undefined) {
                 this._edgesRenderers.push(mesh._edgesRenderer);
                 this._edgesRenderers.push(mesh._edgesRenderer);
             }
             }
         };
         };
@@ -18677,6 +18699,7 @@ var BABYLON;
             this._activeRequests = new Array();
             this._activeRequests = new Array();
             this._pendingData = new Array();
             this._pendingData = new Array();
             this._isDisposed = false;
             this._isDisposed = false;
+            this.dispatchAllSubMeshesOfActiveMeshes = false;
             this._activeMeshes = new BABYLON.SmartArray(256);
             this._activeMeshes = new BABYLON.SmartArray(256);
             this._processedMaterials = new BABYLON.SmartArray(256);
             this._processedMaterials = new BABYLON.SmartArray(256);
             this._renderTargets = new BABYLON.SmartArrayNoDuplicate(256);
             this._renderTargets = new BABYLON.SmartArrayNoDuplicate(256);
@@ -20744,15 +20767,17 @@ var BABYLON;
             return this._externalData.remove(key);
             return this._externalData.remove(key);
         };
         };
         Scene.prototype._evaluateSubMesh = function (subMesh, mesh) {
         Scene.prototype._evaluateSubMesh = function (subMesh, mesh) {
-            if (mesh.alwaysSelectAsActiveMesh || mesh.subMeshes.length === 1 || subMesh.isInFrustum(this._frustumPlanes)) {
-                var material = subMesh.getMaterial();
+            if (this.dispatchAllSubMeshesOfActiveMeshes || mesh.alwaysSelectAsActiveMesh || mesh.subMeshes.length === 1 || subMesh.isInFrustum(this._frustumPlanes)) {
                 if (mesh.showSubMeshesBoundingBox) {
                 if (mesh.showSubMeshesBoundingBox) {
                     var boundingInfo = subMesh.getBoundingInfo();
                     var boundingInfo = subMesh.getBoundingInfo();
-                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
+                    if (boundingInfo !== null && boundingInfo !== undefined) {
+                        this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
+                    }
                 }
                 }
-                if (material) {
+                var material = subMesh.getMaterial();
+                if (material !== null && material !== undefined) {
                     // Render targets
                     // Render targets
-                    if (material.getRenderTargetTextures) {
+                    if (material.getRenderTargetTextures !== undefined) {
                         if (this._processedMaterials.indexOf(material) === -1) {
                         if (this._processedMaterials.indexOf(material) === -1) {
                             this._processedMaterials.push(material);
                             this._processedMaterials.push(material);
                             this._renderTargets.concatWithNoDuplicate(material.getRenderTargetTextures());
                             this._renderTargets.concatWithNoDuplicate(material.getRenderTargetTextures());
@@ -20760,13 +20785,19 @@ var BABYLON;
                     }
                     }
                     // Dispatch
                     // Dispatch
                     this._activeIndices.addCount(subMesh.indexCount, false);
                     this._activeIndices.addCount(subMesh.indexCount, false);
-                    this._renderingManager.dispatch(subMesh);
+                    this._renderingManager.dispatch(subMesh, mesh, material);
                 }
                 }
             }
             }
         };
         };
         Scene.prototype._isInIntermediateRendering = function () {
         Scene.prototype._isInIntermediateRendering = function () {
             return this._intermediateRendering;
             return this._intermediateRendering;
         };
         };
+        Scene.prototype.setActiveMeshCandidateProvider = function (provider) {
+            this._activeMeshCandidateProvider = provider;
+        };
+        Scene.prototype.getActiveMeshCandidateProvider = function () {
+            return this._activeMeshCandidateProvider;
+        };
         /**
         /**
          * Use this function to stop evaluating active meshes. The current list will be keep alive between frames
          * Use this function to stop evaluating active meshes. The current list will be keep alive between frames
          */
          */
@@ -20803,22 +20834,38 @@ var BABYLON;
             // Meshes
             // Meshes
             var meshes;
             var meshes;
             var len;
             var len;
-            if (this._selectionOctree) {
+            var checkIsEnabled = true;
+            // Determine mesh candidates
+            if (this._activeMeshCandidateProvider !== undefined) {
+                // Use _activeMeshCandidateProvider
+                meshes = this._activeMeshCandidateProvider.getMeshes(this);
+                checkIsEnabled = this._activeMeshCandidateProvider.checksIsEnabled === false;
+                if (meshes !== undefined) {
+                    len = meshes.length;
+                }
+                else {
+                    len = 0;
+                }
+            }
+            else if (this._selectionOctree !== undefined) {
+                // Octree
                 var selection = this._selectionOctree.select(this._frustumPlanes);
                 var selection = this._selectionOctree.select(this._frustumPlanes);
                 meshes = selection.data;
                 meshes = selection.data;
                 len = selection.length;
                 len = selection.length;
             }
             }
             else {
             else {
+                // Full scene traversal
                 len = this.meshes.length;
                 len = this.meshes.length;
                 meshes = this.meshes;
                 meshes = this.meshes;
             }
             }
-            for (var meshIndex = 0; meshIndex < len; meshIndex++) {
-                var mesh = meshes[meshIndex];
+            // Check each mesh
+            for (var meshIndex = 0, mesh, meshLOD; meshIndex < len; meshIndex++) {
+                mesh = meshes[meshIndex];
                 if (mesh.isBlocked) {
                 if (mesh.isBlocked) {
                     continue;
                     continue;
                 }
                 }
                 this._totalVertices.addCount(mesh.getTotalVertices(), false);
                 this._totalVertices.addCount(mesh.getTotalVertices(), false);
-                if (!mesh.isReady() || !mesh.isEnabled()) {
+                if (!mesh.isReady() || (checkIsEnabled && !mesh.isEnabled())) {
                     continue;
                     continue;
                 }
                 }
                 mesh.computeWorldMatrix();
                 mesh.computeWorldMatrix();
@@ -20827,8 +20874,8 @@ var BABYLON;
                     this._meshesForIntersections.pushNoDuplicate(mesh);
                     this._meshesForIntersections.pushNoDuplicate(mesh);
                 }
                 }
                 // Switch to current LOD
                 // Switch to current LOD
-                var meshLOD = mesh.getLOD(this.activeCamera);
-                if (!meshLOD) {
+                meshLOD = mesh.getLOD(this.activeCamera);
+                if (meshLOD === undefined || meshLOD === null) {
                     continue;
                     continue;
                 }
                 }
                 mesh._preActivate();
                 mesh._preActivate();
@@ -20862,7 +20909,7 @@ var BABYLON;
             }
             }
         };
         };
         Scene.prototype._activeMesh = function (sourceMesh, mesh) {
         Scene.prototype._activeMesh = function (sourceMesh, mesh) {
-            if (mesh.skeleton && this.skeletonsEnabled) {
+            if (this.skeletonsEnabled && mesh.skeleton !== null && mesh.skeleton !== undefined) {
                 if (this._activeSkeletons.pushNoDuplicate(mesh.skeleton)) {
                 if (this._activeSkeletons.pushNoDuplicate(mesh.skeleton)) {
                     mesh.skeleton.prepare();
                     mesh.skeleton.prepare();
                 }
                 }
@@ -20874,11 +20921,12 @@ var BABYLON;
                 var boundingInfo = sourceMesh.getBoundingInfo();
                 var boundingInfo = sourceMesh.getBoundingInfo();
                 this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
                 this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
             }
             }
-            if (mesh && mesh.subMeshes) {
+            if (mesh !== undefined && mesh !== null
+                && mesh.subMeshes !== undefined && mesh.subMeshes !== null && mesh.subMeshes.length > 0) {
                 // Submeshes Octrees
                 // Submeshes Octrees
                 var len;
                 var len;
                 var subMeshes;
                 var subMeshes;
-                if (mesh._submeshesOctree && mesh.useOctreeForRenderingSelection) {
+                if (mesh.useOctreeForRenderingSelection && mesh._submeshesOctree !== undefined && mesh._submeshesOctree !== null) {
                     var intersections = mesh._submeshesOctree.select(this._frustumPlanes);
                     var intersections = mesh._submeshesOctree.select(this._frustumPlanes);
                     len = intersections.length;
                     len = intersections.length;
                     subMeshes = intersections.data;
                     subMeshes = intersections.data;
@@ -20887,8 +20935,8 @@ var BABYLON;
                     subMeshes = mesh.subMeshes;
                     subMeshes = mesh.subMeshes;
                     len = subMeshes.length;
                     len = subMeshes.length;
                 }
                 }
-                for (var subIndex = 0; subIndex < len; subIndex++) {
-                    var subMesh = subMeshes[subIndex];
+                for (var subIndex = 0, subMesh; subIndex < len; subIndex++) {
+                    subMesh = subMeshes[subIndex];
                     this._evaluateSubMesh(subMesh, mesh);
                     this._evaluateSubMesh(subMesh, mesh);
                 }
                 }
             }
             }
@@ -23952,7 +24000,7 @@ var BABYLON;
          * Returns a positive integer : the total number of vertices within the mesh geometry or zero if the mesh has no geometry.
          * Returns a positive integer : the total number of vertices within the mesh geometry or zero if the mesh has no geometry.
          */
          */
         Mesh.prototype.getTotalVertices = function () {
         Mesh.prototype.getTotalVertices = function () {
-            if (!this._geometry) {
+            if (this._geometry === null || this._geometry === undefined) {
                 return 0;
                 return 0;
             }
             }
             return this._geometry.getTotalVertices();
             return this._geometry.getTotalVertices();
@@ -25419,7 +25467,7 @@ var BABYLON;
             }
             }
             serializationObject.scaling = this.scaling.asArray();
             serializationObject.scaling = this.scaling.asArray();
             serializationObject.localMatrix = this.getPivotMatrix().asArray();
             serializationObject.localMatrix = this.getPivotMatrix().asArray();
-            serializationObject.isEnabled = this.isEnabled();
+            serializationObject.isEnabled = this.isEnabled(false);
             serializationObject.isVisible = this.isVisible;
             serializationObject.isVisible = this.isVisible;
             serializationObject.infiniteDistance = this.infiniteDistance;
             serializationObject.infiniteDistance = this.infiniteDistance;
             serializationObject.pickable = this.isPickable;
             serializationObject.pickable = this.isPickable;
@@ -26639,7 +26687,10 @@ var BABYLON;
          */
          */
         SubMesh.prototype.getMaterial = function () {
         SubMesh.prototype.getMaterial = function () {
             var rootMaterial = this._renderingMesh.material;
             var rootMaterial = this._renderingMesh.material;
-            if (rootMaterial && rootMaterial.getSubMaterial) {
+            if (rootMaterial === null || rootMaterial === undefined) {
+                return this._mesh.getScene().defaultMaterial;
+            }
+            else if (rootMaterial.getSubMaterial) {
                 var multiMaterial = rootMaterial;
                 var multiMaterial = rootMaterial;
                 var effectiveMaterial = multiMaterial.getSubMaterial(this.materialIndex);
                 var effectiveMaterial = multiMaterial.getSubMaterial(this.materialIndex);
                 if (this._currentMaterial !== effectiveMaterial) {
                 if (this._currentMaterial !== effectiveMaterial) {
@@ -26648,9 +26699,6 @@ var BABYLON;
                 }
                 }
                 return effectiveMaterial;
                 return effectiveMaterial;
             }
             }
-            if (!rootMaterial) {
-                return this._mesh.getScene().defaultMaterial;
-            }
             return rootMaterial;
             return rootMaterial;
         };
         };
         // Methods
         // Methods
@@ -32057,8 +32105,9 @@ var BABYLON;
             // Update
             // Update
             mesh.computeWorldMatrix(true);
             mesh.computeWorldMatrix(true);
             // Octree
             // Octree
-            if (scene['_selectionOctree']) {
-                scene['_selectionOctree'].addMesh(mesh);
+            var sceneOctree = scene.selectionOctree;
+            if (sceneOctree !== undefined && sceneOctree !== null) {
+                sceneOctree.addMesh(mesh);
             }
             }
         };
         };
         Geometry._CleanMatricesWeights = function (parsedGeometry, mesh) {
         Geometry._CleanMatricesWeights = function (parsedGeometry, mesh) {
@@ -34557,25 +34606,24 @@ var BABYLON;
         MaterialHelper.BindLights = function (scene, mesh, effect, defines, maxSimultaneousLights, usePhysicalLightFalloff) {
         MaterialHelper.BindLights = function (scene, mesh, effect, defines, maxSimultaneousLights, usePhysicalLightFalloff) {
             if (maxSimultaneousLights === void 0) { maxSimultaneousLights = 4; }
             if (maxSimultaneousLights === void 0) { maxSimultaneousLights = 4; }
             if (usePhysicalLightFalloff === void 0) { usePhysicalLightFalloff = false; }
             if (usePhysicalLightFalloff === void 0) { usePhysicalLightFalloff = false; }
-            var lightIndex = 0;
-            for (var _i = 0, _a = mesh._lightSources; _i < _a.length; _i++) {
-                var light = _a[_i];
+            for (var i = 0, len = mesh._lightSources.length, light, iAsString; i < len; i++) {
+                light = mesh._lightSources[i];
+                iAsString = i.toString();
                 var scaledIntensity = light.getScaledIntensity();
                 var scaledIntensity = light.getScaledIntensity();
-                light._uniformBuffer.bindToEffect(effect, "Light" + lightIndex);
-                MaterialHelper.BindLightProperties(light, effect, lightIndex);
+                light._uniformBuffer.bindToEffect(effect, "Light" + i);
+                MaterialHelper.BindLightProperties(light, effect, i);
                 light.diffuse.scaleToRef(scaledIntensity, BABYLON.Tmp.Color3[0]);
                 light.diffuse.scaleToRef(scaledIntensity, BABYLON.Tmp.Color3[0]);
-                light._uniformBuffer.updateColor4("vLightDiffuse", BABYLON.Tmp.Color3[0], usePhysicalLightFalloff ? light.radius : light.range, lightIndex + "");
+                light._uniformBuffer.updateColor4("vLightDiffuse", BABYLON.Tmp.Color3[0], usePhysicalLightFalloff ? light.radius : light.range, iAsString);
                 if (defines["SPECULARTERM"]) {
                 if (defines["SPECULARTERM"]) {
                     light.specular.scaleToRef(scaledIntensity, BABYLON.Tmp.Color3[1]);
                     light.specular.scaleToRef(scaledIntensity, BABYLON.Tmp.Color3[1]);
-                    light._uniformBuffer.updateColor3("vLightSpecular", BABYLON.Tmp.Color3[1], lightIndex + "");
+                    light._uniformBuffer.updateColor3("vLightSpecular", BABYLON.Tmp.Color3[1], iAsString);
                 }
                 }
                 // Shadows
                 // Shadows
                 if (scene.shadowsEnabled) {
                 if (scene.shadowsEnabled) {
-                    this.BindLightShadow(light, scene, mesh, lightIndex + "", effect);
+                    this.BindLightShadow(light, scene, mesh, iAsString, effect);
                 }
                 }
                 light._uniformBuffer.update();
                 light._uniformBuffer.update();
-                lightIndex++;
-                if (lightIndex === maxSimultaneousLights)
+                if (i === maxSimultaneousLights)
                     break;
                     break;
             }
             }
         };
         };
@@ -42179,6 +42227,7 @@ var BABYLON;
                 if (this._speedRatio === value) {
                 if (this._speedRatio === value) {
                     return;
                     return;
                 }
                 }
+                this._speedRatio = value;
                 for (var index = 0; index < this._animatables.length; index++) {
                 for (var index = 0; index < this._animatables.length; index++) {
                     var animatable = this._animatables[index];
                     var animatable = this._animatables[index];
                     animatable.speedRatio = this._speedRatio;
                     animatable.speedRatio = this._speedRatio;
@@ -42298,7 +42347,7 @@ var BABYLON;
                 this.restart();
                 this.restart();
             }
             }
             else {
             else {
-                this.start(loop);
+                this.start(loop, this._speedRatio);
             }
             }
             return this;
             return this;
         };
         };
@@ -51654,7 +51703,7 @@ var BABYLON;
                         for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                         for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                             var subMesh = mesh.subMeshes[subIndex];
                             var subMesh = mesh.subMeshes[subIndex];
                             scene._activeIndices.addCount(subMesh.indexCount, false);
                             scene._activeIndices.addCount(subMesh.indexCount, false);
-                            this._renderingManager.dispatch(subMesh);
+                            this._renderingManager.dispatch(subMesh, mesh);
                         }
                         }
                     }
                     }
                 }
                 }
@@ -77481,6 +77530,10 @@ var BABYLON;
                 var multiMaterial = scene.multiMaterials[index];
                 var multiMaterial = scene.multiMaterials[index];
                 serializationObject.multiMaterials.push(multiMaterial.serialize());
                 serializationObject.multiMaterials.push(multiMaterial.serialize());
             }
             }
+            // Environment texture
+            if (scene.environmentTexture) {
+                serializationObject.environmentTexture = scene.environmentTexture.name;
+            }
             // Skeletons
             // Skeletons
             serializationObject.skeletons = [];
             serializationObject.skeletons = [];
             for (index = 0; index < scene.skeletons.length; index++) {
             for (index = 0; index < scene.skeletons.length; index++) {

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


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


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


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


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


File diff suppressed because it is too large
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


File diff suppressed because it is too large
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


File diff suppressed because it is too large
+ 3 - 3
dist/preview release/materialsLibrary/babylonjs.materials.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


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


+ 3 - 1
src/Animations/babylon.animationGroup.ts

@@ -44,6 +44,8 @@ module BABYLON {
                 return;
                 return;
             }
             }
 
 
+            this._speedRatio = value;
+
             for (var index = 0; index < this._animatables.length; index++) {
             for (var index = 0; index < this._animatables.length; index++) {
                 let animatable = this._animatables[index];
                 let animatable = this._animatables[index];
                 animatable.speedRatio = this._speedRatio;
                 animatable.speedRatio = this._speedRatio;
@@ -177,7 +179,7 @@ module BABYLON {
                 }
                 }
                 this.restart();
                 this.restart();
             } else {
             } else {
-                this.start(loop);
+                this.start(loop, this._speedRatio);
             }
             }
 
 
             return this;
             return this;

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

@@ -279,7 +279,7 @@
      */
      */
     export class Engine {
     export class Engine {
         /** Use this array to turn off some WebGL2 features on known buggy browsers version */
         /** Use this array to turn off some WebGL2 features on known buggy browsers version */
-        public static WebGL2UniformBuffersExceptionList = ["Chrome/63"];
+        public static WebGL2UniformBuffersExceptionList = ["Chrome/63", "Firefox/58"];
 
 
         public static Instances = new Array<Engine>();
         public static Instances = new Array<Engine>();
 
 

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

@@ -445,7 +445,7 @@
                         for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                         for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                             var subMesh = mesh.subMeshes[subIndex];
                             var subMesh = mesh.subMeshes[subIndex];
                             scene._activeIndices.addCount(subMesh.indexCount, false);
                             scene._activeIndices.addCount(subMesh.indexCount, false);
-                            this._renderingManager.dispatch(subMesh);
+                            this._renderingManager.dispatch(subMesh, mesh);
                         }
                         }
                     }
                     }
                 }
                 }

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

@@ -148,7 +148,7 @@
                     if (onReady) {
                     if (onReady) {
                         onReady(new VideoTexture("video", video, scene, true, true));
                         onReady(new VideoTexture("video", video, scene, true, true));
                     }
                     }
-                }, function (e: DOMException) {
+                }, function (e: MediaStreamError) {
                     Tools.Error(e.name);
                     Tools.Error(e.name);
                 });
                 });
             }
             }

+ 10 - 9
src/Materials/babylon.materialHelper.ts

@@ -370,28 +370,29 @@
         }
         }
 
 
         public static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights = 4, usePhysicalLightFalloff = false) {
         public static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights = 4, usePhysicalLightFalloff = false) {
-            var lightIndex = 0;
-            for (var light of mesh._lightSources) {
+            for (var i = 0, len = mesh._lightSources.length, light, iAsString; i < len; i++) {
+                light = mesh._lightSources[i];
+                iAsString = i.toString();
+
                 let scaledIntensity = light.getScaledIntensity();
                 let scaledIntensity = light.getScaledIntensity();
-                light._uniformBuffer.bindToEffect(effect, "Light" + lightIndex);
+                light._uniformBuffer.bindToEffect(effect, "Light" + i);
 
 
-                MaterialHelper.BindLightProperties(light, effect, lightIndex);
+                MaterialHelper.BindLightProperties(light, effect, i);
 
 
                 light.diffuse.scaleToRef(scaledIntensity, Tmp.Color3[0]);
                 light.diffuse.scaleToRef(scaledIntensity, Tmp.Color3[0]);
-                light._uniformBuffer.updateColor4("vLightDiffuse", Tmp.Color3[0], usePhysicalLightFalloff ? light.radius : light.range, lightIndex + "");
+                light._uniformBuffer.updateColor4("vLightDiffuse", Tmp.Color3[0], usePhysicalLightFalloff ? light.radius : light.range, iAsString);
                 if (defines["SPECULARTERM"]) {
                 if (defines["SPECULARTERM"]) {
                     light.specular.scaleToRef(scaledIntensity, Tmp.Color3[1]);
                     light.specular.scaleToRef(scaledIntensity, Tmp.Color3[1]);
-                    light._uniformBuffer.updateColor3("vLightSpecular", Tmp.Color3[1], lightIndex + "");
+                    light._uniformBuffer.updateColor3("vLightSpecular", Tmp.Color3[1], iAsString);
                 }
                 }
 
 
                 // Shadows
                 // Shadows
                 if (scene.shadowsEnabled) {
                 if (scene.shadowsEnabled) {
-                    this.BindLightShadow(light, scene, mesh, lightIndex + "", effect);
+                    this.BindLightShadow(light, scene, mesh, iAsString, effect);
                 }
                 }
                 light._uniformBuffer.update();
                 light._uniformBuffer.update();
-                lightIndex++;
 
 
-                if (lightIndex === maxSimultaneousLights)
+                if (i === maxSimultaneousLights)
                     break;
                     break;
             }
             }
         }
         }

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

@@ -1322,7 +1322,7 @@
             var index: number;
             var index: number;
 
 
             // Action manager
             // Action manager
-            if (this.actionManager) {
+            if (this.actionManager !== undefined && this.actionManager !== null) {
                 this.actionManager.dispose();
                 this.actionManager.dispose();
                 this.actionManager = null;
                 this.actionManager = null;
             }
             }
@@ -1388,8 +1388,8 @@
             }
             }
 
 
             // Octree
             // Octree
-            var sceneOctree = this.getScene().selectionOctree;
-            if (sceneOctree) {
+            const sceneOctree = this.getScene().selectionOctree;
+            if (sceneOctree !== undefined && sceneOctree !== null) {
                 var index = sceneOctree.dynamicContent.indexOf(this);
                 var index = sceneOctree.dynamicContent.indexOf(this);
 
 
                 if (index !== -1) {
                 if (index !== -1) {

+ 3 - 2
src/Mesh/babylon.geometry.ts

@@ -1059,8 +1059,9 @@
             mesh.computeWorldMatrix(true);
             mesh.computeWorldMatrix(true);
 
 
             // Octree
             // Octree
-            if (scene['_selectionOctree']) {
-                scene['_selectionOctree'].addMesh(<AbstractMesh>mesh);
+            const sceneOctree = scene.selectionOctree;
+            if (sceneOctree !== undefined && sceneOctree !== null) {
+                sceneOctree.addMesh(<AbstractMesh>mesh);
             }
             }
         }
         }
 
 

+ 2 - 2
src/Mesh/babylon.mesh.ts

@@ -427,7 +427,7 @@
          * Returns a positive integer : the total number of vertices within the mesh geometry or zero if the mesh has no geometry.
          * Returns a positive integer : the total number of vertices within the mesh geometry or zero if the mesh has no geometry.
          */
          */
         public getTotalVertices(): number {
         public getTotalVertices(): number {
-            if (!this._geometry) {
+            if (this._geometry === null || this._geometry === undefined) {
                 return 0;
                 return 0;
             }
             }
             return this._geometry.getTotalVertices();
             return this._geometry.getTotalVertices();
@@ -2104,7 +2104,7 @@
             serializationObject.scaling = this.scaling.asArray();
             serializationObject.scaling = this.scaling.asArray();
             serializationObject.localMatrix = this.getPivotMatrix().asArray();
             serializationObject.localMatrix = this.getPivotMatrix().asArray();
 
 
-            serializationObject.isEnabled = this.isEnabled();
+            serializationObject.isEnabled = this.isEnabled(false);
             serializationObject.isVisible = this.isVisible;
             serializationObject.isVisible = this.isVisible;
             serializationObject.infiniteDistance = this.infiniteDistance;
             serializationObject.infiniteDistance = this.infiniteDistance;
             serializationObject.pickable = this.isPickable;
             serializationObject.pickable = this.isPickable;

+ 3 - 5
src/Mesh/babylon.subMesh.ts

@@ -101,7 +101,9 @@
         public getMaterial(): Nullable<Material> {
         public getMaterial(): Nullable<Material> {
             var rootMaterial = this._renderingMesh.material;
             var rootMaterial = this._renderingMesh.material;
 
 
-            if (rootMaterial && (<MultiMaterial>rootMaterial).getSubMaterial) {
+            if (rootMaterial === null || rootMaterial === undefined) {
+                return this._mesh.getScene().defaultMaterial;
+            } else if ((<MultiMaterial>rootMaterial).getSubMaterial) {
                 var multiMaterial = <MultiMaterial>rootMaterial;
                 var multiMaterial = <MultiMaterial>rootMaterial;
                 var effectiveMaterial = multiMaterial.getSubMaterial(this.materialIndex);
                 var effectiveMaterial = multiMaterial.getSubMaterial(this.materialIndex);
 
 
@@ -113,10 +115,6 @@
                 return effectiveMaterial;
                 return effectiveMaterial;
             }
             }
 
 
-            if (!rootMaterial) {
-                return this._mesh.getScene().defaultMaterial;
-            }
-
             return rootMaterial;
             return rootMaterial;
         }
         }
 
 

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

@@ -463,7 +463,7 @@ module BABYLON {
          */
          */
         public setParent(node: Nullable<Node>): TransformNode {
         public setParent(node: Nullable<Node>): TransformNode {
 
 
-            if (node == null) {
+            if (node === null) {
                 var rotation = Tmp.Quaternion[0];
                 var rotation = Tmp.Quaternion[0];
                 var position = Tmp.Vector3[0];
                 var position = Tmp.Vector3[0];
                 var scale = Tmp.Vector3[1];
                 var scale = Tmp.Vector3[1];

+ 12 - 5
src/Rendering/babylon.renderingGroup.ts

@@ -315,12 +315,19 @@
         /**
         /**
          * Inserts the submesh in its correct queue depending on its material.
          * Inserts the submesh in its correct queue depending on its material.
          * @param subMesh The submesh to dispatch
          * @param subMesh The submesh to dispatch
+         * @param [mesh] Optional reference to the submeshes's mesh. Provide if you have an exiting reference to improve performance.
+         * @param [material] Optional reference to the submeshes's material. Provide if you have an exiting reference to improve performance.
          */
          */
-        public dispatch(subMesh: SubMesh): void {
-            var material = subMesh.getMaterial();
-            var mesh = subMesh.getMesh();
+        public dispatch(subMesh: SubMesh, mesh?: AbstractMesh, material?: Nullable<Material>): void {
+            // Get mesh and materials if not provided
+            if (mesh === undefined) {
+                mesh = subMesh.getMesh();
+            }
+            if (material === undefined) {
+                material = subMesh.getMaterial();
+            }
 
 
-            if (!material) {
+            if (material === null || material === undefined) {
                 return;
                 return;
             }
             }
 
 
@@ -340,7 +347,7 @@
                 this._opaqueSubMeshes.push(subMesh); // Opaque
                 this._opaqueSubMeshes.push(subMesh); // Opaque
             }
             }
 
 
-            if (mesh._edgesRenderer) {
+            if (mesh._edgesRenderer !== null && mesh._edgesRenderer !== undefined) {
                 this._edgesRenderers.push(mesh._edgesRenderer);
                 this._edgesRenderers.push(mesh._edgesRenderer);
             }
             }
         }
         }

+ 11 - 4
src/Rendering/babylon.renderingManager.ts

@@ -142,7 +142,7 @@
         }
         }
 
 
         private _prepareRenderingGroup(renderingGroupId: number): void {
         private _prepareRenderingGroup(renderingGroupId: number): void {
-            if (!this._renderingGroups[renderingGroupId]) {
+            if (this._renderingGroups[renderingGroupId] === undefined) {
                 this._renderingGroups[renderingGroupId] = new RenderingGroup(renderingGroupId, this._scene,
                 this._renderingGroups[renderingGroupId] = new RenderingGroup(renderingGroupId, this._scene,
                     this._customOpaqueSortCompareFn[renderingGroupId],
                     this._customOpaqueSortCompareFn[renderingGroupId],
                     this._customAlphaTestSortCompareFn[renderingGroupId],
                     this._customAlphaTestSortCompareFn[renderingGroupId],
@@ -167,13 +167,20 @@
             this._renderingGroups[renderingGroupId].dispatchParticles(particleSystem);
             this._renderingGroups[renderingGroupId].dispatchParticles(particleSystem);
         }
         }
 
 
-        public dispatch(subMesh: SubMesh): void {
-            var mesh = subMesh.getMesh();
+        /**
+         * @param subMesh The submesh to dispatch
+         * @param [mesh] Optional reference to the submeshes's mesh. Provide if you have an exiting reference to improve performance.
+         * @param [material] Optional reference to the submeshes's material. Provide if you have an exiting reference to improve performance.
+         */
+        public dispatch(subMesh: SubMesh, mesh?: AbstractMesh, material?: Nullable<Material>): void {
+            if (mesh === undefined) {
+                mesh = subMesh.getMesh();
+            }
             var renderingGroupId = mesh.renderingGroupId || 0;
             var renderingGroupId = mesh.renderingGroupId || 0;
 
 
             this._prepareRenderingGroup(renderingGroupId);
             this._prepareRenderingGroup(renderingGroupId);
 
 
-            this._renderingGroups[renderingGroupId].dispatch(subMesh);
+            this._renderingGroups[renderingGroupId].dispatch(subMesh, mesh, material);
         }
         }
 
 
         /**
         /**

+ 6 - 1
src/Tools/babylon.sceneSerializer.ts

@@ -209,6 +209,11 @@
                 serializationObject.multiMaterials.push(multiMaterial.serialize());
                 serializationObject.multiMaterials.push(multiMaterial.serialize());
             }
             }
 
 
+            // Environment texture
+            if (scene.environmentTexture) {
+                serializationObject.environmentTexture = scene.environmentTexture.name;
+            }
+
             // Skeletons
             // Skeletons
             serializationObject.skeletons = [];
             serializationObject.skeletons = [];
             for (index = 0; index < scene.skeletons.length; index++) {
             for (index = 0; index < scene.skeletons.length; index++) {
@@ -219,7 +224,7 @@
             serializationObject.transformNodes = [];
             serializationObject.transformNodes = [];
             for (index = 0; index < scene.transformNodes.length; index++) {
             for (index = 0; index < scene.transformNodes.length; index++) {
                 serializationObject.transformNodes.push(scene.transformNodes[index].serialize());
                 serializationObject.transformNodes.push(scene.transformNodes[index].serialize());
-            }            
+            }
 
 
             // Geometries
             // Geometries
             serializationObject.geometries = {};
             serializationObject.geometries = {};

+ 14 - 43
src/babylon.mixins.ts

@@ -1,18 +1,11 @@
 // Mixins
 // Mixins
 interface Window {
 interface Window {
-    mozIndexedDB(func: any): any;
-    webkitIndexedDB(func: any): any;
+    mozIndexedDB: IDBFactory;
+    webkitIndexedDB: IDBFactory;
     msIndexedDB: IDBFactory;
     msIndexedDB: IDBFactory;
-    IDBTransaction(func: any): any;
-    webkitIDBTransaction(func: any): any;
-    msIDBTransaction(func: any): any;
-    IDBKeyRange(func: any): any;
-    webkitIDBKeyRange(func: any): any;
-    msIDBKeyRange(func: any): any;
-    webkitURL: HTMLURL;
-    webkitRequestAnimationFrame(func: any): any;
-    mozRequestAnimationFrame(func: any): any;
-    oRequestAnimationFrame(func: any): any;
+    webkitURL: typeof URL;
+    mozRequestAnimationFrame(callback: FrameRequestCallback): number;
+    oRequestAnimationFrame(callback: FrameRequestCallback): number;
     WebGLRenderingContext: WebGLRenderingContext;
     WebGLRenderingContext: WebGLRenderingContext;
     MSGesture: MSGesture;
     MSGesture: MSGesture;
     CANNON: any;
     CANNON: any;
@@ -23,8 +16,8 @@ interface Window {
     Math: Math;
     Math: Math;
     Uint8Array: Uint8ArrayConstructor;
     Uint8Array: Uint8ArrayConstructor;
     Float32Array: Float32ArrayConstructor;
     Float32Array: Float32ArrayConstructor;
-    mozURL: any;
-    msURL: any;
+    mozURL: typeof URL;
+    msURL: typeof URL;
     VRFrameData: any; // WebVR, from specs 1.1
     VRFrameData: any; // WebVR, from specs 1.1
 }
 }
 
 
@@ -81,13 +74,7 @@ interface WebGLRenderingContext {
     QUERY_RESULT: number;
     QUERY_RESULT: number;
 }
 }
 
 
-interface HTMLURL {
-    createObjectURL(param1: any, param2?: any): string;
-}
-
 interface Document {
 interface Document {
-    exitFullscreen(): void;
-    webkitCancelFullScreen(): void;
     mozCancelFullScreen(): void;
     mozCancelFullScreen(): void;
     msCancelFullScreen(): void;
     msCancelFullScreen(): void;
     mozFullScreen: boolean;
     mozFullScreen: boolean;
@@ -99,17 +86,12 @@ interface Document {
 }
 }
 
 
 interface HTMLCanvasElement {
 interface HTMLCanvasElement {
-    requestPointerLock(): void;
     msRequestPointerLock?(): void;
     msRequestPointerLock?(): void;
     mozRequestPointerLock?(): void;
     mozRequestPointerLock?(): void;
     webkitRequestPointerLock?(): void;
     webkitRequestPointerLock?(): void;
 }
 }
 
 
 interface CanvasRenderingContext2D {
 interface CanvasRenderingContext2D {
-    imageSmoothingEnabled: boolean;
-    mozImageSmoothingEnabled: boolean;
-    oImageSmoothingEnabled: boolean;
-    webkitImageSmoothingEnabled: boolean;
     msImageSmoothingEnabled: boolean;
     msImageSmoothingEnabled: boolean;
 }
 }
 
 
@@ -133,23 +115,16 @@ interface MouseEvent {
     msMovementY: number;
     msMovementY: number;
 }
 }
 
 
-interface MSStyleCSSProperties {
-    webkitTransform: string;
-    webkitTransition: string;
-}
-
 interface Navigator {
 interface Navigator {
     getVRDisplays: () => any;
     getVRDisplays: () => any;
     mozGetVRDevices: (any: any) => any;
     mozGetVRDevices: (any: any) => any;
-    getUserMedia: any;
-    webkitGetUserMedia: any;
-    mozGetUserMedia: any;
-    msGetUserMedia: any;
-
-    getGamepads(func?: any): any;
-    webkitGetGamepads(func?: any): any
-    msGetGamepads(func?: any): any;
-    webkitGamepads(func?: any): any;
+    webkitGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;
+    mozGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;
+    msGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;
+
+    webkitGetGamepads(): Gamepad[];
+    msGetGamepads(): Gamepad[];
+    webkitGamepads(): Gamepad[];
 }
 }
 
 
 interface HTMLVideoElement {
 interface HTMLVideoElement {
@@ -161,10 +136,6 @@ interface Screen {
     mozOrientation: string;
     mozOrientation: string;
 }
 }
 
 
-interface HTMLMediaElement {
-    crossOrigin: string | null;
-}
-
 interface Math {
 interface Math {
     fround(x: number): number;
     fround(x: number): number;
     imul(a: number, b: number): number;
     imul(a: number, b: number): number;

+ 15 - 7
src/babylon.node.ts

@@ -44,17 +44,20 @@
                 return;
                 return;
             }
             }
 
 
-            if (this._parentNode) {
+            // Remove self from list of children of parent
+            if (this._parentNode && this._parentNode._children !== undefined && this._parentNode._children !== null) {
                 var index = this._parentNode._children.indexOf(this);
                 var index = this._parentNode._children.indexOf(this);
                 if (index !== -1) {
                 if (index !== -1) {
                     this._parentNode._children.splice(index, 1);
                     this._parentNode._children.splice(index, 1);
                 }
                 }
             }
             }
 
 
+            // Store new parent
             this._parentNode = parent;
             this._parentNode = parent;
 
 
+            // Add as child to new parent
             if (this._parentNode) {
             if (this._parentNode) {
-                if (!this._parentNode._children) {
+                if (this._parentNode._children === undefined || this._parentNode._children === null) {
                     this._parentNode._children = new Array<Node>();
                     this._parentNode._children = new Array<Node>();
                 }
                 }
                 this._parentNode._children.push(this);
                 this._parentNode._children.push(this);
@@ -241,17 +244,22 @@
 
 
         /**
         /**
          * Is this node enabled. 
          * Is this node enabled. 
-         * If the node has a parent and is enabled, the parent will be inspected as well.
+         * If the node has a parent, all ancestors will be checked and false will be returned if any are false (not enabled), otherwise will return true.
+         * @param {boolean} [checkAncestors=true] - Indicates if this method should check the ancestors. The default is to check the ancestors. If set to false, the method will return the value of this node without checking ancestors.
          * @return {boolean} whether this node (and its parent) is enabled.
          * @return {boolean} whether this node (and its parent) is enabled.
          * @see setEnabled
          * @see setEnabled
          */
          */
-        public isEnabled(): boolean {
-            if (!this._isEnabled) {
+        public isEnabled(checkAncestors: boolean = true): boolean {
+            if (checkAncestors === false) {
+                return this._isEnabled;
+            }
+
+            if (this._isEnabled === false) {
                 return false;
                 return false;
             }
             }
 
 
-            if (this.parent) {
-                return this.parent.isEnabled();
+            if (this.parent !== undefined && this.parent !== null) {
+                return this.parent.isEnabled(checkAncestors);
             }
             }
 
 
             return true;
             return true;

+ 53 - 22
src/babylon.scene.ts

@@ -3,6 +3,11 @@
         dispose(): void;
         dispose(): void;
     }
     }
 
 
+    export interface IActiveMeshCandidateProvider {
+        getMeshes(scene: Scene): AbstractMesh[];
+        readonly checksIsEnabled: boolean; // Indicates if the meshes have been checked to make sure they are isEnabled().
+    }
+
     class ClickInfo {
     class ClickInfo {
         private _singleClick = false;
         private _singleClick = false;
         private _doubleClick = false;
         private _doubleClick = false;
@@ -874,6 +879,7 @@
         private _pendingData = new Array();
         private _pendingData = new Array();
         private _isDisposed = false;
         private _isDisposed = false;
 
 
+        public dispatchAllSubMeshesOfActiveMeshes:boolean = false;
         private _activeMeshes = new SmartArray<AbstractMesh>(256);
         private _activeMeshes = new SmartArray<AbstractMesh>(256);
         private _processedMaterials = new SmartArray<Material>(256);
         private _processedMaterials = new SmartArray<Material>(256);
         private _renderTargets = new SmartArrayNoDuplicate<RenderTargetTexture>(256);
         private _renderTargets = new SmartArrayNoDuplicate<RenderTargetTexture>(256);
@@ -2919,18 +2925,18 @@
         }
         }
 
 
         private _evaluateSubMesh(subMesh: SubMesh, mesh: AbstractMesh): void {
         private _evaluateSubMesh(subMesh: SubMesh, mesh: AbstractMesh): void {
-            if (mesh.alwaysSelectAsActiveMesh || mesh.subMeshes.length === 1 || subMesh.isInFrustum(this._frustumPlanes)) {
-                var material = subMesh.getMaterial();
-
+            if (this.dispatchAllSubMeshesOfActiveMeshes || mesh.alwaysSelectAsActiveMesh || mesh.subMeshes.length === 1 || subMesh.isInFrustum(this._frustumPlanes)) {
                 if (mesh.showSubMeshesBoundingBox) {
                 if (mesh.showSubMeshesBoundingBox) {
-                    let boundingInfo = subMesh.getBoundingInfo();
-
-                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
+                    const boundingInfo = subMesh.getBoundingInfo();
+                    if (boundingInfo !== null && boundingInfo !== undefined) {
+                        this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
+                    }
                 }
                 }
 
 
-                if (material) {
+                const material = subMesh.getMaterial();
+                if (material !== null && material !== undefined) {
                     // Render targets
                     // Render targets
-                    if (material.getRenderTargetTextures) {
+                    if (material.getRenderTargetTextures !== undefined) {
                         if (this._processedMaterials.indexOf(material) === -1) {
                         if (this._processedMaterials.indexOf(material) === -1) {
                             this._processedMaterials.push(material);
                             this._processedMaterials.push(material);
 
 
@@ -2940,7 +2946,7 @@
 
 
                     // Dispatch
                     // Dispatch
                     this._activeIndices.addCount(subMesh.indexCount, false);
                     this._activeIndices.addCount(subMesh.indexCount, false);
-                    this._renderingManager.dispatch(subMesh);
+                    this._renderingManager.dispatch(subMesh, mesh, material);
                 }
                 }
             }
             }
         }
         }
@@ -2949,6 +2955,14 @@
             return this._intermediateRendering
             return this._intermediateRendering
         }
         }
 
 
+        private _activeMeshCandidateProvider: IActiveMeshCandidateProvider;
+        public setActiveMeshCandidateProvider(provider: IActiveMeshCandidateProvider): void {
+            this._activeMeshCandidateProvider = provider;
+        }
+        public getActiveMeshCandidateProvider(): IActiveMeshCandidateProvider {
+            return this._activeMeshCandidateProvider;
+        }
+
         private _activeMeshesFrozen = false;
         private _activeMeshesFrozen = false;
 
 
         /**
         /**
@@ -2993,18 +3007,32 @@
             // Meshes
             // Meshes
             var meshes: AbstractMesh[];
             var meshes: AbstractMesh[];
             var len: number;
             var len: number;
-
-            if (this._selectionOctree) { // Octree
+            var checkIsEnabled = true;
+
+            // Determine mesh candidates
+            if (this._activeMeshCandidateProvider !== undefined) {
+                // Use _activeMeshCandidateProvider
+                meshes = this._activeMeshCandidateProvider.getMeshes(this);
+                checkIsEnabled = this._activeMeshCandidateProvider.checksIsEnabled === false;
+                if (meshes !== undefined) {
+                    len = meshes.length;
+                } else {
+                    len = 0;
+                }
+            } else if (this._selectionOctree !== undefined) {
+                // Octree
                 var selection = this._selectionOctree.select(this._frustumPlanes);
                 var selection = this._selectionOctree.select(this._frustumPlanes);
                 meshes = selection.data;
                 meshes = selection.data;
                 len = selection.length;
                 len = selection.length;
-            } else { // Full scene traversal
+            } else {
+                // Full scene traversal
                 len = this.meshes.length;
                 len = this.meshes.length;
                 meshes = this.meshes;
                 meshes = this.meshes;
             }
             }
 
 
-            for (var meshIndex = 0; meshIndex < len; meshIndex++) {
-                var mesh = meshes[meshIndex];
+            // Check each mesh
+            for (var meshIndex = 0, mesh, meshLOD; meshIndex < len; meshIndex++) {
+                mesh = meshes[meshIndex];
 
 
                 if (mesh.isBlocked) {
                 if (mesh.isBlocked) {
                     continue;
                     continue;
@@ -3012,7 +3040,7 @@
 
 
                 this._totalVertices.addCount(mesh.getTotalVertices(), false);
                 this._totalVertices.addCount(mesh.getTotalVertices(), false);
 
 
-                if (!mesh.isReady() || !mesh.isEnabled()) {
+                if (!mesh.isReady() || (checkIsEnabled && !mesh.isEnabled())) {
                     continue;
                     continue;
                 }
                 }
 
 
@@ -3024,9 +3052,9 @@
                 }
                 }
 
 
                 // Switch to current LOD
                 // Switch to current LOD
-                var meshLOD = mesh.getLOD(this.activeCamera);
+                meshLOD = mesh.getLOD(this.activeCamera);
 
 
-                if (!meshLOD) {
+                if (meshLOD === undefined || meshLOD === null) {
                     continue;
                     continue;
                 }
                 }
 
 
@@ -3069,7 +3097,7 @@
         }
         }
 
 
         private _activeMesh(sourceMesh: AbstractMesh, mesh: AbstractMesh): void {
         private _activeMesh(sourceMesh: AbstractMesh, mesh: AbstractMesh): void {
-            if (mesh.skeleton && this.skeletonsEnabled) {
+            if (this.skeletonsEnabled && mesh.skeleton !== null && mesh.skeleton !== undefined) {
                 if (this._activeSkeletons.pushNoDuplicate(mesh.skeleton)) {
                 if (this._activeSkeletons.pushNoDuplicate(mesh.skeleton)) {
                     mesh.skeleton.prepare();
                     mesh.skeleton.prepare();
                 }
                 }
@@ -3085,12 +3113,15 @@
                 this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
                 this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
             }
             }
 
 
-            if (mesh && mesh.subMeshes) {
+            if (
+                mesh !== undefined && mesh !== null
+                && mesh.subMeshes !== undefined && mesh.subMeshes !== null && mesh.subMeshes.length > 0
+            ) {
                 // Submeshes Octrees
                 // Submeshes Octrees
                 var len: number;
                 var len: number;
                 var subMeshes: SubMesh[];
                 var subMeshes: SubMesh[];
 
 
-                if (mesh._submeshesOctree && mesh.useOctreeForRenderingSelection) {
+                if (mesh.useOctreeForRenderingSelection && mesh._submeshesOctree !== undefined && mesh._submeshesOctree !== null) {
                     var intersections = mesh._submeshesOctree.select(this._frustumPlanes);
                     var intersections = mesh._submeshesOctree.select(this._frustumPlanes);
 
 
                     len = intersections.length;
                     len = intersections.length;
@@ -3100,8 +3131,8 @@
                     len = subMeshes.length;
                     len = subMeshes.length;
                 }
                 }
 
 
-                for (var subIndex = 0; subIndex < len; subIndex++) {
-                    var subMesh = subMeshes[subIndex];
+                for (var subIndex = 0, subMesh; subIndex < len; subIndex++) {
+                    subMesh = subMeshes[subIndex];
 
 
                     this._evaluateSubMesh(subMesh, mesh);
                     this._evaluateSubMesh(subMesh, mesh);
                 }
                 }