Forráskód Böngészése

Merge pull request #3148 from BabylonJS/master

Nightly
David Catuhe 7 éve
szülő
commit
baef72b5ef
78 módosított fájl, 5960 hozzáadás és 5512 törlés
  1. 1 1
      .vscode/tasks.json
  2. 1 0
      Viewer/dist/viewer.js
  3. 4 1
      Viewer/src/viewer/viewer.ts
  4. 940 923
      dist/preview release/babylon.d.ts
  5. 42 42
      dist/preview release/babylon.js
  6. 263 134
      dist/preview release/babylon.max.js
  7. 940 923
      dist/preview release/babylon.module.d.ts
  8. 42 42
      dist/preview release/babylon.worker.js
  9. 906 889
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  10. 42 42
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  11. 442 200
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  12. 906 889
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  13. 1 1
      dist/preview release/gui/package.json
  14. 5 5
      dist/preview release/inspector/babylon.inspector.bundle.js
  15. 4 0
      dist/preview release/inspector/babylon.inspector.css
  16. 6 18
      dist/preview release/inspector/babylon.inspector.d.ts
  17. 68 234
      dist/preview release/inspector/babylon.inspector.js
  18. 4 4
      dist/preview release/inspector/babylon.inspector.min.js
  19. 1 1
      dist/preview release/inspector/package.json
  20. 4 4
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  21. 3 0
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  22. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  23. 11 8
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  24. 179 66
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  25. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  26. 11 8
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  27. 179 66
      dist/preview release/loaders/babylon.glTFFileLoader.js
  28. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  29. 179 66
      dist/preview release/loaders/babylonjs.loaders.js
  30. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  31. 11 8
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  32. 1 1
      dist/preview release/loaders/package.json
  33. 1 1
      dist/preview release/materialsLibrary/package.json
  34. 1 1
      dist/preview release/postProcessesLibrary/package.json
  35. 1 1
      dist/preview release/proceduralTexturesLibrary/package.json
  36. 1 1
      dist/preview release/serializers/package.json
  37. 1 1
      gui/src/advancedDynamicTexture.ts
  38. 8 1
      inspector/sass/_tree.scss
  39. 0 5
      inspector/src/adapters/Adapter.ts
  40. 16 8
      inspector/src/adapters/MeshAdapter.ts
  41. 15 13
      inspector/src/details/PropertyLine.ts
  42. 29 13
      inspector/src/helpers/Helpers.ts
  43. 17 237
      inspector/src/properties.ts
  44. 39 22
      inspector/src/tabs/MeshTab.ts
  45. 78 77
      inspector/src/tabs/SceneTab.ts
  46. 8 0
      inspector/src/tree/TreeItem.ts
  47. 24 284
      inspector/test/index.js
  48. 1 0
      loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts
  49. 22 16
      loaders/src/glTF/2.0/Extensions/MSFT_lod.ts
  50. 162 47
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  51. 7 8
      loaders/src/glTF/babylon.glTFFileLoader.ts
  52. 1 1
      package.json
  53. 1 1
      sandbox/index.css
  54. 2 7
      sandbox/index.js
  55. 0 5
      src/Audio/babylon.sound.ts
  56. 1 1
      src/Behaviors/Cameras/babylon.bouncingBehavior.ts
  57. 1 1
      src/Behaviors/Cameras/babylon.framingBehavior.ts
  58. 47 24
      src/Cameras/VR/babylon.vrExperienceHelper.ts
  59. 2 0
      src/Cameras/VR/babylon.webVRCamera.ts
  60. 2 2
      src/Collisions/babylon.collisionCoordinator.ts
  61. 2 2
      src/Culling/Octrees/babylon.octree.ts
  62. 1 1
      src/Engine/babylon.engine.ts
  63. 24 10
      src/Lights/Shadows/babylon.shadowGenerator.ts
  64. 0 5
      src/Lights/babylon.directionalLight.ts
  65. 15 0
      src/Loading/Plugins/babylon.babylonFileLoader.ts
  66. 9 3
      src/Materials/babylon.material.ts
  67. 66 68
      src/Mesh/babylon.abstractMesh.ts
  68. 1 7
      src/Mesh/babylon.instancedMesh.ts
  69. 2 10
      src/Mesh/babylon.mesh.ts
  70. 1 1
      src/Mesh/babylon.mesh.vertexData.ts
  71. 3 11
      src/Mesh/babylon.subMesh.ts
  72. 122 0
      src/Mesh/babylon.transformNode.ts
  73. 4 6
      src/Particles/babylon.solidParticleSystem.ts
  74. 2 2
      src/Physics/Plugins/babylon.cannonJSPlugin.ts
  75. 2 10
      src/Physics/babylon.physicsImpostor.ts
  76. 1 1
      src/Rendering/babylon.renderingGroup.ts
  77. 6 0
      src/Tools/babylon.sceneSerializer.ts
  78. 6 12
      src/babylon.scene.ts

+ 1 - 1
.vscode/tasks.json

@@ -26,7 +26,7 @@
                     "code": 4,
                     "message": 5
                 },
-                "watching": {
+                "background": {
                     "activeOnStart": true,
                     "beginsPattern": "Starting \\'watch\\'",
                     "endsPattern": "Finished \\'run\\'"

+ 1 - 0
Viewer/dist/viewer.js

@@ -78315,6 +78315,7 @@ var AbstractViewer = (function () {
         }
         var config = this.configuration.engine || {};
         this.engine = new babylonjs_1.Engine(canvasElement, !!config.antialiasing);
+        babylonjs_1.Database.IDBStorageEnabled = false;
         window.addEventListener('resize', function () {
             _this.engine.resize();
         });

+ 4 - 1
Viewer/src/viewer/viewer.ts

@@ -1,7 +1,7 @@
 import { viewerManager } from './viewerManager';
 import { TemplateManager } from './../templateManager';
 import configurationLoader from './../configuration/loader';
-import { Observable, Engine, Scene, ArcRotateCamera, Vector3, SceneLoader, AbstractMesh, Mesh, HemisphericLight } from 'babylonjs';
+import { Observable, Engine, Scene, ArcRotateCamera, Vector3, SceneLoader, AbstractMesh, Mesh, HemisphericLight, Database } from 'babylonjs';
 import { ViewerConfiguration } from '../configuration/configuration';
 import { PromiseObservable } from '../util/promiseObservable';
 
@@ -106,6 +106,9 @@ export abstract class AbstractViewer {
         // TDO enable further configuration
         this.engine = new Engine(canvasElement, !!config.antialiasing);
 
+        // Disable manifest checking
+        Database.IDBStorageEnabled = false;
+
         window.addEventListener('resize', () => {
             this.engine.resize();
         });

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 940 - 923
dist/preview release/babylon.d.ts


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 42 - 42
dist/preview release/babylon.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 263 - 134
dist/preview release/babylon.max.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 940 - 923
dist/preview release/babylon.module.d.ts


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 42 - 42
dist/preview release/babylon.worker.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 906 - 889
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 42 - 42
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 442 - 200
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 906 - 889
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


+ 1 - 1
dist/preview release/gui/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-gui",
     "description": "The Babylon.js GUI library is an extension you can use to generate interactive user interface. It is build on top of the DynamicTexture.",
-    "version": "3.1.0-beta1.1",
+    "version": "3.1.0-beta3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 5 - 5
dist/preview release/inspector/babylon.inspector.bundle.js


+ 4 - 0
dist/preview release/inspector/babylon.inspector.css

@@ -273,6 +273,10 @@
         display: inline-block;
         font-family: 'FontAwesome', sans-serif;
         content: "\f054"; }
+      .insp-wrapper .insp-tree .line.unfolded.transformNode > span:first-of-type {
+        color: #f29766; }
+      .insp-wrapper .insp-tree .line.folded.transformNode > span:first-of-type {
+        color: #f29766; }
       .insp-wrapper .insp-tree .line .line-content {
         padding-left: 15px; }
         .insp-wrapper .insp-tree .line .line-content:hover {

+ 6 - 18
dist/preview release/inspector/babylon.inspector.d.ts

@@ -73,17 +73,14 @@ declare module INSPECTOR {
         };
         'Vector2': {
             type: typeof BABYLON.Vector2;
-            properties: string[];
             format: (vec: BABYLON.Vector2) => string;
         };
         'Vector3': {
             type: typeof BABYLON.Vector3;
-            properties: string[];
             format: (vec: BABYLON.Vector3) => string;
         };
         'Color3': {
             type: typeof BABYLON.Color3;
-            properties: string[];
             format: (color: BABYLON.Color3) => string;
             slider: {
                 r: {
@@ -105,7 +102,6 @@ declare module INSPECTOR {
         };
         'Color4': {
             type: typeof BABYLON.Color4;
-            properties: string[];
             format: (color: BABYLON.Color4) => string;
             slider: {
                 r: {
@@ -127,16 +123,13 @@ declare module INSPECTOR {
         };
         'Quaternion': {
             type: typeof BABYLON.Quaternion;
-            properties: string[];
         };
         'Size': {
             type: typeof BABYLON.Size;
-            properties: string[];
             format: (size: BABYLON.Size) => string;
         };
         'Texture': {
             type: typeof BABYLON.Texture;
-            properties: string[];
             format: (tex: BABYLON.Texture) => string;
         };
         'RenderTargetTexture': {
@@ -156,11 +149,9 @@ declare module INSPECTOR {
         };
         'Sound': {
             type: typeof BABYLON.Sound;
-            properties: string[];
         };
         'ArcRotateCamera': {
             type: typeof BABYLON.ArcRotateCamera;
-            properties: string[];
             slider: {
                 alpha: {
                     min: number;
@@ -181,7 +172,6 @@ declare module INSPECTOR {
         };
         'FreeCamera': {
             type: typeof BABYLON.FreeCamera;
-            properties: string[];
             slider: {
                 fov: {
                     min: number;
@@ -192,11 +182,9 @@ declare module INSPECTOR {
         };
         'Scene': {
             type: typeof BABYLON.Scene;
-            properties: string[];
         };
         'Mesh': {
             type: typeof BABYLON.Mesh;
-            properties: string[];
             format: (m: BABYLON.Mesh) => string;
             slider: {
                 visibility: {
@@ -208,7 +196,6 @@ declare module INSPECTOR {
         };
         'StandardMaterial': {
             type: typeof BABYLON.StandardMaterial;
-            properties: string[];
             format: (mat: BABYLON.StandardMaterial) => string;
             slider: {
                 alpha: {
@@ -220,7 +207,6 @@ declare module INSPECTOR {
         };
         'PBRMaterial': {
             type: typeof BABYLON.PBRMaterial;
-            properties: string[];
             slider: {
                 alpha: {
                     min: number;
@@ -231,7 +217,6 @@ declare module INSPECTOR {
         };
         'PhysicsImpostor': {
             type: typeof BABYLON.PhysicsImpostor;
-            properties: string[];
         };
     };
 }
@@ -277,8 +262,6 @@ declare module INSPECTOR {
         abstract type(): string;
         /** Returns the list of properties to be displayed for this adapter */
         abstract getProperties(): Array<PropertyLine>;
-        /** Returns the actual object behind this adapter */
-        readonly actualObject: any;
         /** Returns true if the given object correspond to this  */
         correspondsTo(obj: any): boolean;
         /** Returns the adapter unique name */
@@ -399,7 +382,7 @@ declare module INSPECTOR {
         /** Keep track of the axis of the actual object */
         private _axesViewer;
         private onBeforeRenderObserver;
-        constructor(mesh: BABYLON.AbstractMesh);
+        constructor(mesh: BABYLON.Node);
         /** Returns the name displayed in the tree */
         id(): string;
         /** Returns the type of this object - displayed in the tree */
@@ -767,6 +750,11 @@ declare module INSPECTOR {
          * @param obj
          */
         static GetAllLinesProperties(obj: any): Array<PropertyLine>;
+        /**
+         * Returns an array of string corresponding to tjhe list of properties of the object to be displayed
+         * @param obj
+         */
+        static GetAllLinesPropertiesAsString(obj: any): Array<string>;
         static Capitalize(str: string): string;
     }
 }

+ 68 - 234
dist/preview release/inspector/babylon.inspector.js

@@ -371,17 +371,14 @@ var INSPECTOR;
         },
         'Vector2': {
             type: BABYLON.Vector2,
-            properties: ['x', 'y'],
             format: function (vec) { return "x:" + INSPECTOR.Helpers.Trunc(vec.x) + ", y:" + INSPECTOR.Helpers.Trunc(vec.y); }
         },
         'Vector3': {
             type: BABYLON.Vector3,
-            properties: ['x', 'y', 'z'],
             format: function (vec) { return "x:" + INSPECTOR.Helpers.Trunc(vec.x) + ", y:" + INSPECTOR.Helpers.Trunc(vec.y) + ", z:" + INSPECTOR.Helpers.Trunc(vec.z); }
         },
         'Color3': {
             type: BABYLON.Color3,
-            properties: ['r', 'g', 'b'],
             format: function (color) { return "R:" + color.r + ", G:" + color.g + ", B:" + color.b; },
             slider: {
                 r: { min: 0, max: 1, step: 0.01 },
@@ -391,7 +388,6 @@ var INSPECTOR;
         },
         'Color4': {
             type: BABYLON.Color4,
-            properties: ['r', 'g', 'b'],
             format: function (color) { return "R:" + color.r + ", G:" + color.g + ", B:" + color.b; },
             slider: {
                 r: { min: 0, max: 1, step: 0.01 },
@@ -400,30 +396,14 @@ var INSPECTOR;
             }
         },
         'Quaternion': {
-            type: BABYLON.Quaternion,
-            properties: ['x', 'y', 'z', 'w']
+            type: BABYLON.Quaternion
         },
         'Size': {
             type: BABYLON.Size,
-            properties: ['width', 'height'],
             format: function (size) { return "Size - w:" + INSPECTOR.Helpers.Trunc(size.width) + ", h:" + INSPECTOR.Helpers.Trunc(size.height); }
         },
         'Texture': {
             type: BABYLON.Texture,
-            properties: [
-                'hasAlpha',
-                'level',
-                'name',
-                'wrapU',
-                'wrapV',
-                'uScale',
-                'vScale',
-                'uAng',
-                'vAng',
-                'wAng',
-                'uOffset',
-                'vOffset'
-            ],
             format: function (tex) { return tex.name; }
         },
         'RenderTargetTexture': {
@@ -442,45 +422,10 @@ var INSPECTOR;
             type: BABYLON.HDRCubeTexture
         },
         'Sound': {
-            type: BABYLON.Sound,
-            properties: [
-                'name',
-                'autoplay',
-                'loop',
-                'useCustomAttenuation',
-                'soundTrackId',
-                'spatialSound',
-                'refDistance',
-                'rolloffFactor',
-                'maxDistance',
-                'distanceModel',
-                'isPlaying',
-                'isPaused'
-            ]
+            type: BABYLON.Sound
         },
         'ArcRotateCamera': {
             type: BABYLON.ArcRotateCamera,
-            properties: [
-                'position',
-                'alpha',
-                'beta',
-                'radius',
-                'angularSensibilityX',
-                'angularSensibilityY',
-                'angularTouchSensibilityX',
-                'angularTouchSensibilityY',
-                'target',
-                'lowerAlphaLimit',
-                'lowerBetaLimit',
-                'upperAlphaLimit',
-                'upperBetaLimit',
-                'lowerRadiusLimit',
-                'upperRadiusLimit',
-                'pinchPrecision',
-                'wheelPrecision',
-                'allowUpsideDown',
-                'checkCollisions'
-            ],
             slider: {
                 alpha: { min: 0, max: 2 * Math.PI, step: 0.01 },
                 beta: { min: -Math.PI, max: Math.PI, step: 0.01 },
@@ -489,97 +434,15 @@ var INSPECTOR;
         },
         'FreeCamera': {
             type: BABYLON.FreeCamera,
-            properties: [
-                'position',
-                'rotation',
-                'rotationQuaternion',
-                'cameraDirection',
-                'cameraRotation',
-                'ellipsoid',
-                'applyGravity',
-                'angularSensibility',
-                'keysUp',
-                'keysDown',
-                'keysLeft',
-                'keysRight',
-                'checkCollisions',
-                'speed',
-                'lockedTarget',
-                'noRotationConstraint',
-                'fov',
-                'inertia',
-                'minZ', 'maxZ',
-                'layerMask',
-                'mode',
-                'orthoBottom',
-                'orthoTop',
-                'orthoLeft',
-                'orthoRight'
-            ],
             slider: {
                 fov: { min: 0, max: 180, step: 1 }
             }
         },
         'Scene': {
             type: BABYLON.Scene,
-            properties: [
-                'actionManager',
-                'activeCamera',
-                'ambientColor',
-                'clearColor',
-                'forceWireframe',
-                'forcePointsCloud',
-                'forceShowBoundingBoxes',
-                'useRightHandedSystem',
-                'hoverCursor',
-                'cameraToUseForPointers',
-                'fogEnabled',
-                'fogColor',
-                'fogDensity',
-                'fogStart',
-                'fogEnd',
-                'shadowsEnabled',
-                'lightsEnabled',
-                'collisionsEnabled',
-                'gravity',
-                'meshUnderPointer',
-                'pointerX',
-                'pointerY',
-                'uid'
-            ]
         },
         'Mesh': {
             type: BABYLON.Mesh,
-            properties: [
-                'name',
-                'position',
-                'rotation',
-                'rotationQuaternion',
-                'absolutePosition',
-                'material',
-                'actionManager',
-                'visibility',
-                'isVisible',
-                'isPickable',
-                'renderingGroupId',
-                'receiveShadows',
-                'renderOutline',
-                'outlineColor',
-                'outlineWidth',
-                'renderOverlay',
-                'overlayColor',
-                'overlayAlpha',
-                'hasVertexAlpha',
-                'useVertexColors',
-                'layerMask',
-                'alwaysSelectAsActiveMesh',
-                'ellipsoid',
-                'ellipsoidOffset',
-                'edgesWidth',
-                'edgesColor',
-                'checkCollisions',
-                'hasLODLevels'
-            ],
             format: function (m) { return m.name; },
             slider: {
                 visibility: { min: 0, max: 1, step: 0.1 }
@@ -587,36 +450,6 @@ var INSPECTOR;
         },
         'StandardMaterial': {
             type: BABYLON.StandardMaterial,
-            properties: [
-                'name',
-                'alpha',
-                'alphaMode',
-                'wireframe',
-                'isFrozen',
-                'zOffset',
-                'ambientColor',
-                'emissiveColor',
-                'diffuseColor',
-                'specularColor',
-                'specularPower',
-                'useAlphaFromDiffuseTexture',
-                'linkEmissiveWithDiffuse',
-                'useSpecularOverAlpha',
-                'diffuseFresnelParameters',
-                'opacityFresnelParameters',
-                'reflectionFresnelParameters',
-                'refractionFresnelParameters',
-                'emissiveFresnelParameters',
-                'diffuseTexture',
-                'emissiveTexture',
-                'specularTexture',
-                'ambientTexture',
-                'bumpTexture',
-                'lightMapTexture',
-                'opacityTexture',
-                'reflectionTexture',
-                'refractionTexture'
-            ],
             format: function (mat) { return mat.name; },
             slider: {
                 alpha: { min: 0, max: 1, step: 0.01 }
@@ -624,52 +457,12 @@ var INSPECTOR;
         },
         'PBRMaterial': {
             type: BABYLON.PBRMaterial,
-            properties: [
-                'name',
-                'albedoColor',
-                'albedoTexture',
-                'opacityTexture',
-                'reflectionTexture',
-                'emissiveTexture',
-                'bumpTexture',
-                'lightmapTexture',
-                'opacityFresnelParameters',
-                'emissiveFresnelParameters',
-                'linkEmissiveWithAlbedo',
-                'useLightmapAsShadowmap',
-                'useAlphaFromAlbedoTexture',
-                'useSpecularOverAlpha',
-                'useAutoMicroSurfaceFromReflectivityMap',
-                'useLogarithmicDepth',
-                'reflectivityColor',
-                'reflectivityTexture',
-                'reflectionTexture',
-                'reflectionColor',
-                'alpha',
-                'linkRefractionWithTransparency',
-                'indexOfRefraction',
-                'microSurface',
-                'useMicroSurfaceFromReflectivityMapAlpha',
-                'directIntensity',
-                'emissiveIntensity',
-                'specularIntensity',
-                'environmentIntensity',
-                'cameraExposure',
-                'cameraContrast',
-                'cameraColorGradingTexture',
-                'cameraColorCurves'
-            ],
             slider: {
                 alpha: { min: 0, max: 1, step: 0.01 }
             }
         },
         'PhysicsImpostor': {
-            type: BABYLON.PhysicsImpostor,
-            properties: [
-                'friction',
-                'mass',
-                'restitution',
-            ]
+            type: BABYLON.PhysicsImpostor
         },
     };
 })(INSPECTOR || (INSPECTOR = {}));
@@ -833,14 +626,6 @@ var INSPECTOR;
         function Adapter(obj) {
             this._obj = obj;
         }
-        Object.defineProperty(Adapter.prototype, "actualObject", {
-            /** Returns the actual object behind this adapter */
-            get: function () {
-                return this._obj;
-            },
-            enumerable: true,
-            configurable: true
-        });
         /** Returns true if the given object correspond to this  */
         Adapter.prototype.correspondsTo = function (obj) {
             return obj === this._obj;
@@ -1267,8 +1052,10 @@ var INSPECTOR;
             var tools = [];
             tools.push(new INSPECTOR.Checkbox(this));
             tools.push(new INSPECTOR.DebugArea(this));
-            if (this._obj.getTotalVertices() > 0) {
-                tools.push(new INSPECTOR.BoundingBox(this));
+            if (this._obj instanceof BABYLON.AbstractMesh) {
+                if (this._obj.getTotalVertices() > 0) {
+                    tools.push(new INSPECTOR.BoundingBox(this));
+                }
             }
             tools.push(new INSPECTOR.Info(this));
             return tools;
@@ -1301,7 +1088,10 @@ var INSPECTOR;
         };
         /** Returns some information about this mesh */
         MeshAdapter.prototype.getInfo = function () {
-            return this._obj.getTotalVertices() + " vertices";
+            if (this._obj instanceof BABYLON.AbstractMesh) {
+                return this._obj.getTotalVertices() + " vertices";
+            }
+            return '0 vertices';
         };
         /** Draw X, Y and Z axis for the actual object if this adapter.
          * Should be called only one time as it will fill this._axis
@@ -1309,15 +1099,18 @@ var INSPECTOR;
         MeshAdapter.prototype._drawAxis = function () {
             var _this = this;
             this._obj.computeWorldMatrix();
-            var mesh = this._obj;
             // Axis
             var x = new BABYLON.Vector3(1, 0, 0);
             var y = new BABYLON.Vector3(0, 1, 0);
             var z = new BABYLON.Vector3(0, 0, 1);
             this._axesViewer = new BABYLON.Debug.AxesViewer(this._obj.getScene());
+            var mesh = this._obj;
             this.onBeforeRenderObserver = mesh.getScene().onBeforeRenderObservable.add(function () {
                 var matrix = mesh.getWorldMatrix();
-                var extend = mesh.getBoundingInfo().boundingBox.extendSizeWorld;
+                var extend = new BABYLON.Vector3(1, 1, 1);
+                if (mesh instanceof BABYLON.AbstractMesh) {
+                    extend = mesh.getBoundingInfo().boundingBox.extendSizeWorld;
+                }
                 _this._axesViewer.scaleLines = Math.max(extend.x, extend.y, extend.z) * 2;
                 _this._axesViewer.update(_this._obj.position, BABYLON.Vector3.TransformNormal(x, matrix), BABYLON.Vector3.TransformNormal(y, matrix), BABYLON.Vector3.TransformNormal(z, matrix));
             });
@@ -1893,7 +1686,9 @@ var INSPECTOR;
                 this._div.classList.toggle('unfolded');
                 if (this._children.length == 0) {
                     var objToDetail = this.value;
-                    var propToDisplay = INSPECTOR.PROPERTIES[INSPECTOR.Helpers.GET_TYPE(objToDetail)].properties.slice().reverse();
+                    // Display all properties that are not functions
+                    var propToDisplay = INSPECTOR.Helpers.GetAllLinesPropertiesAsString(objToDetail);
+                    propToDisplay.sort().reverse();
                     for (var _b = 0, propToDisplay_1 = propToDisplay; _b < propToDisplay_1.length; _b++) {
                         var prop = propToDisplay_1[_b];
                         var infos = new INSPECTOR.Property(prop, this._property.value);
@@ -2484,6 +2279,9 @@ var INSPECTOR;
         };
         /** Returns the given number with 2 decimal number max if a decimal part exists */
         Helpers.Trunc = function (nb) {
+            if (typeof nb !== 'number') {
+                return 0;
+            }
             if (Math.round(nb) !== nb) {
                 return nb.toFixed(2);
             }
@@ -2568,16 +2366,27 @@ var INSPECTOR;
          */
         Helpers.GetAllLinesProperties = function (obj) {
             var propertiesLines = [];
+            var props = Helpers.GetAllLinesPropertiesAsString(obj);
+            for (var _i = 0, props_1 = props; _i < props_1.length; _i++) {
+                var prop = props_1[_i];
+                var infos = new INSPECTOR.Property(prop, obj);
+                propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+            }
+            return propertiesLines;
+        };
+        /**
+         * Returns an array of string corresponding to tjhe list of properties of the object to be displayed
+         * @param obj
+         */
+        Helpers.GetAllLinesPropertiesAsString = function (obj) {
+            var props = [];
             for (var prop in obj) {
-                /**
-                 * No private and no function
-                 */
+                //No private and no function
                 if (prop.substring(0, 1) !== '_' && typeof obj[prop] !== 'function') {
-                    var infos = new INSPECTOR.Property(prop, obj);
-                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                    props.push(prop);
                 }
             }
-            return propertiesLines;
+            return props;
         };
         Helpers.Capitalize = function (str) {
             return str.charAt(0).toUpperCase() + str.slice(1);
@@ -3291,7 +3100,7 @@ var INSPECTOR;
                 if (descendants.length > 0) {
                     for (var _i = 0, descendants_1 = descendants; _i < descendants_1.length; _i++) {
                         var child = descendants_1[_i];
-                        if (child instanceof BABYLON.AbstractMesh) {
+                        if (child instanceof BABYLON.TransformNode) {
                             if (!INSPECTOR.Helpers.IsSystemName(child.name)) {
                                 var n = createNode(child);
                                 node.add(n);
@@ -3319,8 +3128,25 @@ var INSPECTOR;
             };
             // get all meshes from the first scene
             var instances = this._inspector.scene;
+            // Find top of hierarchy for meshes...
+            var meshWithoutAnyParent = [];
             for (var _i = 0, _a = instances.meshes; _i < _a.length; _i++) {
                 var mesh = _a[_i];
+                // Not already in the array, not system name and no parent
+                if (meshWithoutAnyParent.indexOf(mesh) == -1 && !INSPECTOR.Helpers.IsSystemName(mesh.name) && !mesh.parent) {
+                    meshWithoutAnyParent.push(mesh);
+                }
+            }
+            // ... and for transforms
+            for (var _b = 0, _c = instances.transformNodes; _b < _c.length; _b++) {
+                var tn = _c[_b];
+                // Not already in the array, not system name and no parent
+                if (meshWithoutAnyParent.indexOf(tn) == -1 && !INSPECTOR.Helpers.IsSystemName(tn.name) && !tn.parent) {
+                    meshWithoutAnyParent.push(tn);
+                }
+            }
+            for (var _d = 0, meshWithoutAnyParent_1 = meshWithoutAnyParent; _d < meshWithoutAnyParent_1.length; _d++) {
+                var mesh = meshWithoutAnyParent_1[_d];
                 if (alreadyIn.indexOf(mesh) == -1 && !INSPECTOR.Helpers.IsSystemName(mesh.name)) {
                     var node = createNode(mesh);
                     arr.push(node);
@@ -3359,9 +3185,10 @@ var INSPECTOR;
             _this._panel.appendChild(_this._detailsPanel.toHtml());
             // build propertiesline
             var details = [];
-            for (var _i = 0, _a = INSPECTOR.PROPERTIES['Scene'].properties; _i < _a.length; _i++) {
-                var prop = _a[_i];
-                details.push(new INSPECTOR.PropertyLine(new INSPECTOR.Property(prop, _this._inspector.scene)));
+            var props = INSPECTOR.Helpers.GetAllLinesProperties(_this._inspector.scene);
+            for (var _i = 0, props_1 = props; _i < props_1.length; _i++) {
+                var prop = props_1[_i];
+                details.push(prop);
             }
             _this._detailsPanel.details = details;
             Split([_this._actions, _this._detailsPanel.toHtml()], {
@@ -4702,6 +4529,13 @@ var INSPECTOR;
         /** Build the HTML of this item */
         TreeItem.prototype._build = function () {
             this._div.className = 'line';
+            // special class for transform node ONLY
+            if (this.adapter instanceof INSPECTOR.MeshAdapter) {
+                var obj = this.adapter.object;
+                if (obj instanceof BABYLON.TransformNode && !(obj instanceof BABYLON.AbstractMesh)) {
+                    this._div.className += ' transformNode';
+                }
+            }
             for (var _i = 0, _a = this._tools; _i < _a.length; _i++) {
                 var tool = _a[_i];
                 this._div.appendChild(tool.toHtml());

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 4 - 4
dist/preview release/inspector/babylon.inspector.min.js


+ 1 - 1
dist/preview release/inspector/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-inspector",
     "description": "The Babylon.js inspector.",
-    "version": "3.1.0-beta1.1.1",
+    "version": "3.1.0-beta3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 4 - 4
dist/preview release/loaders/babylon.glTF1FileLoader.d.ts

@@ -20,13 +20,13 @@ declare module BABYLON {
         static HomogeneousCoordinates: boolean;
         static IncrementalLoading: boolean;
         coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
+        compileMaterials: boolean;
+        compileShadowGenerators: boolean;
+        useClipPlane: boolean;
+        onMeshLoaded: (mesh: AbstractMesh) => void;
         onTextureLoaded: (texture: BaseTexture) => void;
         onMaterialLoaded: (material: Material) => void;
         /**
-         * Let the user decides if he needs to process the material (like precompilation) before affecting it to meshes
-         */
-        onBeforeMaterialReadyAsync: (material: Material, targetMesh: AbstractMesh, isLOD: boolean, callback: () => void) => void;
-        /**
          * Raised when the asset is completely loaded, just before the loader is disposed.
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete just after onSuccess.

+ 3 - 0
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -15,6 +15,9 @@ var BABYLON;
         function GLTFFileLoader() {
             // V2 options
             this.coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
+            this.compileMaterials = false;
+            this.compileShadowGenerators = false;
+            this.useClipPlane = false;
             this.name = "gltf";
             this.extensions = {
                 ".gltf": { isBinary: false },

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 11 - 8
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -20,13 +20,13 @@ declare module BABYLON {
         static HomogeneousCoordinates: boolean;
         static IncrementalLoading: boolean;
         coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
+        compileMaterials: boolean;
+        compileShadowGenerators: boolean;
+        useClipPlane: boolean;
+        onMeshLoaded: (mesh: AbstractMesh) => void;
         onTextureLoaded: (texture: BaseTexture) => void;
         onMaterialLoaded: (material: Material) => void;
         /**
-         * Let the user decides if he needs to process the material (like precompilation) before affecting it to meshes
-         */
-        onBeforeMaterialReadyAsync: (material: Material, targetMesh: AbstractMesh, isLOD: boolean, callback: () => void) => void;
-        /**
          * Raised when the asset is completely loaded, just before the loader is disposed.
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete just after onSuccess.
@@ -329,7 +329,7 @@ declare module BABYLON.GLTF2 {
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         private _loadAsync(nodeNames, scene, data, rootUrl, onSuccess, onProgress, onError);
-        private _onProgress(event);
+        private _onProgress();
         _executeWhenRenderReady(func: () => void): void;
         private _onRenderReady();
         private _onComplete();
@@ -387,14 +387,17 @@ declare module BABYLON.GLTF2 {
         _loadMaterialBaseProperties(context: string, material: IGLTFMaterial): void;
         _loadMaterialAlphaProperties(context: string, material: IGLTFMaterial, colorFactor: number[]): void;
         _loadTexture(context: string, texture: IGLTFTexture, coordinatesIndex?: number): Texture;
-        private _loadImage(context, image, onSuccess);
-        _loadUri(context: string, uri: string, onSuccess: (data: ArrayBufferView) => void): void;
+        private _loadImageAsync(context, image, onSuccess);
+        _loadUriAsync(context: string, uri: string, onSuccess: (data: ArrayBufferView) => void): void;
         _tryCatchOnError(handler: () => void): void;
         private static _AssignIndices(array?);
         static _GetProperty<T extends IGLTFProperty>(array?: ArrayLike<T>, index?: number): Nullable<T>;
         private static _GetTextureWrapMode(mode?);
         private static _GetTextureSamplingMode(magFilter?, minFilter?);
         private static _GetNumComponents(type);
+        private _compileMaterialAsync(babylonMaterial, babylonMesh, onSuccess);
+        private _compileMaterialsAsync(onSuccess);
+        private _compileShadowGeneratorsAsync(onSuccess);
     }
 }
 
@@ -441,7 +444,7 @@ declare module BABYLON.GLTF2.Extensions {
         /**
          * Specify the minimal delay between LODs in ms (default = 250)
          */
-        static MinimalLODDelay: number;
+        Delay: number;
         readonly name: string;
         protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean;
         protected _loadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean;

+ 179 - 66
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -15,6 +15,9 @@ var BABYLON;
         function GLTFFileLoader() {
             // V2 options
             this.coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
+            this.compileMaterials = false;
+            this.compileShadowGenerators = false;
+            this.useClipPlane = false;
             this.name = "gltf";
             this.extensions = {
                 ".gltf": { isBinary: false },
@@ -386,10 +389,25 @@ var BABYLON;
                     _this._removePendingData(_this);
                 });
             };
-            GLTFLoader.prototype._onProgress = function (event) {
-                if (this._progressCallback) {
-                    this._progressCallback(event);
+            GLTFLoader.prototype._onProgress = function () {
+                if (!this._progressCallback) {
+                    return;
+                }
+                var loaded = 0;
+                var total = 0;
+                for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
+                    var request = _a[_i];
+                    if (!request._loaded || !request._total) {
+                        return;
+                    }
+                    loaded += request._loaded;
+                    total += request._total;
                 }
+                this._progressCallback(new ProgressEvent("GLTFLoaderProgress", {
+                    lengthComputable: true,
+                    loaded: loaded,
+                    total: total
+                }));
             };
             GLTFLoader.prototype._executeWhenRenderReady = function (func) {
                 if (this._renderReady) {
@@ -514,6 +532,9 @@ var BABYLON;
                         return;
                     }
                 }
+                if (this._parent.onMeshLoaded) {
+                    this._parent.onMeshLoaded(this._rootNode.babylonMesh);
+                }
                 var nodeIndices = scene.nodes;
                 this._traverseNodes(context, nodeIndices, function (node, parentNode) {
                     node.parent = parentNode;
@@ -581,6 +602,9 @@ var BABYLON;
                         this._loadNode("#/nodes/" + index, childNode);
                     }
                 }
+                if (this._parent.onMeshLoaded) {
+                    this._parent.onMeshLoaded(node.babylonMesh);
+                }
             };
             GLTFLoader.prototype._loadMesh = function (context, node, mesh) {
                 var _this = this;
@@ -621,26 +645,15 @@ var BABYLON;
                         subMaterials[index] = this_1._getDefaultMaterial();
                     }
                     else {
-                        var material_1 = GLTFLoader._GetProperty(this_1._gltf.materials, primitive.material);
-                        if (!material_1) {
+                        var material = GLTFLoader._GetProperty(this_1._gltf.materials, primitive.material);
+                        if (!material) {
                             throw new Error(context + ": Failed to find material " + primitive.material);
                         }
-                        this_1._loadMaterial("#/materials/" + material_1.index, material_1, function (babylonMaterial, isNew) {
+                        this_1._loadMaterial("#/materials/" + material.index, material, function (babylonMaterial, isNew) {
                             if (isNew && _this._parent.onMaterialLoaded) {
                                 _this._parent.onMaterialLoaded(babylonMaterial);
                             }
-                            if (_this._parent.onBeforeMaterialReadyAsync) {
-                                _this._addLoaderPendingData(material_1);
-                                _this._parent.onBeforeMaterialReadyAsync(babylonMaterial, node.babylonMesh, subMaterials[index] != null, function () {
-                                    _this._tryCatchOnError(function () {
-                                        subMaterials[index] = babylonMaterial;
-                                        _this._removeLoaderPendingData(material_1);
-                                    });
-                                });
-                            }
-                            else {
-                                subMaterials[index] = babylonMaterial;
-                            }
+                            subMaterials[index] = babylonMaterial;
                         });
                     }
                 };
@@ -1247,24 +1260,16 @@ var BABYLON;
                     if (!buffer.uri) {
                         throw new Error(context + ": Uri is missing");
                     }
-                    if (GLTF2.GLTFUtils.IsBase64(buffer.uri)) {
-                        var data = GLTF2.GLTFUtils.DecodeBase64(buffer.uri);
-                        buffer.loadedData = new Uint8Array(data);
+                    buffer.loadedObservable = new BABYLON.Observable();
+                    buffer.loadedObservable.add(function (buffer) {
                         onSuccess(buffer.loadedData);
-                        this._removePendingData(buffer);
-                    }
-                    else {
-                        buffer.loadedObservable = new BABYLON.Observable();
-                        buffer.loadedObservable.add(function (buffer) {
-                            onSuccess(buffer.loadedData);
-                            _this._removePendingData(buffer);
-                        });
-                        this._loadUri(context, buffer.uri, function (data) {
-                            buffer.loadedData = data;
-                            buffer.loadedObservable.notifyObservers(buffer);
-                            buffer.loadedObservable = undefined;
-                        });
-                    }
+                        _this._removePendingData(buffer);
+                    });
+                    this._loadUriAsync(context, buffer.uri, function (data) {
+                        buffer.loadedData = data;
+                        buffer.loadedObservable.notifyObservers(buffer);
+                        buffer.loadedObservable = undefined;
+                    });
                 }
             };
             GLTFLoader.prototype._loadBufferViewAsync = function (context, bufferView, onSuccess) {
@@ -1364,10 +1369,17 @@ var BABYLON;
                 this._addLoaderPendingData(data);
             };
             GLTFLoader.prototype._removePendingData = function (data) {
+                var _this = this;
                 if (!this._renderReady) {
                     if (--this._renderPendingCount === 0) {
-                        this._renderReady = true;
-                        this._onRenderReady();
+                        this._addLoaderPendingData(this);
+                        this._compileMaterialsAsync(function () {
+                            _this._compileShadowGeneratorsAsync(function () {
+                                _this._removeLoaderPendingData(_this);
+                                _this._renderReady = true;
+                                _this._onRenderReady();
+                            });
+                        });
                     }
                 }
                 this._removeLoaderPendingData(data);
@@ -1575,7 +1587,7 @@ var BABYLON;
                     if (!image_1) {
                         throw new Error(context + ": Failed to find source " + texture.source);
                     }
-                    this._loadImage("#/images/" + image_1.index, image_1, function (data) {
+                    this._loadImageAsync("#/images/" + image_1.index, image_1, function (data) {
                         texture.url = URL.createObjectURL(new Blob([data], { type: image_1.mimeType }));
                         texture.dataReadyObservable.notifyObservers(texture);
                         texture.dataReadyObservable = undefined;
@@ -1590,14 +1602,9 @@ var BABYLON;
                 }
                 return babylonTexture;
             };
-            GLTFLoader.prototype._loadImage = function (context, image, onSuccess) {
+            GLTFLoader.prototype._loadImageAsync = function (context, image, onSuccess) {
                 if (image.uri) {
-                    if (GLTF2.GLTFUtils.IsBase64(image.uri)) {
-                        onSuccess(new Uint8Array(GLTF2.GLTFUtils.DecodeBase64(image.uri)));
-                    }
-                    else {
-                        this._loadUri(context, image.uri, onSuccess);
-                    }
+                    this._loadUriAsync(context, image.uri, onSuccess);
                 }
                 else {
                     var bufferView = GLTFLoader._GetProperty(this._gltf.bufferViews, image.bufferView);
@@ -1607,8 +1614,12 @@ var BABYLON;
                     this._loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView, onSuccess);
                 }
             };
-            GLTFLoader.prototype._loadUri = function (context, uri, onSuccess) {
+            GLTFLoader.prototype._loadUriAsync = function (context, uri, onSuccess) {
                 var _this = this;
+                if (GLTF2.GLTFUtils.IsBase64(uri)) {
+                    onSuccess(new Uint8Array(GLTF2.GLTFUtils.DecodeBase64(uri)));
+                    return;
+                }
                 if (!GLTF2.GLTFUtils.ValidateUri(uri)) {
                     throw new Error(context + ": Uri '" + uri + "' is invalid");
                 }
@@ -1618,7 +1629,11 @@ var BABYLON;
                     });
                 }, function (event) {
                     _this._tryCatchOnError(function () {
-                        _this._onProgress(event);
+                        if (request && !_this._renderReady) {
+                            request._loaded = event.loaded;
+                            request._total = event.total;
+                            _this._onProgress();
+                        }
                     });
                 }, this._babylonScene.database, true, function (request) {
                     _this._tryCatchOnError(function () {
@@ -1626,6 +1641,8 @@ var BABYLON;
                     });
                 });
                 if (request) {
+                    request._loaded = null;
+                    request._total = null;
                     this._requests.push(request);
                 }
             };
@@ -1715,6 +1732,94 @@ var BABYLON;
                 }
                 return 0;
             };
+            GLTFLoader.prototype._compileMaterialAsync = function (babylonMaterial, babylonMesh, onSuccess) {
+                var _this = this;
+                if (!this._parent.compileMaterials) {
+                    onSuccess();
+                    return;
+                }
+                if (this._parent.useClipPlane) {
+                    babylonMaterial.forceCompilation(babylonMesh, function () {
+                        babylonMaterial.forceCompilation(babylonMesh, function () {
+                            _this._tryCatchOnError(onSuccess);
+                        }, { clipPlane: true });
+                    });
+                }
+                else {
+                    babylonMaterial.forceCompilation(babylonMesh, function () {
+                        _this._tryCatchOnError(onSuccess);
+                    });
+                }
+            };
+            GLTFLoader.prototype._compileMaterialsAsync = function (onSuccess) {
+                if (!this._parent.compileMaterials || !this._gltf.materials) {
+                    onSuccess();
+                    return;
+                }
+                var meshes = this._getMeshes();
+                var remaining = 0;
+                for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                    var mesh = meshes_1[_i];
+                    if (mesh.material instanceof BABYLON.MultiMaterial) {
+                        for (var _a = 0, _b = mesh.material.subMaterials; _a < _b.length; _a++) {
+                            var subMaterial = _b[_a];
+                            if (subMaterial) {
+                                remaining++;
+                            }
+                        }
+                    }
+                }
+                if (remaining === 0) {
+                    onSuccess();
+                    return;
+                }
+                for (var _c = 0, meshes_2 = meshes; _c < meshes_2.length; _c++) {
+                    var mesh = meshes_2[_c];
+                    if (mesh.material instanceof BABYLON.MultiMaterial) {
+                        for (var _d = 0, _e = mesh.material.subMaterials; _d < _e.length; _d++) {
+                            var subMaterial = _e[_d];
+                            if (subMaterial) {
+                                this._compileMaterialAsync(subMaterial, mesh, function () {
+                                    if (--remaining === 0) {
+                                        onSuccess();
+                                    }
+                                });
+                            }
+                        }
+                    }
+                }
+            };
+            GLTFLoader.prototype._compileShadowGeneratorsAsync = function (onSuccess) {
+                var _this = this;
+                if (!this._parent.compileShadowGenerators) {
+                    onSuccess();
+                    return;
+                }
+                var lights = this._babylonScene.lights;
+                var remaining = 0;
+                for (var _i = 0, lights_1 = lights; _i < lights_1.length; _i++) {
+                    var light = lights_1[_i];
+                    var generator = light.getShadowGenerator();
+                    if (generator) {
+                        remaining++;
+                    }
+                }
+                if (remaining === 0) {
+                    onSuccess();
+                    return;
+                }
+                for (var _a = 0, lights_2 = lights; _a < lights_2.length; _a++) {
+                    var light = lights_2[_a];
+                    var generator = light.getShadowGenerator();
+                    if (generator) {
+                        generator.forceCompilation(function () {
+                            if (--remaining === 0) {
+                                _this._tryCatchOnError(onSuccess);
+                            }
+                        });
+                    }
+                }
+            };
             GLTFLoader.Extensions = {};
             return GLTFLoader;
         }());
@@ -1851,7 +1956,12 @@ var BABYLON;
             var MSFTLOD = /** @class */ (function (_super) {
                 __extends(MSFTLOD, _super);
                 function MSFTLOD() {
-                    return _super !== null && _super.apply(this, arguments) || this;
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
+                    /**
+                     * Specify the minimal delay between LODs in ms (default = 250)
+                     */
+                    _this.Delay = 250;
+                    return _this;
                 }
                 Object.defineProperty(MSFTLOD.prototype, "name", {
                     get: function () {
@@ -1909,7 +2019,7 @@ var BABYLON;
                             loader._tryCatchOnError(function () {
                                 _this._loadNodeLOD(loader, context, nodes, index - 1, onComplete);
                             });
-                        }, MSFTLOD.MinimalLODDelay);
+                        }, _this.Delay);
                     });
                 };
                 MSFTLOD.prototype._loadMaterial = function (loader, context, material, assign) {
@@ -1934,28 +2044,30 @@ var BABYLON;
                 MSFTLOD.prototype._loadMaterialLOD = function (loader, context, materials, index, assign, onComplete) {
                     var _this = this;
                     loader._loadMaterial(context, materials[index], function (babylonMaterial, isNew) {
-                        assign(babylonMaterial, isNew);
-                        if (index === 0) {
-                            onComplete();
-                            return;
+                        if (index === materials.length - 1) {
+                            assign(babylonMaterial, isNew);
+                            // Load the next LOD when the loader is ready to render.
+                            loader._executeWhenRenderReady(function () {
+                                _this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
+                            });
                         }
-                        // Load the next LOD when the loader is ready to render and
-                        // all active material textures of the current LOD are loaded.
-                        loader._executeWhenRenderReady(function () {
+                        else {
                             BABYLON.BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), function () {
-                                setTimeout(function () {
-                                    loader._tryCatchOnError(function () {
-                                        _this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
-                                    });
-                                }, MSFTLOD.MinimalLODDelay);
+                                assign(babylonMaterial, isNew);
+                                if (index === 0) {
+                                    onComplete();
+                                }
+                                else {
+                                    setTimeout(function () {
+                                        loader._tryCatchOnError(function () {
+                                            _this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
+                                        });
+                                    }, _this.Delay);
+                                }
                             });
-                        });
+                        }
                     });
                 };
-                /**
-                 * Specify the minimal delay between LODs in ms (default = 250)
-                 */
-                MSFTLOD.MinimalLODDelay = 250;
                 return MSFTLOD;
             }(GLTF2.GLTFLoaderExtension));
             Extensions.MSFTLOD = MSFTLOD;
@@ -2002,6 +2114,7 @@ var BABYLON;
                         loader._loadMaterialBaseProperties(context, material);
                         _this._loadSpecularGlossinessProperties(loader, context, material, extension);
                         assign(material.babylonMaterial, true);
+                        onComplete();
                     });
                 };
                 KHRMaterialsPbrSpecularGlossiness.prototype._loadSpecularGlossinessProperties = function (loader, context, material, properties) {

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 11 - 8
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -20,13 +20,13 @@ declare module BABYLON {
         static HomogeneousCoordinates: boolean;
         static IncrementalLoading: boolean;
         coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
+        compileMaterials: boolean;
+        compileShadowGenerators: boolean;
+        useClipPlane: boolean;
+        onMeshLoaded: (mesh: AbstractMesh) => void;
         onTextureLoaded: (texture: BaseTexture) => void;
         onMaterialLoaded: (material: Material) => void;
         /**
-         * Let the user decides if he needs to process the material (like precompilation) before affecting it to meshes
-         */
-        onBeforeMaterialReadyAsync: (material: Material, targetMesh: AbstractMesh, isLOD: boolean, callback: () => void) => void;
-        /**
          * Raised when the asset is completely loaded, just before the loader is disposed.
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete just after onSuccess.
@@ -876,7 +876,7 @@ declare module BABYLON.GLTF2 {
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         private _loadAsync(nodeNames, scene, data, rootUrl, onSuccess, onProgress, onError);
-        private _onProgress(event);
+        private _onProgress();
         _executeWhenRenderReady(func: () => void): void;
         private _onRenderReady();
         private _onComplete();
@@ -934,14 +934,17 @@ declare module BABYLON.GLTF2 {
         _loadMaterialBaseProperties(context: string, material: IGLTFMaterial): void;
         _loadMaterialAlphaProperties(context: string, material: IGLTFMaterial, colorFactor: number[]): void;
         _loadTexture(context: string, texture: IGLTFTexture, coordinatesIndex?: number): Texture;
-        private _loadImage(context, image, onSuccess);
-        _loadUri(context: string, uri: string, onSuccess: (data: ArrayBufferView) => void): void;
+        private _loadImageAsync(context, image, onSuccess);
+        _loadUriAsync(context: string, uri: string, onSuccess: (data: ArrayBufferView) => void): void;
         _tryCatchOnError(handler: () => void): void;
         private static _AssignIndices(array?);
         static _GetProperty<T extends IGLTFProperty>(array?: ArrayLike<T>, index?: number): Nullable<T>;
         private static _GetTextureWrapMode(mode?);
         private static _GetTextureSamplingMode(magFilter?, minFilter?);
         private static _GetNumComponents(type);
+        private _compileMaterialAsync(babylonMaterial, babylonMesh, onSuccess);
+        private _compileMaterialsAsync(onSuccess);
+        private _compileShadowGeneratorsAsync(onSuccess);
     }
 }
 
@@ -988,7 +991,7 @@ declare module BABYLON.GLTF2.Extensions {
         /**
          * Specify the minimal delay between LODs in ms (default = 250)
          */
-        static MinimalLODDelay: number;
+        Delay: number;
         readonly name: string;
         protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean;
         protected _loadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean;

+ 179 - 66
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -15,6 +15,9 @@ var BABYLON;
         function GLTFFileLoader() {
             // V2 options
             this.coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
+            this.compileMaterials = false;
+            this.compileShadowGenerators = false;
+            this.useClipPlane = false;
             this.name = "gltf";
             this.extensions = {
                 ".gltf": { isBinary: false },
@@ -2531,10 +2534,25 @@ var BABYLON;
                     _this._removePendingData(_this);
                 });
             };
-            GLTFLoader.prototype._onProgress = function (event) {
-                if (this._progressCallback) {
-                    this._progressCallback(event);
+            GLTFLoader.prototype._onProgress = function () {
+                if (!this._progressCallback) {
+                    return;
+                }
+                var loaded = 0;
+                var total = 0;
+                for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
+                    var request = _a[_i];
+                    if (!request._loaded || !request._total) {
+                        return;
+                    }
+                    loaded += request._loaded;
+                    total += request._total;
                 }
+                this._progressCallback(new ProgressEvent("GLTFLoaderProgress", {
+                    lengthComputable: true,
+                    loaded: loaded,
+                    total: total
+                }));
             };
             GLTFLoader.prototype._executeWhenRenderReady = function (func) {
                 if (this._renderReady) {
@@ -2659,6 +2677,9 @@ var BABYLON;
                         return;
                     }
                 }
+                if (this._parent.onMeshLoaded) {
+                    this._parent.onMeshLoaded(this._rootNode.babylonMesh);
+                }
                 var nodeIndices = scene.nodes;
                 this._traverseNodes(context, nodeIndices, function (node, parentNode) {
                     node.parent = parentNode;
@@ -2726,6 +2747,9 @@ var BABYLON;
                         this._loadNode("#/nodes/" + index, childNode);
                     }
                 }
+                if (this._parent.onMeshLoaded) {
+                    this._parent.onMeshLoaded(node.babylonMesh);
+                }
             };
             GLTFLoader.prototype._loadMesh = function (context, node, mesh) {
                 var _this = this;
@@ -2766,26 +2790,15 @@ var BABYLON;
                         subMaterials[index] = this_1._getDefaultMaterial();
                     }
                     else {
-                        var material_1 = GLTFLoader._GetProperty(this_1._gltf.materials, primitive.material);
-                        if (!material_1) {
+                        var material = GLTFLoader._GetProperty(this_1._gltf.materials, primitive.material);
+                        if (!material) {
                             throw new Error(context + ": Failed to find material " + primitive.material);
                         }
-                        this_1._loadMaterial("#/materials/" + material_1.index, material_1, function (babylonMaterial, isNew) {
+                        this_1._loadMaterial("#/materials/" + material.index, material, function (babylonMaterial, isNew) {
                             if (isNew && _this._parent.onMaterialLoaded) {
                                 _this._parent.onMaterialLoaded(babylonMaterial);
                             }
-                            if (_this._parent.onBeforeMaterialReadyAsync) {
-                                _this._addLoaderPendingData(material_1);
-                                _this._parent.onBeforeMaterialReadyAsync(babylonMaterial, node.babylonMesh, subMaterials[index] != null, function () {
-                                    _this._tryCatchOnError(function () {
-                                        subMaterials[index] = babylonMaterial;
-                                        _this._removeLoaderPendingData(material_1);
-                                    });
-                                });
-                            }
-                            else {
-                                subMaterials[index] = babylonMaterial;
-                            }
+                            subMaterials[index] = babylonMaterial;
                         });
                     }
                 };
@@ -3392,24 +3405,16 @@ var BABYLON;
                     if (!buffer.uri) {
                         throw new Error(context + ": Uri is missing");
                     }
-                    if (GLTF2.GLTFUtils.IsBase64(buffer.uri)) {
-                        var data = GLTF2.GLTFUtils.DecodeBase64(buffer.uri);
-                        buffer.loadedData = new Uint8Array(data);
+                    buffer.loadedObservable = new BABYLON.Observable();
+                    buffer.loadedObservable.add(function (buffer) {
                         onSuccess(buffer.loadedData);
-                        this._removePendingData(buffer);
-                    }
-                    else {
-                        buffer.loadedObservable = new BABYLON.Observable();
-                        buffer.loadedObservable.add(function (buffer) {
-                            onSuccess(buffer.loadedData);
-                            _this._removePendingData(buffer);
-                        });
-                        this._loadUri(context, buffer.uri, function (data) {
-                            buffer.loadedData = data;
-                            buffer.loadedObservable.notifyObservers(buffer);
-                            buffer.loadedObservable = undefined;
-                        });
-                    }
+                        _this._removePendingData(buffer);
+                    });
+                    this._loadUriAsync(context, buffer.uri, function (data) {
+                        buffer.loadedData = data;
+                        buffer.loadedObservable.notifyObservers(buffer);
+                        buffer.loadedObservable = undefined;
+                    });
                 }
             };
             GLTFLoader.prototype._loadBufferViewAsync = function (context, bufferView, onSuccess) {
@@ -3509,10 +3514,17 @@ var BABYLON;
                 this._addLoaderPendingData(data);
             };
             GLTFLoader.prototype._removePendingData = function (data) {
+                var _this = this;
                 if (!this._renderReady) {
                     if (--this._renderPendingCount === 0) {
-                        this._renderReady = true;
-                        this._onRenderReady();
+                        this._addLoaderPendingData(this);
+                        this._compileMaterialsAsync(function () {
+                            _this._compileShadowGeneratorsAsync(function () {
+                                _this._removeLoaderPendingData(_this);
+                                _this._renderReady = true;
+                                _this._onRenderReady();
+                            });
+                        });
                     }
                 }
                 this._removeLoaderPendingData(data);
@@ -3720,7 +3732,7 @@ var BABYLON;
                     if (!image_1) {
                         throw new Error(context + ": Failed to find source " + texture.source);
                     }
-                    this._loadImage("#/images/" + image_1.index, image_1, function (data) {
+                    this._loadImageAsync("#/images/" + image_1.index, image_1, function (data) {
                         texture.url = URL.createObjectURL(new Blob([data], { type: image_1.mimeType }));
                         texture.dataReadyObservable.notifyObservers(texture);
                         texture.dataReadyObservable = undefined;
@@ -3735,14 +3747,9 @@ var BABYLON;
                 }
                 return babylonTexture;
             };
-            GLTFLoader.prototype._loadImage = function (context, image, onSuccess) {
+            GLTFLoader.prototype._loadImageAsync = function (context, image, onSuccess) {
                 if (image.uri) {
-                    if (GLTF2.GLTFUtils.IsBase64(image.uri)) {
-                        onSuccess(new Uint8Array(GLTF2.GLTFUtils.DecodeBase64(image.uri)));
-                    }
-                    else {
-                        this._loadUri(context, image.uri, onSuccess);
-                    }
+                    this._loadUriAsync(context, image.uri, onSuccess);
                 }
                 else {
                     var bufferView = GLTFLoader._GetProperty(this._gltf.bufferViews, image.bufferView);
@@ -3752,8 +3759,12 @@ var BABYLON;
                     this._loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView, onSuccess);
                 }
             };
-            GLTFLoader.prototype._loadUri = function (context, uri, onSuccess) {
+            GLTFLoader.prototype._loadUriAsync = function (context, uri, onSuccess) {
                 var _this = this;
+                if (GLTF2.GLTFUtils.IsBase64(uri)) {
+                    onSuccess(new Uint8Array(GLTF2.GLTFUtils.DecodeBase64(uri)));
+                    return;
+                }
                 if (!GLTF2.GLTFUtils.ValidateUri(uri)) {
                     throw new Error(context + ": Uri '" + uri + "' is invalid");
                 }
@@ -3763,7 +3774,11 @@ var BABYLON;
                     });
                 }, function (event) {
                     _this._tryCatchOnError(function () {
-                        _this._onProgress(event);
+                        if (request && !_this._renderReady) {
+                            request._loaded = event.loaded;
+                            request._total = event.total;
+                            _this._onProgress();
+                        }
                     });
                 }, this._babylonScene.database, true, function (request) {
                     _this._tryCatchOnError(function () {
@@ -3771,6 +3786,8 @@ var BABYLON;
                     });
                 });
                 if (request) {
+                    request._loaded = null;
+                    request._total = null;
                     this._requests.push(request);
                 }
             };
@@ -3860,6 +3877,94 @@ var BABYLON;
                 }
                 return 0;
             };
+            GLTFLoader.prototype._compileMaterialAsync = function (babylonMaterial, babylonMesh, onSuccess) {
+                var _this = this;
+                if (!this._parent.compileMaterials) {
+                    onSuccess();
+                    return;
+                }
+                if (this._parent.useClipPlane) {
+                    babylonMaterial.forceCompilation(babylonMesh, function () {
+                        babylonMaterial.forceCompilation(babylonMesh, function () {
+                            _this._tryCatchOnError(onSuccess);
+                        }, { clipPlane: true });
+                    });
+                }
+                else {
+                    babylonMaterial.forceCompilation(babylonMesh, function () {
+                        _this._tryCatchOnError(onSuccess);
+                    });
+                }
+            };
+            GLTFLoader.prototype._compileMaterialsAsync = function (onSuccess) {
+                if (!this._parent.compileMaterials || !this._gltf.materials) {
+                    onSuccess();
+                    return;
+                }
+                var meshes = this._getMeshes();
+                var remaining = 0;
+                for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                    var mesh = meshes_1[_i];
+                    if (mesh.material instanceof BABYLON.MultiMaterial) {
+                        for (var _a = 0, _b = mesh.material.subMaterials; _a < _b.length; _a++) {
+                            var subMaterial = _b[_a];
+                            if (subMaterial) {
+                                remaining++;
+                            }
+                        }
+                    }
+                }
+                if (remaining === 0) {
+                    onSuccess();
+                    return;
+                }
+                for (var _c = 0, meshes_2 = meshes; _c < meshes_2.length; _c++) {
+                    var mesh = meshes_2[_c];
+                    if (mesh.material instanceof BABYLON.MultiMaterial) {
+                        for (var _d = 0, _e = mesh.material.subMaterials; _d < _e.length; _d++) {
+                            var subMaterial = _e[_d];
+                            if (subMaterial) {
+                                this._compileMaterialAsync(subMaterial, mesh, function () {
+                                    if (--remaining === 0) {
+                                        onSuccess();
+                                    }
+                                });
+                            }
+                        }
+                    }
+                }
+            };
+            GLTFLoader.prototype._compileShadowGeneratorsAsync = function (onSuccess) {
+                var _this = this;
+                if (!this._parent.compileShadowGenerators) {
+                    onSuccess();
+                    return;
+                }
+                var lights = this._babylonScene.lights;
+                var remaining = 0;
+                for (var _i = 0, lights_1 = lights; _i < lights_1.length; _i++) {
+                    var light = lights_1[_i];
+                    var generator = light.getShadowGenerator();
+                    if (generator) {
+                        remaining++;
+                    }
+                }
+                if (remaining === 0) {
+                    onSuccess();
+                    return;
+                }
+                for (var _a = 0, lights_2 = lights; _a < lights_2.length; _a++) {
+                    var light = lights_2[_a];
+                    var generator = light.getShadowGenerator();
+                    if (generator) {
+                        generator.forceCompilation(function () {
+                            if (--remaining === 0) {
+                                _this._tryCatchOnError(onSuccess);
+                            }
+                        });
+                    }
+                }
+            };
             GLTFLoader.Extensions = {};
             return GLTFLoader;
         }());
@@ -3996,7 +4101,12 @@ var BABYLON;
             var MSFTLOD = /** @class */ (function (_super) {
                 __extends(MSFTLOD, _super);
                 function MSFTLOD() {
-                    return _super !== null && _super.apply(this, arguments) || this;
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
+                    /**
+                     * Specify the minimal delay between LODs in ms (default = 250)
+                     */
+                    _this.Delay = 250;
+                    return _this;
                 }
                 Object.defineProperty(MSFTLOD.prototype, "name", {
                     get: function () {
@@ -4054,7 +4164,7 @@ var BABYLON;
                             loader._tryCatchOnError(function () {
                                 _this._loadNodeLOD(loader, context, nodes, index - 1, onComplete);
                             });
-                        }, MSFTLOD.MinimalLODDelay);
+                        }, _this.Delay);
                     });
                 };
                 MSFTLOD.prototype._loadMaterial = function (loader, context, material, assign) {
@@ -4079,28 +4189,30 @@ var BABYLON;
                 MSFTLOD.prototype._loadMaterialLOD = function (loader, context, materials, index, assign, onComplete) {
                     var _this = this;
                     loader._loadMaterial(context, materials[index], function (babylonMaterial, isNew) {
-                        assign(babylonMaterial, isNew);
-                        if (index === 0) {
-                            onComplete();
-                            return;
+                        if (index === materials.length - 1) {
+                            assign(babylonMaterial, isNew);
+                            // Load the next LOD when the loader is ready to render.
+                            loader._executeWhenRenderReady(function () {
+                                _this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
+                            });
                         }
-                        // Load the next LOD when the loader is ready to render and
-                        // all active material textures of the current LOD are loaded.
-                        loader._executeWhenRenderReady(function () {
+                        else {
                             BABYLON.BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), function () {
-                                setTimeout(function () {
-                                    loader._tryCatchOnError(function () {
-                                        _this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
-                                    });
-                                }, MSFTLOD.MinimalLODDelay);
+                                assign(babylonMaterial, isNew);
+                                if (index === 0) {
+                                    onComplete();
+                                }
+                                else {
+                                    setTimeout(function () {
+                                        loader._tryCatchOnError(function () {
+                                            _this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
+                                        });
+                                    }, _this.Delay);
+                                }
                             });
-                        });
+                        }
                     });
                 };
-                /**
-                 * Specify the minimal delay between LODs in ms (default = 250)
-                 */
-                MSFTLOD.MinimalLODDelay = 250;
                 return MSFTLOD;
             }(GLTF2.GLTFLoaderExtension));
             Extensions.MSFTLOD = MSFTLOD;
@@ -4147,6 +4259,7 @@ var BABYLON;
                         loader._loadMaterialBaseProperties(context, material);
                         _this._loadSpecularGlossinessProperties(loader, context, material, extension);
                         assign(material.babylonMaterial, true);
+                        onComplete();
                     });
                 };
                 KHRMaterialsPbrSpecularGlossiness.prototype._loadSpecularGlossinessProperties = function (loader, context, material, properties) {

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 179 - 66
dist/preview release/loaders/babylonjs.loaders.js

@@ -989,6 +989,9 @@ var BABYLON;
         function GLTFFileLoader() {
             // V2 options
             this.coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
+            this.compileMaterials = false;
+            this.compileShadowGenerators = false;
+            this.useClipPlane = false;
             this.name = "gltf";
             this.extensions = {
                 ".gltf": { isBinary: false },
@@ -3487,10 +3490,25 @@ var BABYLON;
                     _this._removePendingData(_this);
                 });
             };
-            GLTFLoader.prototype._onProgress = function (event) {
-                if (this._progressCallback) {
-                    this._progressCallback(event);
+            GLTFLoader.prototype._onProgress = function () {
+                if (!this._progressCallback) {
+                    return;
+                }
+                var loaded = 0;
+                var total = 0;
+                for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
+                    var request = _a[_i];
+                    if (!request._loaded || !request._total) {
+                        return;
+                    }
+                    loaded += request._loaded;
+                    total += request._total;
                 }
+                this._progressCallback(new ProgressEvent("GLTFLoaderProgress", {
+                    lengthComputable: true,
+                    loaded: loaded,
+                    total: total
+                }));
             };
             GLTFLoader.prototype._executeWhenRenderReady = function (func) {
                 if (this._renderReady) {
@@ -3615,6 +3633,9 @@ var BABYLON;
                         return;
                     }
                 }
+                if (this._parent.onMeshLoaded) {
+                    this._parent.onMeshLoaded(this._rootNode.babylonMesh);
+                }
                 var nodeIndices = scene.nodes;
                 this._traverseNodes(context, nodeIndices, function (node, parentNode) {
                     node.parent = parentNode;
@@ -3682,6 +3703,9 @@ var BABYLON;
                         this._loadNode("#/nodes/" + index, childNode);
                     }
                 }
+                if (this._parent.onMeshLoaded) {
+                    this._parent.onMeshLoaded(node.babylonMesh);
+                }
             };
             GLTFLoader.prototype._loadMesh = function (context, node, mesh) {
                 var _this = this;
@@ -3722,26 +3746,15 @@ var BABYLON;
                         subMaterials[index] = this_1._getDefaultMaterial();
                     }
                     else {
-                        var material_1 = GLTFLoader._GetProperty(this_1._gltf.materials, primitive.material);
-                        if (!material_1) {
+                        var material = GLTFLoader._GetProperty(this_1._gltf.materials, primitive.material);
+                        if (!material) {
                             throw new Error(context + ": Failed to find material " + primitive.material);
                         }
-                        this_1._loadMaterial("#/materials/" + material_1.index, material_1, function (babylonMaterial, isNew) {
+                        this_1._loadMaterial("#/materials/" + material.index, material, function (babylonMaterial, isNew) {
                             if (isNew && _this._parent.onMaterialLoaded) {
                                 _this._parent.onMaterialLoaded(babylonMaterial);
                             }
-                            if (_this._parent.onBeforeMaterialReadyAsync) {
-                                _this._addLoaderPendingData(material_1);
-                                _this._parent.onBeforeMaterialReadyAsync(babylonMaterial, node.babylonMesh, subMaterials[index] != null, function () {
-                                    _this._tryCatchOnError(function () {
-                                        subMaterials[index] = babylonMaterial;
-                                        _this._removeLoaderPendingData(material_1);
-                                    });
-                                });
-                            }
-                            else {
-                                subMaterials[index] = babylonMaterial;
-                            }
+                            subMaterials[index] = babylonMaterial;
                         });
                     }
                 };
@@ -4348,24 +4361,16 @@ var BABYLON;
                     if (!buffer.uri) {
                         throw new Error(context + ": Uri is missing");
                     }
-                    if (GLTF2.GLTFUtils.IsBase64(buffer.uri)) {
-                        var data = GLTF2.GLTFUtils.DecodeBase64(buffer.uri);
-                        buffer.loadedData = new Uint8Array(data);
+                    buffer.loadedObservable = new BABYLON.Observable();
+                    buffer.loadedObservable.add(function (buffer) {
                         onSuccess(buffer.loadedData);
-                        this._removePendingData(buffer);
-                    }
-                    else {
-                        buffer.loadedObservable = new BABYLON.Observable();
-                        buffer.loadedObservable.add(function (buffer) {
-                            onSuccess(buffer.loadedData);
-                            _this._removePendingData(buffer);
-                        });
-                        this._loadUri(context, buffer.uri, function (data) {
-                            buffer.loadedData = data;
-                            buffer.loadedObservable.notifyObservers(buffer);
-                            buffer.loadedObservable = undefined;
-                        });
-                    }
+                        _this._removePendingData(buffer);
+                    });
+                    this._loadUriAsync(context, buffer.uri, function (data) {
+                        buffer.loadedData = data;
+                        buffer.loadedObservable.notifyObservers(buffer);
+                        buffer.loadedObservable = undefined;
+                    });
                 }
             };
             GLTFLoader.prototype._loadBufferViewAsync = function (context, bufferView, onSuccess) {
@@ -4465,10 +4470,17 @@ var BABYLON;
                 this._addLoaderPendingData(data);
             };
             GLTFLoader.prototype._removePendingData = function (data) {
+                var _this = this;
                 if (!this._renderReady) {
                     if (--this._renderPendingCount === 0) {
-                        this._renderReady = true;
-                        this._onRenderReady();
+                        this._addLoaderPendingData(this);
+                        this._compileMaterialsAsync(function () {
+                            _this._compileShadowGeneratorsAsync(function () {
+                                _this._removeLoaderPendingData(_this);
+                                _this._renderReady = true;
+                                _this._onRenderReady();
+                            });
+                        });
                     }
                 }
                 this._removeLoaderPendingData(data);
@@ -4676,7 +4688,7 @@ var BABYLON;
                     if (!image_1) {
                         throw new Error(context + ": Failed to find source " + texture.source);
                     }
-                    this._loadImage("#/images/" + image_1.index, image_1, function (data) {
+                    this._loadImageAsync("#/images/" + image_1.index, image_1, function (data) {
                         texture.url = URL.createObjectURL(new Blob([data], { type: image_1.mimeType }));
                         texture.dataReadyObservable.notifyObservers(texture);
                         texture.dataReadyObservable = undefined;
@@ -4691,14 +4703,9 @@ var BABYLON;
                 }
                 return babylonTexture;
             };
-            GLTFLoader.prototype._loadImage = function (context, image, onSuccess) {
+            GLTFLoader.prototype._loadImageAsync = function (context, image, onSuccess) {
                 if (image.uri) {
-                    if (GLTF2.GLTFUtils.IsBase64(image.uri)) {
-                        onSuccess(new Uint8Array(GLTF2.GLTFUtils.DecodeBase64(image.uri)));
-                    }
-                    else {
-                        this._loadUri(context, image.uri, onSuccess);
-                    }
+                    this._loadUriAsync(context, image.uri, onSuccess);
                 }
                 else {
                     var bufferView = GLTFLoader._GetProperty(this._gltf.bufferViews, image.bufferView);
@@ -4708,8 +4715,12 @@ var BABYLON;
                     this._loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView, onSuccess);
                 }
             };
-            GLTFLoader.prototype._loadUri = function (context, uri, onSuccess) {
+            GLTFLoader.prototype._loadUriAsync = function (context, uri, onSuccess) {
                 var _this = this;
+                if (GLTF2.GLTFUtils.IsBase64(uri)) {
+                    onSuccess(new Uint8Array(GLTF2.GLTFUtils.DecodeBase64(uri)));
+                    return;
+                }
                 if (!GLTF2.GLTFUtils.ValidateUri(uri)) {
                     throw new Error(context + ": Uri '" + uri + "' is invalid");
                 }
@@ -4719,7 +4730,11 @@ var BABYLON;
                     });
                 }, function (event) {
                     _this._tryCatchOnError(function () {
-                        _this._onProgress(event);
+                        if (request && !_this._renderReady) {
+                            request._loaded = event.loaded;
+                            request._total = event.total;
+                            _this._onProgress();
+                        }
                     });
                 }, this._babylonScene.database, true, function (request) {
                     _this._tryCatchOnError(function () {
@@ -4727,6 +4742,8 @@ var BABYLON;
                     });
                 });
                 if (request) {
+                    request._loaded = null;
+                    request._total = null;
                     this._requests.push(request);
                 }
             };
@@ -4816,6 +4833,94 @@ var BABYLON;
                 }
                 return 0;
             };
+            GLTFLoader.prototype._compileMaterialAsync = function (babylonMaterial, babylonMesh, onSuccess) {
+                var _this = this;
+                if (!this._parent.compileMaterials) {
+                    onSuccess();
+                    return;
+                }
+                if (this._parent.useClipPlane) {
+                    babylonMaterial.forceCompilation(babylonMesh, function () {
+                        babylonMaterial.forceCompilation(babylonMesh, function () {
+                            _this._tryCatchOnError(onSuccess);
+                        }, { clipPlane: true });
+                    });
+                }
+                else {
+                    babylonMaterial.forceCompilation(babylonMesh, function () {
+                        _this._tryCatchOnError(onSuccess);
+                    });
+                }
+            };
+            GLTFLoader.prototype._compileMaterialsAsync = function (onSuccess) {
+                if (!this._parent.compileMaterials || !this._gltf.materials) {
+                    onSuccess();
+                    return;
+                }
+                var meshes = this._getMeshes();
+                var remaining = 0;
+                for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                    var mesh = meshes_1[_i];
+                    if (mesh.material instanceof BABYLON.MultiMaterial) {
+                        for (var _a = 0, _b = mesh.material.subMaterials; _a < _b.length; _a++) {
+                            var subMaterial = _b[_a];
+                            if (subMaterial) {
+                                remaining++;
+                            }
+                        }
+                    }
+                }
+                if (remaining === 0) {
+                    onSuccess();
+                    return;
+                }
+                for (var _c = 0, meshes_2 = meshes; _c < meshes_2.length; _c++) {
+                    var mesh = meshes_2[_c];
+                    if (mesh.material instanceof BABYLON.MultiMaterial) {
+                        for (var _d = 0, _e = mesh.material.subMaterials; _d < _e.length; _d++) {
+                            var subMaterial = _e[_d];
+                            if (subMaterial) {
+                                this._compileMaterialAsync(subMaterial, mesh, function () {
+                                    if (--remaining === 0) {
+                                        onSuccess();
+                                    }
+                                });
+                            }
+                        }
+                    }
+                }
+            };
+            GLTFLoader.prototype._compileShadowGeneratorsAsync = function (onSuccess) {
+                var _this = this;
+                if (!this._parent.compileShadowGenerators) {
+                    onSuccess();
+                    return;
+                }
+                var lights = this._babylonScene.lights;
+                var remaining = 0;
+                for (var _i = 0, lights_1 = lights; _i < lights_1.length; _i++) {
+                    var light = lights_1[_i];
+                    var generator = light.getShadowGenerator();
+                    if (generator) {
+                        remaining++;
+                    }
+                }
+                if (remaining === 0) {
+                    onSuccess();
+                    return;
+                }
+                for (var _a = 0, lights_2 = lights; _a < lights_2.length; _a++) {
+                    var light = lights_2[_a];
+                    var generator = light.getShadowGenerator();
+                    if (generator) {
+                        generator.forceCompilation(function () {
+                            if (--remaining === 0) {
+                                _this._tryCatchOnError(onSuccess);
+                            }
+                        });
+                    }
+                }
+            };
             GLTFLoader.Extensions = {};
             return GLTFLoader;
         }());
@@ -4943,7 +5048,12 @@ var BABYLON;
             var MSFTLOD = /** @class */ (function (_super) {
                 __extends(MSFTLOD, _super);
                 function MSFTLOD() {
-                    return _super !== null && _super.apply(this, arguments) || this;
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
+                    /**
+                     * Specify the minimal delay between LODs in ms (default = 250)
+                     */
+                    _this.Delay = 250;
+                    return _this;
                 }
                 Object.defineProperty(MSFTLOD.prototype, "name", {
                     get: function () {
@@ -5001,7 +5111,7 @@ var BABYLON;
                             loader._tryCatchOnError(function () {
                                 _this._loadNodeLOD(loader, context, nodes, index - 1, onComplete);
                             });
-                        }, MSFTLOD.MinimalLODDelay);
+                        }, _this.Delay);
                     });
                 };
                 MSFTLOD.prototype._loadMaterial = function (loader, context, material, assign) {
@@ -5026,28 +5136,30 @@ var BABYLON;
                 MSFTLOD.prototype._loadMaterialLOD = function (loader, context, materials, index, assign, onComplete) {
                     var _this = this;
                     loader._loadMaterial(context, materials[index], function (babylonMaterial, isNew) {
-                        assign(babylonMaterial, isNew);
-                        if (index === 0) {
-                            onComplete();
-                            return;
+                        if (index === materials.length - 1) {
+                            assign(babylonMaterial, isNew);
+                            // Load the next LOD when the loader is ready to render.
+                            loader._executeWhenRenderReady(function () {
+                                _this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
+                            });
                         }
-                        // Load the next LOD when the loader is ready to render and
-                        // all active material textures of the current LOD are loaded.
-                        loader._executeWhenRenderReady(function () {
+                        else {
                             BABYLON.BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), function () {
-                                setTimeout(function () {
-                                    loader._tryCatchOnError(function () {
-                                        _this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
-                                    });
-                                }, MSFTLOD.MinimalLODDelay);
+                                assign(babylonMaterial, isNew);
+                                if (index === 0) {
+                                    onComplete();
+                                }
+                                else {
+                                    setTimeout(function () {
+                                        loader._tryCatchOnError(function () {
+                                            _this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
+                                        });
+                                    }, _this.Delay);
+                                }
                             });
-                        });
+                        }
                     });
                 };
-                /**
-                 * Specify the minimal delay between LODs in ms (default = 250)
-                 */
-                MSFTLOD.MinimalLODDelay = 250;
                 return MSFTLOD;
             }(GLTF2.GLTFLoaderExtension));
             Extensions.MSFTLOD = MSFTLOD;
@@ -5085,6 +5197,7 @@ var BABYLON;
                         loader._loadMaterialBaseProperties(context, material);
                         _this._loadSpecularGlossinessProperties(loader, context, material, extension);
                         assign(material.babylonMaterial, true);
+                        onComplete();
                     });
                 };
                 KHRMaterialsPbrSpecularGlossiness.prototype._loadSpecularGlossinessProperties = function (loader, context, material, properties) {

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


+ 11 - 8
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -118,13 +118,13 @@ declare module BABYLON {
         static HomogeneousCoordinates: boolean;
         static IncrementalLoading: boolean;
         coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
+        compileMaterials: boolean;
+        compileShadowGenerators: boolean;
+        useClipPlane: boolean;
+        onMeshLoaded: (mesh: AbstractMesh) => void;
         onTextureLoaded: (texture: BaseTexture) => void;
         onMaterialLoaded: (material: Material) => void;
         /**
-         * Let the user decides if he needs to process the material (like precompilation) before affecting it to meshes
-         */
-        onBeforeMaterialReadyAsync: (material: Material, targetMesh: AbstractMesh, isLOD: boolean, callback: () => void) => void;
-        /**
          * Raised when the asset is completely loaded, just before the loader is disposed.
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete just after onSuccess.
@@ -974,7 +974,7 @@ declare module BABYLON.GLTF2 {
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onProgress: (event: ProgressEvent) => void, onError: (message: string) => void): void;
         private _loadAsync(nodeNames, scene, data, rootUrl, onSuccess, onProgress, onError);
-        private _onProgress(event);
+        private _onProgress();
         _executeWhenRenderReady(func: () => void): void;
         private _onRenderReady();
         private _onComplete();
@@ -1032,14 +1032,17 @@ declare module BABYLON.GLTF2 {
         _loadMaterialBaseProperties(context: string, material: IGLTFMaterial): void;
         _loadMaterialAlphaProperties(context: string, material: IGLTFMaterial, colorFactor: number[]): void;
         _loadTexture(context: string, texture: IGLTFTexture, coordinatesIndex?: number): Texture;
-        private _loadImage(context, image, onSuccess);
-        _loadUri(context: string, uri: string, onSuccess: (data: ArrayBufferView) => void): void;
+        private _loadImageAsync(context, image, onSuccess);
+        _loadUriAsync(context: string, uri: string, onSuccess: (data: ArrayBufferView) => void): void;
         _tryCatchOnError(handler: () => void): void;
         private static _AssignIndices(array?);
         static _GetProperty<T extends IGLTFProperty>(array?: ArrayLike<T>, index?: number): Nullable<T>;
         private static _GetTextureWrapMode(mode?);
         private static _GetTextureSamplingMode(magFilter?, minFilter?);
         private static _GetNumComponents(type);
+        private _compileMaterialAsync(babylonMaterial, babylonMesh, onSuccess);
+        private _compileMaterialsAsync(onSuccess);
+        private _compileShadowGeneratorsAsync(onSuccess);
     }
 }
 
@@ -1086,7 +1089,7 @@ declare module BABYLON.GLTF2.Extensions {
         /**
          * Specify the minimal delay between LODs in ms (default = 250)
          */
-        static MinimalLODDelay: number;
+        Delay: number;
         readonly name: string;
         protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean;
         protected _loadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean;

+ 1 - 1
dist/preview release/loaders/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-loaders",
     "description": "The Babylon.js file loaders library is an extension you can use to load different 3D file types into a Babylon scene.",
-    "version": "3.1.0-beta1.1",
+    "version": "3.1.0-beta3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/materialsLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-materials",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "3.1.0-beta1.1",
+    "version": "3.1.0-beta3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/postProcessesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-post-process",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "3.1.0-beta1.1",
+    "version": "3.1.0-beta3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/proceduralTexturesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-procedural-textures",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "3.1.0-beta1.1",
+    "version": "3.1.0-beta3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/serializers/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-serializers",
     "description": "The Babylon.js serializers library is an extension you can use to serialize Babylon scenes.",
-    "version": "3.1.0-beta1.1",
+    "version": "3.1.0-beta3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
gui/src/advancedDynamicTexture.ts

@@ -300,7 +300,7 @@ module BABYLON.GUI {
                         continue;
                     }
                     
-                    var position = (<BoundingInfo>mesh.getBoundingInfo()).boundingSphere.center;
+                    var position = mesh.getBoundingInfo().boundingSphere.center;
                     var projectedPosition = Vector3.Project(position, mesh.getWorldMatrix(), scene.getTransformMatrix(), globalViewport);
 
                     if (projectedPosition.z < 0 || projectedPosition.z > 1) {

+ 8 - 1
inspector/sass/_tree.scss

@@ -35,7 +35,7 @@
             line-height: 1em;
             display    : inline-block;
             font-family: 'FontAwesome', sans-serif;
-            content    : "\f078";
+            content    : "\f078";            
         }
         &.folded:before{            
             width      : 1em;
@@ -45,6 +45,13 @@
             font-family: 'FontAwesome', sans-serif;
             content    : "\f054";
         }
+        
+        &.unfolded.transformNode > span:first-of-type{
+            color:$color-top;
+        }
+        &.folded.transformNode > span:first-of-type{ 
+            color:$color-top;
+        }
 
         // Sub lines
         .line-content {

+ 0 - 5
inspector/src/adapters/Adapter.ts

@@ -20,11 +20,6 @@ module INSPECTOR {
         /** Returns the list of properties to be displayed for this adapter */
         public abstract getProperties(): Array<PropertyLine>;
 
-        /** Returns the actual object behind this adapter */
-        public get actualObject(): any {
-            return this._obj;
-        }
-
         /** Returns true if the given object correspond to this  */
         public correspondsTo(obj: any) {
             return obj === this._obj;

+ 16 - 8
inspector/src/adapters/MeshAdapter.ts

@@ -8,7 +8,7 @@ module INSPECTOR {
         private _axesViewer: BABYLON.Nullable<BABYLON.Debug.AxesViewer>;
         private onBeforeRenderObserver: BABYLON.Nullable<BABYLON.Observer<BABYLON.Scene>>;
 
-        constructor(mesh: BABYLON.AbstractMesh) {
+        constructor(mesh: BABYLON.Node) {
             super(mesh);
         }
 
@@ -35,10 +35,13 @@ module INSPECTOR {
             let tools = [];
             tools.push(new Checkbox(this));
             tools.push(new DebugArea(this));
-            if ((this._obj as BABYLON.AbstractMesh).getTotalVertices() > 0) {
-                tools.push(new BoundingBox(this));
+            if (this._obj instanceof BABYLON.AbstractMesh) {
+                if ((this._obj as BABYLON.AbstractMesh).getTotalVertices() > 0) {
+                    tools.push(new BoundingBox(this));
+                }
             }
 
+
             tools.push(new Info(this));
             return tools;
         }
@@ -60,7 +63,7 @@ module INSPECTOR {
         public debug(enable: boolean) {
             // Draw axis the first time
             if (!this._axesViewer) {
-                 this._drawAxis();
+                this._drawAxis();
             }
             // Display or hide axis
             if (!enable && this._axesViewer) {
@@ -73,7 +76,10 @@ module INSPECTOR {
 
         /** Returns some information about this mesh */
         public getInfo(): string {
-            return `${(this._obj as BABYLON.AbstractMesh).getTotalVertices()} vertices`;
+            if (this._obj instanceof BABYLON.AbstractMesh) {
+                return `${(this._obj as BABYLON.AbstractMesh).getTotalVertices()} vertices`;
+            }
+            return '0 vertices';
         }
 
         /** Draw X, Y and Z axis for the actual object if this adapter.
@@ -82,8 +88,6 @@ module INSPECTOR {
         private _drawAxis() {
             this._obj.computeWorldMatrix();
 
-            let mesh = this._obj as BABYLON.Mesh;
-
             // Axis
             var x = new BABYLON.Vector3(1, 0, 0);
             var y = new BABYLON.Vector3(0, 1, 0);
@@ -91,9 +95,13 @@ module INSPECTOR {
 
             this._axesViewer = new BABYLON.Debug.AxesViewer(this._obj.getScene());
 
+            let mesh = this._obj as BABYLON.TransformNode;
             this.onBeforeRenderObserver = mesh.getScene().onBeforeRenderObservable.add(() => {
                 let matrix = mesh.getWorldMatrix();
-                let extend = mesh.getBoundingInfo()!.boundingBox.extendSizeWorld;
+                let extend = new BABYLON.Vector3(1, 1, 1);
+                if (mesh instanceof BABYLON.AbstractMesh) {
+                    extend = mesh.getBoundingInfo().boundingBox.extendSizeWorld;
+                }
                 this._axesViewer!.scaleLines = Math.max(extend.x, extend.y, extend.z) * 2;
                 this._axesViewer!.update(this._obj.position, BABYLON.Vector3.TransformNormal(x, matrix), BABYLON.Vector3.TransformNormal(y, matrix), BABYLON.Vector3.TransformNormal(z, matrix));
             });

+ 15 - 13
inspector/src/details/PropertyLine.ts

@@ -150,7 +150,7 @@ module INSPECTOR {
             }
         }
 
-        public validateInput(value: any, forceupdate:boolean = true): void {
+        public validateInput(value: any, forceupdate: boolean = true): void {
             this.updateObject();
             if (typeof this._property.value === 'number') {
                 this._property.value = parseFloat(value);
@@ -182,7 +182,7 @@ module INSPECTOR {
             Helpers.CleanDiv(this._valueDiv);
             if (typeof this.value !== 'boolean' && !this._isSliderType()) {
                 this._valueDiv.textContent = "-";
-            } 
+            }
             // restore elements
             for (let elem of this._elements) {
                 this._valueDiv.appendChild(elem.toHtml());
@@ -313,7 +313,7 @@ module INSPECTOR {
             // Then update its value
             // this._valueDiv.textContent = " "; // TOFIX this removes the elements after
             if (typeof this.value === 'boolean') {
-                 this._checkboxInput();
+                this._checkboxInput();
             } else if (this._isSliderType()) { // Add slider when parent have slider property
                 this._rangeInput();
             } else {
@@ -386,7 +386,9 @@ module INSPECTOR {
                 this._div.classList.toggle('unfolded');
                 if (this._children.length == 0) {
                     let objToDetail = this.value;
-                    let propToDisplay = (<any>PROPERTIES)[Helpers.GET_TYPE(objToDetail)].properties.slice().reverse();
+                    // Display all properties that are not functions
+                    let propToDisplay = Helpers.GetAllLinesPropertiesAsString(objToDetail);
+                    propToDisplay.sort().reverse();
 
                     for (let prop of propToDisplay) {
                         let infos = new Property(prop, this._property.value);
@@ -395,7 +397,7 @@ module INSPECTOR {
                     }
                 }
                 // otherwise display it    
-                if (this._div.parentNode) {                
+                if (this._div.parentNode) {
                     for (let child of this._children) {
                         this._div.parentNode.insertBefore(child.toHtml(), this._div.nextSibling);
                     }
@@ -437,7 +439,7 @@ module INSPECTOR {
          * Create input entry
          */
         private _checkboxInput() {
-            if(this._valueDiv.childElementCount < 1) { // Prevent display two checkbox
+            if (this._valueDiv.childElementCount < 1) { // Prevent display two checkbox
                 this._input = Helpers.CreateInput('checkbox-element', this._valueDiv);
                 this._input.type = 'checkbox'
                 this._input.checked = this.value;
@@ -445,11 +447,11 @@ module INSPECTOR {
                     Scheduler.getInstance().pause = true;
                     this.validateInput(!this.value)
                 })
-            }            
+            }
         }
 
         private _rangeInput() {
-            if(this._valueDiv.childElementCount < 1) { // Prevent display two input range
+            if (this._valueDiv.childElementCount < 1) { // Prevent display two input range
                 this._input = Helpers.CreateInput('slider-element', this._valueDiv);
                 this._input.type = 'range';
                 this._input.style.display = 'inline-block';
@@ -457,7 +459,7 @@ module INSPECTOR {
                 this._input.max = this._getSliderProperty().max;
                 this._input.step = this._getSliderProperty().step;
                 this._input.value = this.value;
-                
+
                 this._validateInputHandler = this._rangeHandler.bind(this)
                 this._input.addEventListener('input', this._validateInputHandler)
                 this._input.addEventListener('change', () => {
@@ -479,10 +481,10 @@ module INSPECTOR {
         }
 
         private _isSliderType() { //Check if property have slider definition
-            return this._property  && 
-            PROPERTIES.hasOwnProperty(this._property.obj.constructor.name) &&
-            (<any>PROPERTIES)[this._property.obj.constructor.name].hasOwnProperty('slider') && 
-            (<any>PROPERTIES)[this._property.obj.constructor.name].slider.hasOwnProperty(this.name);
+            return this._property &&
+                PROPERTIES.hasOwnProperty(this._property.obj.constructor.name) &&
+                (<any>PROPERTIES)[this._property.obj.constructor.name].hasOwnProperty('slider') &&
+                (<any>PROPERTIES)[this._property.obj.constructor.name].slider.hasOwnProperty(this.name);
         }
 
         private _getSliderProperty() {

+ 29 - 13
inspector/src/helpers/Helpers.ts

@@ -7,7 +7,7 @@ module INSPECTOR {
          * uses getClassName. If nothing is returned, used the type of the constructor
          */
         public static GET_TYPE(obj: any): string {
-            if(typeof obj === 'boolean') {
+            if (typeof obj === 'boolean') {
                 return 'boolean';
             }
 
@@ -24,10 +24,10 @@ module INSPECTOR {
                 if (!this._CheckIfTypeExists(classname)) {
                     return this._GetTypeFor(obj);
                 }
-                
+
                 return classname;
             } else {
-                
+
                 return 'type_not_defined';
             }
         }
@@ -91,6 +91,9 @@ module INSPECTOR {
 
         /** Returns the given number with 2 decimal number max if a decimal part exists */
         public static Trunc(nb: number): number {
+            if (typeof nb !== 'number') {
+                return 0;
+            }
             if (Math.round(nb) !== nb) {
                 return (<any>nb.toFixed(2));
             }
@@ -141,7 +144,7 @@ module INSPECTOR {
             div.style.display = 'none';
             div.appendChild(clone);
             let value = (<any>Inspector.WINDOW.getComputedStyle(clone))[cssAttribute];
-            if (div.parentNode)  {
+            if (div.parentNode) {
                 div.parentNode.removeChild(div);
             }
             return value;
@@ -185,20 +188,33 @@ module INSPECTOR {
          */
         public static GetAllLinesProperties(obj: any): Array<PropertyLine> {
             let propertiesLines: Array<PropertyLine> = [];
-            
+            let props = Helpers.GetAllLinesPropertiesAsString(obj);
+
+            for (let prop of props) {
+                let infos = new Property(prop, obj);
+                propertiesLines.push(new PropertyLine(infos));
+            }
+            return propertiesLines;
+        }
+
+
+        /**
+         * Returns an array of string corresponding to tjhe list of properties of the object to be displayed
+         * @param obj 
+         */
+        public static GetAllLinesPropertiesAsString(obj: any): Array<string> {
+            let props: Array<string> = [];
+
             for (let prop in obj) {
-                /**
-                 * No private and no function
-                 */
-                if(prop.substring(0, 1) !== '_' && typeof obj[prop] !== 'function') {
-                    let infos = new Property(prop, obj);
-                    propertiesLines.push(new PropertyLine(infos));
+                //No private and no function
+                if (prop.substring(0, 1) !== '_' && typeof obj[prop] !== 'function') {
+                    props.push(prop);
                 }
             }
-            return propertiesLines;
+            return props;
         }
 
-        public static Capitalize (str : string) : string {
+        public static Capitalize(str: string): string {
             return str.charAt(0).toUpperCase() + str.slice(1);
         }
     }

+ 17 - 237
inspector/src/properties.ts

@@ -20,59 +20,39 @@ module INSPECTOR {
         },
         'Vector2': {
             type: BABYLON.Vector2,
-            properties: ['x', 'y'],
             format: (vec: BABYLON.Vector2) => { return `x:${Helpers.Trunc(vec.x)}, y:${Helpers.Trunc(vec.y)}`; }
         },
         'Vector3': {
             type: BABYLON.Vector3,
-            properties: ['x', 'y', 'z'],
             format: (vec: BABYLON.Vector3) => { return `x:${Helpers.Trunc(vec.x)}, y:${Helpers.Trunc(vec.y)}, z:${Helpers.Trunc(vec.z)}` }
         },
         'Color3': {
             type: BABYLON.Color3,
-            properties: ['r', 'g', 'b'],
             format: (color: BABYLON.Color3) => { return `R:${color.r}, G:${color.g}, B:${color.b}` },
             slider: {
-                r: {min: 0, max: 1, step: 0.01},
-                g: {min: 0, max: 1, step: 0.01},
-                b: {min: 0, max: 1, step: 0.01}
+                r: { min: 0, max: 1, step: 0.01 },
+                g: { min: 0, max: 1, step: 0.01 },
+                b: { min: 0, max: 1, step: 0.01 }
             }
         },
         'Color4': {
             type: BABYLON.Color4,
-            properties: ['r', 'g', 'b'],
             format: (color: BABYLON.Color4) => { return `R:${color.r}, G:${color.g}, B:${color.b}` },
             slider: {
-                r: {min: 0, max: 1, step: 0.01},
-                g: {min: 0, max: 1, step: 0.01},
-                b: {min: 0, max: 1, step: 0.01}
+                r: { min: 0, max: 1, step: 0.01 },
+                g: { min: 0, max: 1, step: 0.01 },
+                b: { min: 0, max: 1, step: 0.01 }
             }
         },
         'Quaternion': {
-            type: BABYLON.Quaternion,
-            properties: ['x', 'y', 'z', 'w']
+            type: BABYLON.Quaternion
         },
         'Size': {
             type: BABYLON.Size,
-            properties: ['width', 'height'],
             format: (size: BABYLON.Size) => { return `Size - w:${Helpers.Trunc(size.width)}, h:${Helpers.Trunc(size.height)}` }
         },
         'Texture': {
             type: BABYLON.Texture,
-            properties: [
-                'hasAlpha',
-                'level',
-                'name',
-                'wrapU',
-                'wrapV',
-                'uScale',
-                'vScale',
-                'uAng',
-                'vAng',
-                'wAng',
-                'uOffset',
-                'vOffset'
-            ],
             format: (tex: BABYLON.Texture) => { return tex.name }
         },
         'RenderTargetTexture': {
@@ -91,247 +71,47 @@ module INSPECTOR {
             type: BABYLON.HDRCubeTexture
         },
         'Sound': {
-            type: BABYLON.Sound,
-            properties: [
-                'name',
-                'autoplay',
-                'loop',
-                'useCustomAttenuation',
-                'soundTrackId',
-                'spatialSound',
-                'refDistance',
-                'rolloffFactor',
-                'maxDistance',
-                'distanceModel',
-                'isPlaying',
-                'isPaused'
-            ]
+            type: BABYLON.Sound
         },
         'ArcRotateCamera': {
             type: BABYLON.ArcRotateCamera,
-            properties: [
-                'position',
-                'alpha',
-                'beta',
-                'radius',
-                'angularSensibilityX',
-                'angularSensibilityY',
-                'angularTouchSensibilityX',
-                'angularTouchSensibilityY',
-                'target',
-                'lowerAlphaLimit',
-                'lowerBetaLimit',
-                'upperAlphaLimit',
-                'upperBetaLimit',
-                'lowerRadiusLimit',
-                'upperRadiusLimit',
-
-                'pinchPrecision',
-                'wheelPrecision',
-                'allowUpsideDown',
-                'checkCollisions'
-            ],
             slider: {
-                alpha: {min: 0, max: 2*Math.PI, step: 0.01},
-                beta: {min: -Math.PI, max: Math.PI, step: 0.01},
-                fov: {min: 0, max: 180, step: 1}
+                alpha: { min: 0, max: 2 * Math.PI, step: 0.01 },
+                beta: { min: -Math.PI, max: Math.PI, step: 0.01 },
+                fov: { min: 0, max: 180, step: 1 }
             }
         },
         'FreeCamera': {
             type: BABYLON.FreeCamera,
-            properties: [
-                'position',
-                'rotation',
-                'rotationQuaternion',
-                'cameraDirection',
-                'cameraRotation',
-                'ellipsoid',
-                'applyGravity',
-                'angularSensibility',
-                'keysUp',
-                'keysDown',
-                'keysLeft',
-                'keysRight',
-                'checkCollisions',
-                'speed',
-                'lockedTarget',
-                'noRotationConstraint',
-                'fov',
-                'inertia',
-                'minZ', 'maxZ',
-                'layerMask',
-                'mode',
-                'orthoBottom',
-                'orthoTop',
-                'orthoLeft',
-                'orthoRight'
-            ],
             slider: {
-                fov: {min: 0, max: 180, step: 1}
+                fov: { min: 0, max: 180, step: 1 }
             }
         },
         'Scene': {
             type: BABYLON.Scene,
-            properties: [
-                'actionManager',
-                'activeCamera',
-                'ambientColor',
-                'clearColor',
-                'forceWireframe',
-                'forcePointsCloud',
-                'forceShowBoundingBoxes',
-                'useRightHandedSystem',
-                'hoverCursor',
-                'cameraToUseForPointers',
-                'fogEnabled',
-                'fogColor',
-                'fogDensity',
-                'fogStart',
-                'fogEnd',
-                'shadowsEnabled',
-                'lightsEnabled',
-                'collisionsEnabled',
-                'gravity',
-                'meshUnderPointer',
-                'pointerX',
-                'pointerY',
-                'uid'
-            ]
         },
         'Mesh': {
             type: BABYLON.Mesh,
-            properties: [
-                'name',
-                'position',
-                'rotation',
-                'rotationQuaternion',
-                'absolutePosition',
-                'material',
-                'actionManager',
-                'visibility',
-                'isVisible',
-                'isPickable',
-                'renderingGroupId',
-                'receiveShadows',
-                'renderOutline',
-                'outlineColor',
-                'outlineWidth',
-                'renderOverlay',
-                'overlayColor',
-                'overlayAlpha',
-                'hasVertexAlpha',
-                'useVertexColors',
-                'layerMask',
-                'alwaysSelectAsActiveMesh',
-                'ellipsoid',
-                'ellipsoidOffset',
-                'edgesWidth',
-                'edgesColor',
-                'checkCollisions',
-                'hasLODLevels'
-            ],
             format: (m: BABYLON.Mesh): string => { return m.name; },
             slider: {
-                visibility: {min: 0, max: 1, step: 0.1}
+                visibility: { min: 0, max: 1, step: 0.1 }
             }
         },
         'StandardMaterial': {
             type: BABYLON.StandardMaterial,
-            properties: [
-                'name',
-                'alpha',
-                'alphaMode',
-                'wireframe',
-                'isFrozen',
-                'zOffset',
-
-                'ambientColor',
-                'emissiveColor',
-                'diffuseColor',
-                'specularColor',
-
-                'specularPower',
-                'useAlphaFromDiffuseTexture',
-                'linkEmissiveWithDiffuse',
-                'useSpecularOverAlpha',
-
-                'diffuseFresnelParameters',
-                'opacityFresnelParameters',
-                'reflectionFresnelParameters',
-                'refractionFresnelParameters',
-                'emissiveFresnelParameters',
-
-                'diffuseTexture',
-                'emissiveTexture',
-                'specularTexture',
-                'ambientTexture',
-                'bumpTexture',
-                'lightMapTexture',
-                'opacityTexture',
-                'reflectionTexture',
-                'refractionTexture'
-            ],
             format: (mat: BABYLON.StandardMaterial): string => { return mat.name; },
             slider: {
-                alpha: {min: 0, max: 1, step: 0.01}
+                alpha: { min: 0, max: 1, step: 0.01 }
             }
         },
         'PBRMaterial': {
             type: BABYLON.PBRMaterial,
-            properties: [
-                'name',
-                'albedoColor',
-                'albedoTexture',
-
-                'opacityTexture',
-                'reflectionTexture',
-                'emissiveTexture',
-                'bumpTexture',
-                'lightmapTexture',
-
-                'opacityFresnelParameters',
-                'emissiveFresnelParameters',
-
-                'linkEmissiveWithAlbedo',
-                'useLightmapAsShadowmap',
-
-                'useAlphaFromAlbedoTexture',
-                'useSpecularOverAlpha',
-                'useAutoMicroSurfaceFromReflectivityMap',
-                'useLogarithmicDepth',
-
-                'reflectivityColor',
-                'reflectivityTexture',
-                'reflectionTexture',
-                'reflectionColor',
-
-                'alpha',
-                'linkRefractionWithTransparency',
-                'indexOfRefraction',
-
-                'microSurface',
-                'useMicroSurfaceFromReflectivityMapAlpha',
-
-                'directIntensity',
-                'emissiveIntensity',
-                'specularIntensity',
-                'environmentIntensity',
-                'cameraExposure',
-                'cameraContrast',
-                'cameraColorGradingTexture',
-                'cameraColorCurves'
-            ],
             slider: {
-                alpha: {min: 0, max: 1, step: 0.01}
+                alpha: { min: 0, max: 1, step: 0.01 }
             }
-        },  
+        },
         'PhysicsImpostor': {
-            type: BABYLON.PhysicsImpostor,
-            properties: [
-                'friction',
-                'mass',
-                'restitution',
-            ]
+            type: BABYLON.PhysicsImpostor
         },
     }
 

+ 39 - 22
inspector/src/tabs/MeshTab.ts

@@ -1,66 +1,83 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
-module INSPECTOR{
-    
+module INSPECTOR {
+
     export class MeshTab extends PropertyTab {
-                
-        constructor(tabbar:TabBar, inspector:Inspector) {
-            super(tabbar, 'Mesh', inspector); 
+
+        constructor(tabbar: TabBar, inspector: Inspector) {
+            super(tabbar, 'Mesh', inspector);
         }
 
         /* Overrides super */
-        protected _getTree() : Array<TreeItem> {
+        protected _getTree(): Array<TreeItem> {
             let arr = new Array<TreeItem>();
             // Tab containing mesh already in results
-            let alreadyIn = new Array<BABYLON.AbstractMesh>();
+            let alreadyIn = new Array<BABYLON.Node>();
 
             // Recursive method building the tree panel
-            let createNode = (obj : BABYLON.AbstractMesh) => {
+            let createNode = (obj: BABYLON.Node) => {
                 let descendants = obj.getDescendants(true);
 
                 let node = new TreeItem(this, new MeshAdapter(obj));
 
                 if (descendants.length > 0) {
-                    for (let child of descendants) {     
-                        if (child instanceof BABYLON.AbstractMesh) {
-                            if (!Helpers.IsSystemName(child.name)) {  
+                    for (let child of descendants) {
+                        if (child instanceof BABYLON.TransformNode) {
+                            if (!Helpers.IsSystemName(child.name)) {
                                 let n = createNode(child);
-                                node.add(n); 
+                                node.add(n);
                             }
                         }
                     }
                     node.update();
-                } 
+                }
 
                 // Retrieve the root node if the mesh is actually child of another mesh
                 // This can hapen if the child mesh has been created before the parent mesh
-                if(obj.parent != null && alreadyIn.indexOf(obj) != -1){
+                if (obj.parent != null && alreadyIn.indexOf(obj) != -1) {
                     let i: number = 0;
                     let notFound: boolean = true;
                     // Find and delete the root node standing for this mesh
-                    while(i < arr.length && notFound){
-                        if(obj.name === arr[i].id){
-                             arr.splice(i, 1);
-                             notFound = false;
+                    while (i < arr.length && notFound) {
+                        if (obj.name === arr[i].id) {
+                            arr.splice(i, 1);
+                            notFound = false;
                         }
                         i++;
                     }
                 }
 
-                alreadyIn.push(obj);                
+                alreadyIn.push(obj);
                 return node;
             };
-            
+
             // get all meshes from the first scene
             let instances = this._inspector.scene;
+
+            // Find top of hierarchy for meshes...
+            let meshWithoutAnyParent: Array<BABYLON.Node> = [];
             for (let mesh of instances.meshes) {
+                // Not already in the array, not system name and no parent
+                if (meshWithoutAnyParent.indexOf(mesh) == -1 && !Helpers.IsSystemName(mesh.name) && !mesh.parent) {
+                    meshWithoutAnyParent.push(mesh);
+                }
+            }
+            // ... and for transforms
+            for (let tn of instances.transformNodes) {
+                // Not already in the array, not system name and no parent
+                if (meshWithoutAnyParent.indexOf(tn) == -1 && !Helpers.IsSystemName(tn.name) && !tn.parent) {
+                    meshWithoutAnyParent.push(tn);
+                }
+            }
+
+            for (let mesh of meshWithoutAnyParent) {
                 if (alreadyIn.indexOf(mesh) == -1 && !Helpers.IsSystemName(mesh.name)) {
                     let node = createNode(mesh);
                     arr.push(node);
                 }
             }
             return arr;
-        }  
+        }
     }
-    
+
 }

+ 78 - 77
inspector/src/tabs/SceneTab.ts

@@ -1,55 +1,56 @@
 declare function Split(elements: HTMLElement[], options: any): void;
 module INSPECTOR {
-    
+
     export class SceneTab extends Tab {
-        
-        private _inspector : Inspector;
+
+        private _inspector: Inspector;
         /** The list of  channels/options that can be activated/deactivated */
-        private _actions   : HTMLDivElement;
+        private _actions: HTMLDivElement;
 
         /** The list of skeleton viewer */
-        private _skeletonViewers : Array<BABYLON.Debug.SkeletonViewer> = [];
+        private _skeletonViewers: Array<BABYLON.Debug.SkeletonViewer> = [];
 
         /** The detail of the scene */
-        private _detailsPanel : DetailPanel;        
-                
-        constructor(tabbar:TabBar, insp:Inspector) {
-            super(tabbar, 'Scene');            
-            this._inspector = insp;  
-            
+        private _detailsPanel: DetailPanel;
+
+        constructor(tabbar: TabBar, insp: Inspector) {
+            super(tabbar, 'Scene');
+            this._inspector = insp;
+
             // Build the properties panel : a div that will contains the tree and the detail panel
-            this._panel   = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
-            
+            this._panel = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
+
             this._actions = Helpers.CreateDiv('scene-actions', this._panel) as HTMLDivElement;
-           
+
             this._detailsPanel = new DetailPanel();
             this._panel.appendChild(this._detailsPanel.toHtml());
-            
+
             // build propertiesline
             let details = [];
-            for (let prop of PROPERTIES['Scene'].properties) {
-                details.push(new PropertyLine(new Property(prop, this._inspector.scene)));
+            let props = Helpers.GetAllLinesProperties(this._inspector.scene);
+            for (let prop of props) {
+                details.push(prop);
             }
             this._detailsPanel.details = details;
-            
-            Split([this._actions, this._detailsPanel.toHtml()], {  
-                blockDrag : this._inspector.popupMode,
-                sizes:[50, 50],
-                direction:'vertical'
-            });  
-            
+
+            Split([this._actions, this._detailsPanel.toHtml()], {
+                blockDrag: this._inspector.popupMode,
+                sizes: [50, 50],
+                direction: 'vertical'
+            });
+
             // Build actions
             {
-                
+
                 // Rendering mode
                 let title = Helpers.CreateDiv('actions-title', this._actions);
                 title.textContent = 'Rendering mode';
-                let point             = Helpers.CreateDiv('action-radio', this._actions);
-                let wireframe         = Helpers.CreateDiv('action-radio', this._actions);
-                let solid             = Helpers.CreateDiv('action-radio', this._actions);
-                point.textContent     = 'Point';
+                let point = Helpers.CreateDiv('action-radio', this._actions);
+                let wireframe = Helpers.CreateDiv('action-radio', this._actions);
+                let solid = Helpers.CreateDiv('action-radio', this._actions);
+                point.textContent = 'Point';
                 wireframe.textContent = 'Wireframe';
-                solid.textContent     = 'Solid';
+                solid.textContent = 'Solid';
                 if (this._inspector.scene.forcePointsCloud) {
                     point.classList.add('active');
                 } else if (this._inspector.scene.forceWireframe) {
@@ -58,64 +59,64 @@ module INSPECTOR {
                     solid.classList.add('active');
                 }
                 this._generateRadioAction([point, wireframe, solid]);
-                point.addEventListener('click', () => {this._inspector.scene.forcePointsCloud = true; this._inspector.scene.forceWireframe = false;});
-                wireframe.addEventListener('click', () => {this._inspector.scene.forcePointsCloud = false; this._inspector.scene.forceWireframe = true; });
-                solid.addEventListener('click',  () => {this._inspector.scene.forcePointsCloud = false; this._inspector.scene.forceWireframe = false; });
+                point.addEventListener('click', () => { this._inspector.scene.forcePointsCloud = true; this._inspector.scene.forceWireframe = false; });
+                wireframe.addEventListener('click', () => { this._inspector.scene.forcePointsCloud = false; this._inspector.scene.forceWireframe = true; });
+                solid.addEventListener('click', () => { this._inspector.scene.forcePointsCloud = false; this._inspector.scene.forceWireframe = false; });
 
                 // Textures
                 title = Helpers.CreateDiv('actions-title', this._actions);
                 title.textContent = 'Textures channels';
-                this._generateActionLine('Diffuse Texture', BABYLON.StandardMaterial.DiffuseTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.DiffuseTextureEnabled = b });
-                this._generateActionLine('Ambient Texture', BABYLON.StandardMaterial.AmbientTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.AmbientTextureEnabled = b });
-                this._generateActionLine('Specular Texture', BABYLON.StandardMaterial.SpecularTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.SpecularTextureEnabled = b });
-                this._generateActionLine('Emissive Texture', BABYLON.StandardMaterial.EmissiveTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.EmissiveTextureEnabled = b });
-                this._generateActionLine('Bump Texture', BABYLON.StandardMaterial.BumpTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.BumpTextureEnabled = b });
-                this._generateActionLine('Opacity Texture', BABYLON.StandardMaterial.OpacityTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.OpacityTextureEnabled = b });
-                this._generateActionLine('Reflection Texture', BABYLON.StandardMaterial.ReflectionTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.ReflectionTextureEnabled = b });
-                this._generateActionLine('Refraction Texture', BABYLON.StandardMaterial.RefractionTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.RefractionTextureEnabled = b });
-                this._generateActionLine('ColorGrading', BABYLON.StandardMaterial.ColorGradingTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.ColorGradingTextureEnabled = b });
-                this._generateActionLine('Lightmap Texture', BABYLON.StandardMaterial.LightmapTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.LightmapTextureEnabled = b });
-                this._generateActionLine('Fresnel', BABYLON.StandardMaterial.FresnelEnabled, (b:boolean) => {BABYLON.StandardMaterial.FresnelEnabled = b });
+                this._generateActionLine('Diffuse Texture', BABYLON.StandardMaterial.DiffuseTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.DiffuseTextureEnabled = b });
+                this._generateActionLine('Ambient Texture', BABYLON.StandardMaterial.AmbientTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.AmbientTextureEnabled = b });
+                this._generateActionLine('Specular Texture', BABYLON.StandardMaterial.SpecularTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.SpecularTextureEnabled = b });
+                this._generateActionLine('Emissive Texture', BABYLON.StandardMaterial.EmissiveTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.EmissiveTextureEnabled = b });
+                this._generateActionLine('Bump Texture', BABYLON.StandardMaterial.BumpTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.BumpTextureEnabled = b });
+                this._generateActionLine('Opacity Texture', BABYLON.StandardMaterial.OpacityTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.OpacityTextureEnabled = b });
+                this._generateActionLine('Reflection Texture', BABYLON.StandardMaterial.ReflectionTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.ReflectionTextureEnabled = b });
+                this._generateActionLine('Refraction Texture', BABYLON.StandardMaterial.RefractionTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.RefractionTextureEnabled = b });
+                this._generateActionLine('ColorGrading', BABYLON.StandardMaterial.ColorGradingTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.ColorGradingTextureEnabled = b });
+                this._generateActionLine('Lightmap Texture', BABYLON.StandardMaterial.LightmapTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.LightmapTextureEnabled = b });
+                this._generateActionLine('Fresnel', BABYLON.StandardMaterial.FresnelEnabled, (b: boolean) => { BABYLON.StandardMaterial.FresnelEnabled = b });
 
                 // Options
                 title = Helpers.CreateDiv('actions-title', this._actions);
-                title.textContent = 'Options'; 
-                this._generateActionLine('Animations', this._inspector.scene.animationsEnabled, (b:boolean) => {this._inspector.scene.animationsEnabled = b });
-                this._generateActionLine('Collisions', this._inspector.scene.collisionsEnabled, (b:boolean) => {this._inspector.scene.collisionsEnabled = b });
-                this._generateActionLine('Fog', this._inspector.scene.fogEnabled, (b:boolean) => {this._inspector.scene.fogEnabled = b });
-                this._generateActionLine('Lens flares', this._inspector.scene.lensFlaresEnabled, (b:boolean) => {this._inspector.scene.lensFlaresEnabled = b });
-                this._generateActionLine('Lights', this._inspector.scene.lightsEnabled, (b:boolean) => {this._inspector.scene.lightsEnabled = b });
-                this._generateActionLine('Particles', this._inspector.scene.particlesEnabled, (b:boolean) => {this._inspector.scene.particlesEnabled = b });
-                this._generateActionLine('Post-processes', this._inspector.scene.postProcessesEnabled, (b:boolean) => {this._inspector.scene.postProcessesEnabled = b });
-                this._generateActionLine('Probes', this._inspector.scene.probesEnabled, (b:boolean) => {this._inspector.scene.probesEnabled = b });
-                this._generateActionLine('Procedural textures', this._inspector.scene.proceduralTexturesEnabled, (b:boolean) => {this._inspector.scene.proceduralTexturesEnabled = b });
-                this._generateActionLine('Render targets', this._inspector.scene.renderTargetsEnabled, (b:boolean) => {this._inspector.scene.renderTargetsEnabled = b });
-                this._generateActionLine('Shadows', this._inspector.scene.shadowsEnabled, (b:boolean) => {this._inspector.scene.shadowsEnabled = b });
-                this._generateActionLine('Skeletons', this._inspector.scene.skeletonsEnabled, (b:boolean) => {this._inspector.scene.skeletonsEnabled = b });
-                this._generateActionLine('Sprites', this._inspector.scene.spritesEnabled, (b:boolean) => {this._inspector.scene.spritesEnabled = b });
-                this._generateActionLine('Textures', this._inspector.scene.texturesEnabled, (b:boolean) => {this._inspector.scene.texturesEnabled = b });
-                
+                title.textContent = 'Options';
+                this._generateActionLine('Animations', this._inspector.scene.animationsEnabled, (b: boolean) => { this._inspector.scene.animationsEnabled = b });
+                this._generateActionLine('Collisions', this._inspector.scene.collisionsEnabled, (b: boolean) => { this._inspector.scene.collisionsEnabled = b });
+                this._generateActionLine('Fog', this._inspector.scene.fogEnabled, (b: boolean) => { this._inspector.scene.fogEnabled = b });
+                this._generateActionLine('Lens flares', this._inspector.scene.lensFlaresEnabled, (b: boolean) => { this._inspector.scene.lensFlaresEnabled = b });
+                this._generateActionLine('Lights', this._inspector.scene.lightsEnabled, (b: boolean) => { this._inspector.scene.lightsEnabled = b });
+                this._generateActionLine('Particles', this._inspector.scene.particlesEnabled, (b: boolean) => { this._inspector.scene.particlesEnabled = b });
+                this._generateActionLine('Post-processes', this._inspector.scene.postProcessesEnabled, (b: boolean) => { this._inspector.scene.postProcessesEnabled = b });
+                this._generateActionLine('Probes', this._inspector.scene.probesEnabled, (b: boolean) => { this._inspector.scene.probesEnabled = b });
+                this._generateActionLine('Procedural textures', this._inspector.scene.proceduralTexturesEnabled, (b: boolean) => { this._inspector.scene.proceduralTexturesEnabled = b });
+                this._generateActionLine('Render targets', this._inspector.scene.renderTargetsEnabled, (b: boolean) => { this._inspector.scene.renderTargetsEnabled = b });
+                this._generateActionLine('Shadows', this._inspector.scene.shadowsEnabled, (b: boolean) => { this._inspector.scene.shadowsEnabled = b });
+                this._generateActionLine('Skeletons', this._inspector.scene.skeletonsEnabled, (b: boolean) => { this._inspector.scene.skeletonsEnabled = b });
+                this._generateActionLine('Sprites', this._inspector.scene.spritesEnabled, (b: boolean) => { this._inspector.scene.spritesEnabled = b });
+                this._generateActionLine('Textures', this._inspector.scene.texturesEnabled, (b: boolean) => { this._inspector.scene.texturesEnabled = b });
+
                 // Audio
                 title = Helpers.CreateDiv('actions-title', this._actions);
-                title.textContent         = 'Audio'; 
-                let headphones            = Helpers.CreateDiv('action-radio', this._actions);
-                let normalSpeaker         = Helpers.CreateDiv('action-radio', this._actions);
-                this._generateActionLine('Disable audio', !this._inspector.scene.audioEnabled, (b:boolean) => {this._inspector.scene.audioEnabled = !b });
-                headphones.textContent    = 'Headphones';
-                normalSpeaker.textContent = 'Normal speakers';                
+                title.textContent = 'Audio';
+                let headphones = Helpers.CreateDiv('action-radio', this._actions);
+                let normalSpeaker = Helpers.CreateDiv('action-radio', this._actions);
+                this._generateActionLine('Disable audio', !this._inspector.scene.audioEnabled, (b: boolean) => { this._inspector.scene.audioEnabled = !b });
+                headphones.textContent = 'Headphones';
+                normalSpeaker.textContent = 'Normal speakers';
                 this._generateRadioAction([headphones, normalSpeaker]);
                 if (this._inspector.scene.headphone) {
                     headphones.classList.add('active');
                 } else {
                     normalSpeaker.classList.add('active');
                 }
-                headphones.addEventListener('click', () => {this._inspector.scene.headphone = true;});
-                normalSpeaker.addEventListener('click', () => {this._inspector.scene.headphone = false;});
-                
+                headphones.addEventListener('click', () => { this._inspector.scene.headphone = true; });
+                normalSpeaker.addEventListener('click', () => { this._inspector.scene.headphone = false; });
+
                 // Viewers
                 title = Helpers.CreateDiv('actions-title', this._actions);
                 title.textContent = 'Viewer';
-                this._generateActionLine('Skeletons', false, (b:boolean) => {
+                this._generateActionLine('Skeletons', false, (b: boolean) => {
                     if (b) {
                         for (var index = 0; index < this._inspector.scene.meshes.length; index++) {
                             var mesh = this._inspector.scene.meshes[index];
@@ -141,17 +142,17 @@ module INSPECTOR {
                         }
                         this._skeletonViewers = [];
                     }
-                });                
-            }            
+                });
+            }
         }
 
         /** Overrides super.dispose */
         public dispose() {
             this._detailsPanel.dispose();
         }
-        
+
         /** generates a div which correspond to an option that can be activated/deactivated */
-        private _generateActionLine(name:string, initValue:boolean, action:(b:boolean) => void) {
+        private _generateActionLine(name: string, initValue: boolean, action: (b: boolean) => void) {
             let div = Helpers.CreateDiv('scene-actions', this._actions);
             div.textContent = name;
             div.classList.add('action');
@@ -159,9 +160,9 @@ module INSPECTOR {
                 div.classList.add('active');
             }
             div.addEventListener('click', (e) => {
-                div.classList.toggle('active');      
+                div.classList.toggle('active');
                 let isActivated = div.classList.contains('active');
-                action(isActivated);          
+                action(isActivated);
             })
         }
 
@@ -169,7 +170,7 @@ module INSPECTOR {
          * Add a click action for all given elements : 
          * the clicked element is set as active, all others elements are deactivated
          */
-        private _generateRadioAction(arr:Array<HTMLElement>) {
+        private _generateRadioAction(arr: Array<HTMLElement>) {
             let active = (elem: HTMLElement, evt: any) => {
                 for (let e of arr) {
                     e.classList.remove('active');

+ 8 - 0
inspector/src/tree/TreeItem.ts

@@ -82,6 +82,14 @@ module INSPECTOR {
         protected _build() {
             this._div.className = 'line';
 
+            // special class for transform node ONLY
+            if (this.adapter instanceof MeshAdapter) {
+                let obj = this.adapter.object;
+                if (obj instanceof BABYLON.TransformNode && !(obj instanceof BABYLON.AbstractMesh)) {
+                    this._div.className += ' transformNode';
+                }
+            }
+
 
             for (let tool of this._tools) {
                 this._div.appendChild(tool.toHtml());

+ 24 - 284
inspector/test/index.js

@@ -35,301 +35,41 @@ var Test = (function () {
     Test.prototype._initScene = function () {
         var scene = new BABYLON.Scene(this.engine);
         var canvas = scene.getEngine().getRenderingCanvas();
-        var light = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), scene);
 
-        var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, 1.0, 110, new BABYLON.Vector3(0, -20, 0), scene);
-        camera.attachControl(canvas, true);
 
-        var camera1 = new BABYLON.ArcRotateCamera("Camera1", 1.58, 1.2, 110, BABYLON.Vector3.Zero(), scene);
-        var camera2 = new BABYLON.ArcRotateCamera("Camera2", Math.PI / 3, .8, 40, BABYLON.Vector3.Zero(), scene);
-        var camera3 = new BABYLON.ArcRotateCamera("Camera3", -Math.PI / 5, 1.0, 70, BABYLON.Vector3.Zero(), scene);
-        var camera4 = new BABYLON.ArcRotateCamera("Camera4", -Math.PI / 6, 1.3, 110, BABYLON.Vector3.Zero(), scene);
+        var sceneRoot = new BABYLON.TransformNode("abstractmesh");
 
-        camera1.layerMask = 2;
-        camera2.layerMask = 2;
-        camera3.layerMask = 2;
-        camera4.layerMask = 2;
-        /*
-            camera1.parent = camera;
-            camera2.parent = camera;
-            camera3.parent = camera;
-            camera4.parent = camera;
-        */
+        var tn = new BABYLON.TransformNode("transform node");
 
-        //Sounds
-        var jump = new BABYLON.Sound("Jump", "test/jump.wav", scene);
-        var explosion = new BABYLON.Sound("Explosion", "test/explosion.wav", scene);
-        jump.setVolume(0.1);
-        window.addEventListener("keydown", function (evt) {
-            if (evt.keyCode === 32) {
-                jump.play();
-            }
-        });
-
-        // Skybox
-        var skybox = BABYLON.Mesh.CreateBox("skyBox", 500.0, scene);
-        var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
-        skyboxMaterial.backFaceCulling = false;
-        skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("/playground/textures/TropicalSunnyDay", scene);
-        skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
-        skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
-        skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
-        skyboxMaterial.disableLighting = true;
-        skybox.material = skyboxMaterial;
-
-        var sphere1 = BABYLON.Mesh.CreateSphere("Sphere1", 10.0, 9.0, scene);
-        var sphere2 = BABYLON.Mesh.CreateSphere("Sphere2", 2.0, 9.0, scene);//Only two segments
-        var sphere3 = BABYLON.Mesh.CreateSphere("Sphere3", 10.0, 9.0, scene);
-        var sphere4 = BABYLON.Mesh.CreateSphere("Sphere4", 10.0, 9.0, scene);
-        var sphere5 = BABYLON.Mesh.CreateSphere("Sphere5", 10.0, 9.0, scene);
-        var sphere6 = BABYLON.Mesh.CreateSphere("Sphere6", 10.0, 9.0, scene);
-
-        sphere1.position.x = 40;
-        sphere2.position.x = 25;
-        sphere3.position.x = 10;
-        sphere4.position.x = -5;
-        sphere5.position.x = -20;
-        sphere6.position.x = -35;
-
-        var rt1 = new BABYLON.RenderTargetTexture("depth", 1024, scene, true, true);
-        scene.customRenderTargets.push(rt1);
-        rt1.activeCamera = camera1;
-        rt1.renderList = scene.meshes;
-
-        var rt2 = new BABYLON.RenderTargetTexture("depth", 1024, scene, true, true);
-        scene.customRenderTargets.push(rt2);
-        rt2.activeCamera = camera2;
-        rt2.renderList = scene.meshes;
-
-        var rt3 = new BABYLON.RenderTargetTexture("depth", 1024, scene, true, true);
-        scene.customRenderTargets.push(rt3);
-        rt3.activeCamera = camera3;
-        rt3.renderList = scene.meshes;
-
-        var rt4 = new BABYLON.RenderTargetTexture("depth", 1024, scene, true, true);
-        scene.customRenderTargets.push(rt4);
-        rt4.activeCamera = camera4;
-        rt4.renderList = scene.meshes;
-
-        var mon1 = BABYLON.Mesh.CreatePlane("plane", 5, scene);
-        mon1.position = new BABYLON.Vector3(-8.8, -7.8, 25)
-        // mon1.showBoundingBox = true;
-        var mon1mat = new BABYLON.StandardMaterial("texturePlane", scene);
-        mon1mat.diffuseTexture = rt1;
-        mon1.material = mon1mat;
-        mon1.parent = camera;
-        mon1.layerMask = 1;
-
-        var mon2 = BABYLON.Mesh.CreatePlane("plane", 5, scene);
-        mon2.position = new BABYLON.Vector3(-2.9, -7.8, 25)
-        // mon2.showBoundingBox = true;
-        var mon2mat = new BABYLON.StandardMaterial("texturePlane", scene);
-        mon2mat.diffuseTexture = rt2;
-        mon2.material = mon2mat;
-        mon2.parent = camera;
-        mon2.layerMask = 1;
-
-        var mon3 = BABYLON.Mesh.CreatePlane("plane", 5, scene);
-        mon3.position = new BABYLON.Vector3(2.9, -7.8, 25)
-        // mon3.showBoundingBox = true;
-        var mon3mat = new BABYLON.StandardMaterial("texturePlane", scene);
-        mon3mat.diffuseTexture = rt3;
-        mon3.material = mon3mat;
-        mon3.parent = camera;
-        mon3.layerMask = 1;
-
-
-        var mon4 = BABYLON.Mesh.CreatePlane("plane", 5, scene);
-        mon4.position = new BABYLON.Vector3(8.8, -7.8, 25)
-        // mon4.showBoundingBox = true;
-        var mon4mat = new BABYLON.StandardMaterial("texturePlane", scene);
-        mon4mat.diffuseTexture = rt4;
-        mon4.material = mon4mat;
-        mon4.parent = camera;
-        mon4.layerMask = 1;
-
-
-        var butback = BABYLON.MeshBuilder.CreatePlane("plane", { width: 25, height: 6 }, scene);
-        butback.position = new BABYLON.Vector3(0, -8.2, 26)
-        // butback.showBoundingBox = true;
-        var butbackmat = new BABYLON.StandardMaterial("texturePlane", scene);
-        butbackmat.diffuseColor = BABYLON.Color3.Black();
-        butback.material = butbackmat;
-        butback.parent = camera;
-        butback.layerMask = 1;
-
-        var plane = BABYLON.Mesh.CreatePlane("plane", 120, scene);
-        plane.position.y = -5;
-        plane.rotation.x = Math.PI / 2;
-
-        var materialSphere1 = new BABYLON.StandardMaterial("texture1", scene);
-        materialSphere1.wireframe = true;
-
-        //Creation of a red material with alpha
-        var materialSphere2 = new BABYLON.StandardMaterial("texture2", scene);
-        materialSphere2.diffuseColor = new BABYLON.Color3(1, 0, 0); //Red
-        materialSphere2.alpha = 0.3;
-
-        //Creation of a material with an image texture
-        var materialSphere3 = new BABYLON.StandardMaterial("texture3", scene);
-        materialSphere3.diffuseTexture = new BABYLON.Texture("/playground/textures/amiga.jpg", scene);
-
-        //Creation of a material with translated texture
-        var materialSphere4 = new BABYLON.StandardMaterial("texture4", scene);
-        materialSphere4.diffuseTexture = new BABYLON.Texture("/playground/textures/floor.png", scene);
-        materialSphere4.diffuseTexture.vOffset = 0.1;//Vertical offset of 10%
-        materialSphere4.diffuseTexture.uOffset = 0.4;//Horizontal offset of 40%
-
-        //Creation of a material with an alpha texture
-        var materialSphere5 = new BABYLON.StandardMaterial("texture5", scene);
-        materialSphere5.diffuseTexture = new BABYLON.Texture("/playground/textures/rock.png", scene);
-        materialSphere5.diffuseTexture.hasAlpha = true;//Has an alpha
-
-        //Creation of a material and show all the faces
-        var materialSphere6 = new BABYLON.StandardMaterial("texture6", scene);
-        materialSphere6.diffuseTexture = new BABYLON.Texture("/playground/textures/grass.png", scene);
-        materialSphere6.diffuseTexture.hasAlpha = true;//Have an alpha
-        materialSphere6.backFaceCulling = false;//Show all the faces of the element
-
-        //Creation of a repeated textured material
-        var materialPlane = new BABYLON.StandardMaterial("texturePlane", scene);
-        materialPlane.diffuseTexture = new BABYLON.Texture("/playground/textures/mixMap.png", scene);
-        materialPlane.diffuseTexture.uScale = 5.0;
-        materialPlane.diffuseTexture.vScale = 5.0;
-        materialPlane.backFaceCulling = false;
-
-        //Apply the materials to meshes
-        sphere1.material = materialSphere1;
-        sphere2.material = materialSphere2;
+        // Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
+        var ground = BABYLON.Mesh.CreateGround("node_damagedHelmet_-6514", 6, 6, 2, scene);
+        ground.parent = tn;
 
-        sphere3.material = materialSphere3;
-        sphere4.material = materialSphere4;
+        let num = 5;
+        let angStep = 6.283185307 / num;
+        let rad = 2;
+        let p = sceneRoot;
+        for (let i = 0; i < num; i++) {
+            // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
+            let sphere = BABYLON.Mesh.CreateSphere(`sphere${i}`, 16, 2, scene);
 
-        sphere5.material = materialSphere5;
-        sphere6.material = materialSphere6;
-
-        plane.material = materialPlane;
-
-        new BABYLON.Mesh('mesh_without_geometry', scene);
-
-
-
-        var d = 50;
-        var cubes = new Array();
-        for (var i = 0; i < 360; i += 20) {
-            var r = BABYLON.Tools.ToRadians(i);
-            var b = BABYLON.Mesh.CreateBox("Box #" + i / 20, 5, scene, false);
-            b.position.x = Math.cos(r) * d;
-            b.position.z = Math.sin(r) * d;
-            cubes.push(b);
+            // Move the sphere upward 1/2 its height        
+            sphere.position.y = 0.2;
+            sphere.position.x = Math.sin(i * angStep) * rad;
+            sphere.position.z = Math.cos(i * angStep) * rad;
+            sphere.parent = p;
+            p = sphere;
         }
 
-        scene.getMeshByName("Box #6").scaling.x = 2;
-
-        //Other meshes, to contrôl mesh hierarchy
-        var box1 = BABYLON.MeshBuilder.CreateBox("box1", {size: 1}, scene);
-
-        var box2 = BABYLON.MeshBuilder.CreateBox("box2", {size: 1}, scene);
-        box2.position.x = 1.5;
-        box2.parent = box1;
-
-        var box3 = BABYLON.MeshBuilder.CreateBox("box3", {size: 1}, scene);
-        box3.position.x = 1.5;
-        box3.parent = box2;
-
-        var box4 = BABYLON.MeshBuilder.CreateBox("box4", {size: 1}, scene);
-        box4.position.x = 1.5;
-        box4.parent = box3;
-
-        window.addEventListener("keydown", function (evt) {
-            sphere1.dispose();
-            var sphere7 = BABYLON.Mesh.CreateSphere("Sphere7", 10.0, 9.0, scene);
-            sphere7.position.x = 40;
+        let t = 0;
+        scene.registerBeforeRender(() => {
+            ground.rotation.y += 0.01;
+            ground.position.y = Math.cos(t += 0.01);
         });
 
-        var sphere_1 = BABYLON.Mesh.CreateSphere("_sphere_1", 16, 2, scene);
-
-        var assets_mesh = new BABYLON.AbstractMesh("assets_mesh", scene);
-        var sphere_2 = BABYLON.Mesh.CreateSphere("_sphere_2", 3, 2, scene);
-        var sphere_3 = BABYLON.Mesh.CreateSphere("_sphere_3", 2, 2, scene);
-        var scene_mesh = new BABYLON.AbstractMesh;
-        scene_mesh.name="scene_mesh";
-    
-        sphere_1.parent = assets_mesh;
-        sphere_2.parent = assets_mesh;
-        sphere_3.parent = assets_mesh;
-
-        for (var i=0; i<10 ; i++){
-            var inst = sphere_1.createInstance("C_" + i + "clone");
-            inst.isVisible = true;
-            inst.setEnabled = true;
-            inst.parent = scene_mesh;
-            inst.position.x = i*2;
-            inst.refreshBoundingInfo();
-            inst.computeWorldMatrix();
-        }
-
-        // to test reflection prob texture handling
-        var probe = new BABYLON.ReflectionProbe("probe", 512, scene);
-        probe.renderList.push(sphere1);
-
-        // gui
-        var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
-
-        var picker = new BABYLON.GUI.ColorPicker();
-        picker.height = "150px";
-        picker.width = "150px";
-        picker.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
-
-        var checkbox = new BABYLON.GUI.Checkbox();
-        checkbox.width = "20px";
-        checkbox.height = "20px";
-
-        var slider = new BABYLON.GUI.Slider();
-        slider.minimum = 0;
-        slider.maximum = 2 * Math.PI;
-        slider.value = 0;
-        slider.height = "20px";
-        slider.width = "200px";
-
-        var line = new BABYLON.GUI.Line();
-        line.x1 = 10;
-        line.y1 = 10;
-        line.x2 = 1000;
-        line.y2 = 500;
-
-        var panel = new BABYLON.GUI.StackPanel();    
-
-        var button = BABYLON.GUI.Button.CreateSimpleButton("but", "Click Me");
-        button.width = 0.2;
-        button.height = "40px";
-        button.color = "white";
-        button.background = "green";
-        panel.addControl(button);     
-
-        var button2 = BABYLON.GUI.Button.CreateSimpleButton("but2", "Click Me also!");
-        button2.width = 0.2;
-        button2.height = "40px";
-        button2.color = "white";
-        button2.background = "green";
-        panel.addControl(button2);     
-
-        var ellipse1 = new BABYLON.GUI.Ellipse();
-        ellipse1.width = "100px"
-        ellipse1.height = "100px";
-        ellipse1.color = "Orange";
-        ellipse1.thickness = 4;
-        ellipse1.background = "green";
-
+        scene.createDefaultCameraOrLight(true);
+        scene.activeCamera.attachControl(canvas);
 
-        advancedTexture.addControl(ellipse1);    
-        advancedTexture.addControl(panel);   
-        advancedTexture.addControl(picker);    
-        advancedTexture.addControl(checkbox);    
-        advancedTexture.addControl(slider);    
-        advancedTexture.addControl(line);    
-        advancedTexture.addControl(checkbox);  
-        
         this.scene = scene;
     };
     return Test;

+ 1 - 0
loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts

@@ -20,6 +20,7 @@ module BABYLON.GLTF2.Extensions {
                 loader._loadMaterialBaseProperties(context, material);
                 this._loadSpecularGlossinessProperties(loader, context, material, extension);
                 assign(material.babylonMaterial, true);
+                onComplete();
             });
         }
 

+ 22 - 16
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -10,7 +10,7 @@ module BABYLON.GLTF2.Extensions {
         /**
          * Specify the minimal delay between LODs in ms (default = 250)
          */
-        public static MinimalLODDelay = 250;
+        public Delay = 250;
 
         public get name() {
             return "MSFT_lod";
@@ -70,7 +70,7 @@ module BABYLON.GLTF2.Extensions {
                     loader._tryCatchOnError(() => {
                         this._loadNodeLOD(loader, context, nodes, index - 1, onComplete);
                     });
-                }, MSFTLOD.MinimalLODDelay);
+                }, this.Delay);
             });
         }
 
@@ -96,24 +96,30 @@ module BABYLON.GLTF2.Extensions {
 
         private _loadMaterialLOD(loader: GLTFLoader, context: string, materials: IGLTFMaterial[], index: number, assign: (babylonMaterial: Material, isNew: boolean) => void, onComplete: () => void): void {
             loader._loadMaterial(context, materials[index], (babylonMaterial, isNew) => {
-                assign(babylonMaterial, isNew);
+                if (index === materials.length - 1) {
+                    assign(babylonMaterial, isNew);
 
-                if (index === 0) {
-                    onComplete();
-                    return;
+                    // Load the next LOD when the loader is ready to render.
+                    loader._executeWhenRenderReady(() => {
+                        this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
+                    });
                 }
-
-                // Load the next LOD when the loader is ready to render and
-                // all active material textures of the current LOD are loaded.
-                loader._executeWhenRenderReady(() => {
+                else {
                     BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), () => {
-                        setTimeout(() => {
-                            loader._tryCatchOnError(() => {
-                                this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
-                            });
-                        }, MSFTLOD.MinimalLODDelay);
+                        assign(babylonMaterial, isNew);
+
+                        if (index === 0) {
+                            onComplete();
+                        }
+                        else {
+                            setTimeout(() => {
+                                loader._tryCatchOnError(() => {
+                                    this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
+                                });
+                            }, this.Delay);
+                        }
                     });
-                });
+                }
             });
         }
     }

+ 162 - 47
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -33,6 +33,11 @@ module BABYLON.GLTF2 {
         readonly BYTES_PER_ELEMENT: number;
     }
 
+    interface GLTFLoaderRequest extends XMLHttpRequest {
+        _loaded: Nullable<number>;
+        _total: Nullable<number>;
+    }
+
     export class GLTFLoader implements IGLTFLoader {
         public _gltf: IGLTF;
         public _babylonScene: Scene;
@@ -46,7 +51,7 @@ module BABYLON.GLTF2 {
         private _progressCallback: (event: ProgressEvent) => void;
         private _errorCallback: (message: string) => void;
         private _renderReady = false;
-        private _requests = new Array<XMLHttpRequest>();
+        private _requests = new Array<GLTFLoaderRequest>();
 
         private _renderReadyObservable = new Observable<GLTFLoader>();
 
@@ -127,10 +132,27 @@ module BABYLON.GLTF2 {
             });
         }
 
-        private _onProgress(event: ProgressEvent): void {
-            if (this._progressCallback) {
-                this._progressCallback(event);
+        private _onProgress(): void {
+            if (!this._progressCallback) {
+                return;
             }
+
+            let loaded = 0;
+            let total = 0;
+            for (let request of this._requests) {
+                if (!request._loaded || !request._total) {
+                    return;
+                }
+
+                loaded += request._loaded;
+                total += request._total;
+            }
+
+            this._progressCallback(new ProgressEvent("GLTFLoaderProgress", {
+                lengthComputable: true,
+                loaded: loaded,
+                total: total
+            }));
         }
 
         public _executeWhenRenderReady(func: () => void): void {
@@ -276,6 +298,10 @@ module BABYLON.GLTF2 {
                 }
             }
 
+            if (this._parent.onMeshLoaded) {
+                this._parent.onMeshLoaded(this._rootNode.babylonMesh);
+            }
+
             let nodeIndices = scene.nodes;
 
             this._traverseNodes(context, nodeIndices, (node, parentNode) => {
@@ -361,6 +387,10 @@ module BABYLON.GLTF2 {
                     this._loadNode("#/nodes/" + index, childNode);
                 }
             }
+
+            if (this._parent.onMeshLoaded) {
+                this._parent.onMeshLoaded(node.babylonMesh);
+            }
         }
 
         private _loadMesh(context: string, node: IGLTFNode, mesh: IGLTFMesh): void {
@@ -417,17 +447,7 @@ module BABYLON.GLTF2 {
                             this._parent.onMaterialLoaded(babylonMaterial);
                         }
 
-                        if (this._parent.onBeforeMaterialReadyAsync) {
-                            this._addLoaderPendingData(material);
-                            this._parent.onBeforeMaterialReadyAsync(babylonMaterial, node.babylonMesh, subMaterials[index] != null, () => {
-                                this._tryCatchOnError(() => {
-                                    subMaterials[index] = babylonMaterial;
-                                    this._removeLoaderPendingData(material);
-                                });
-                            });
-                        } else {
-                            subMaterials[index] = babylonMaterial;
-                        }
+                        subMaterials[index] = babylonMaterial;
                     });
                 }
             };
@@ -1078,26 +1098,17 @@ module BABYLON.GLTF2 {
                     throw new Error(context + ": Uri is missing");
                 }
 
-                if (GLTFUtils.IsBase64(buffer.uri)) {
-                    const data = GLTFUtils.DecodeBase64(buffer.uri);
-                    buffer.loadedData = new Uint8Array(data);
-                    onSuccess(buffer.loadedData);
+                buffer.loadedObservable = new Observable<IGLTFBuffer>();
+                buffer.loadedObservable.add(buffer => {
+                    onSuccess(buffer.loadedData!);
                     this._removePendingData(buffer);
-                }
-                else {
-
-                    buffer.loadedObservable = new Observable<IGLTFBuffer>();
-                    buffer.loadedObservable.add(buffer => {
-                        onSuccess(buffer.loadedData!);
-                        this._removePendingData(buffer);
-                    });
+                });
 
-                    this._loadUri(context, buffer.uri, data => {
-                        buffer.loadedData = data;
-                        buffer.loadedObservable!.notifyObservers(buffer);
-                        buffer.loadedObservable = undefined;
-                    });
-                }
+                this._loadUriAsync(context, buffer.uri, data => {
+                    buffer.loadedData = data;
+                    buffer.loadedObservable!.notifyObservers(buffer);
+                    buffer.loadedObservable = undefined;
+                });
             }
         }
 
@@ -1217,8 +1228,14 @@ module BABYLON.GLTF2 {
         public _removePendingData(data: any): void {
             if (!this._renderReady) {
                 if (--this._renderPendingCount === 0) {
-                    this._renderReady = true;
-                    this._onRenderReady();
+                    this._addLoaderPendingData(this);
+                    this._compileMaterialsAsync(() => {
+                        this._compileShadowGeneratorsAsync(() => {
+                            this._removeLoaderPendingData(this);
+                            this._renderReady = true;
+                            this._onRenderReady();
+                        });
+                    });
                 }
             }
 
@@ -1252,7 +1269,7 @@ module BABYLON.GLTF2 {
             this._loaderTrackers.push(tracker);
 
             this._addLoaderPendingData(tracker);
-
+            
             action();
 
             this._removeLoaderPendingData(tracker);
@@ -1469,7 +1486,7 @@ module BABYLON.GLTF2 {
                     throw new Error(context + ": Failed to find source " + texture.source);
                 }
 
-                this._loadImage("#/images/" + image.index, image, data => {
+                this._loadImageAsync("#/images/" + image.index, image, data => {
                     texture.url = URL.createObjectURL(new Blob([data], { type: image.mimeType }));
                     texture.dataReadyObservable!.notifyObservers(texture);
                     texture.dataReadyObservable = undefined;
@@ -1488,14 +1505,9 @@ module BABYLON.GLTF2 {
             return babylonTexture;
         }
 
-        private _loadImage(context: string, image: IGLTFImage, onSuccess: (data: ArrayBufferView) => void): void {
+        private _loadImageAsync(context: string, image: IGLTFImage, onSuccess: (data: ArrayBufferView) => void): void {
             if (image.uri) {
-                if (GLTFUtils.IsBase64(image.uri)) {
-                    onSuccess(new Uint8Array(GLTFUtils.DecodeBase64(image.uri)));
-                }
-                else {
-                    this._loadUri(context, image.uri, onSuccess);
-                }
+                this._loadUriAsync(context, image.uri, onSuccess);
             }
             else {
                 const bufferView = GLTFLoader._GetProperty(this._gltf.bufferViews, image.bufferView);
@@ -1507,7 +1519,12 @@ module BABYLON.GLTF2 {
             }
         }
 
-        public _loadUri(context: string, uri: string, onSuccess: (data: ArrayBufferView) => void): void {
+        public _loadUriAsync(context: string, uri: string, onSuccess: (data: ArrayBufferView) => void): void {
+            if (GLTFUtils.IsBase64(uri)) {
+                onSuccess(new Uint8Array(GLTFUtils.DecodeBase64(uri)));
+                return;
+            }
+
             if (!GLTFUtils.ValidateUri(uri)) {
                 throw new Error(context + ": Uri '" + uri + "' is invalid");
             }
@@ -1518,15 +1535,21 @@ module BABYLON.GLTF2 {
                 });
             }, event => {
                 this._tryCatchOnError(() => {
-                    this._onProgress(event);
+                    if (request && !this._renderReady) {
+                        request._loaded = event.loaded;
+                        request._total = event.total;
+                        this._onProgress();
+                    }
                 });
             }, this._babylonScene.database, true, request => {
                 this._tryCatchOnError(() => {
                     throw new Error(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""));
                 });
-            });
+            }) as GLTFLoaderRequest;
 
             if (request) {
+                request._loaded = null;
+                request._total = null;
                 this._requests.push(request);
             }
         }
@@ -1630,6 +1653,98 @@ module BABYLON.GLTF2 {
 
             return 0;
         }
+
+        private _compileMaterialAsync(babylonMaterial: Material, babylonMesh: AbstractMesh, onSuccess: () => void): void {
+            if (!this._parent.compileMaterials) {
+                onSuccess();
+                return;
+            }
+
+            if (this._parent.useClipPlane) {
+                babylonMaterial.forceCompilation(babylonMesh, () => {
+                    babylonMaterial.forceCompilation(babylonMesh, () => {
+                        this._tryCatchOnError(onSuccess);
+                    }, { clipPlane: true });
+                });
+            }
+            else {
+                babylonMaterial.forceCompilation(babylonMesh, () => {
+                    this._tryCatchOnError(onSuccess);
+                });
+            }
+        }
+
+        private _compileMaterialsAsync(onSuccess: () => void): void {
+            if (!this._parent.compileMaterials || !this._gltf.materials) {
+                onSuccess();
+                return;
+            }
+
+            let meshes = this._getMeshes();
+
+            let remaining = 0;
+            for (let mesh of meshes) {
+                if (mesh.material instanceof MultiMaterial) {
+                    for (let subMaterial of mesh.material.subMaterials) {
+                        if (subMaterial) {
+                            remaining++;
+                        }
+                    }
+                }
+            }
+
+            if (remaining === 0) {
+                onSuccess();
+                return;
+            }
+
+            for (let mesh of meshes) {
+                if (mesh.material instanceof MultiMaterial) {
+                    for (let subMaterial of mesh.material.subMaterials) {
+                        if (subMaterial) {
+                            this._compileMaterialAsync(subMaterial, mesh, () => {
+                                if (--remaining === 0) {
+                                    onSuccess();
+                                }
+                            });
+                        }
+                    }
+                }
+            }
+        }
+
+        private _compileShadowGeneratorsAsync(onSuccess: () => void): void {
+            if (!this._parent.compileShadowGenerators) {
+                onSuccess();
+                return;
+            }
+
+            let lights = this._babylonScene.lights;
+
+            let remaining = 0;
+            for (let light of lights) {
+                let generator = light.getShadowGenerator();
+                if (generator) {
+                    remaining++;
+                }
+            }
+
+            if (remaining === 0) {
+                onSuccess();
+                return;
+            }
+
+            for (let light of lights) {
+                let generator = light.getShadowGenerator();
+                if (generator) {
+                    generator.forceCompilation(() => {
+                        if (--remaining === 0) {
+                            this._tryCatchOnError(onSuccess);
+                        }
+                    });
+                }
+            }
+        }
     }
 
     BABYLON.GLTFFileLoader.CreateGLTFLoaderV2 = parent => new GLTFLoader(parent);

+ 7 - 8
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -31,20 +31,19 @@ module BABYLON {
         public onParsed: (data: IGLTFLoaderData) => void;
 
         // V1 options
-        public static HomogeneousCoordinates: boolean = false;
-        public static IncrementalLoading: boolean = true;
+        public static HomogeneousCoordinates = false;
+        public static IncrementalLoading = true;
 
         // V2 options
-        public coordinateSystemMode: GLTFLoaderCoordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
+        public coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
+        public compileMaterials = false;
+        public compileShadowGenerators = false;
+        public useClipPlane = false;
+        public onMeshLoaded: (mesh: AbstractMesh) => void;
         public onTextureLoaded: (texture: BaseTexture) => void;
         public onMaterialLoaded: (material: Material) => void;
 
         /**
-         * Let the user decides if he needs to process the material (like precompilation) before affecting it to meshes
-         */
-        public onBeforeMaterialReadyAsync: (material: Material, targetMesh: AbstractMesh, isLOD: boolean, callback: () => void) => void;
-
-        /**
          * Raised when the asset is completely loaded, just before the loader is disposed.
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete just after onSuccess.

+ 1 - 1
package.json

@@ -8,7 +8,7 @@
     ],
     "name": "babylonjs",
     "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-    "version": "3.1.0-beta1.1.1",
+    "version": "3.1.0-beta3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
sandbox/index.css

@@ -56,7 +56,7 @@ a {
     width: 100%;
     height: 100%;
     top: 0;
-    margin-bottom: 70px;
+    margin-bottom: 65px;
     touch-action: none;
     -ms-touch-action: none;
 }

+ 2 - 7
sandbox/index.js

@@ -38,13 +38,8 @@ if (BABYLON.Engine.isSupported()) {
         if (plugin.name !== "gltf") {
             return;
         }
-        plugin.onBeforeMaterialReadyAsync = function(material, mesh, isLOD, callback) {
-            if (!isLOD) {
-                callback();
-                return;
-            }
-            material.forceCompilation(mesh, callback);
-        }
+
+        plugin.compileMaterials = true;
     });
 
     // Resize

+ 0 - 5
src/Audio/babylon.sound.ts

@@ -563,11 +563,6 @@ module BABYLON {
 
         private _onRegisterAfterWorldMatrixUpdate(connectedMesh: AbstractMesh): void {
             let boundingInfo = connectedMesh.getBoundingInfo();
-
-            if (!boundingInfo) {
-                return;
-            }
-
             this.setPosition(boundingInfo.boundingSphere.centerWorld);
             if (Engine.audioEngine.canUseWebAudio && this._isDirectional && this.isPlaying) {
                 this._updateDirection();

+ 1 - 1
src/Behaviors/Cameras/babylon.bouncingBehavior.ts

@@ -64,7 +64,7 @@ module BABYLON {
 					}
 
 					mesh.computeWorldMatrix(true);
-					let diagonal = (<BoundingInfo>mesh.getBoundingInfo()).diagonalLength;
+					let diagonal = mesh.getBoundingInfo().diagonalLength;
 
 					this.lowerRadiusTransitionRange = diagonal * 0.05;
 					this.upperRadiusTransitionRange = diagonal * 0.05;

+ 1 - 1
src/Behaviors/Cameras/babylon.framingBehavior.ts

@@ -224,7 +224,7 @@ module BABYLON {
 		public zoomOnMesh(mesh: AbstractMesh, focusOnOriginXZ: boolean = false, onAnimationEnd: Nullable<() => void> = null): void {
 			mesh.computeWorldMatrix(true);
 
-			let boundingBox = (<BoundingInfo>mesh.getBoundingInfo()).boundingBox;
+			let boundingBox = mesh.getBoundingInfo().boundingBox;
 			this.zoomOnBoundingInfo(boundingBox.minimumWorld, boundingBox.maximumWorld, focusOnOriginXZ, onAnimationEnd);
 		}
 

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 47 - 24
src/Cameras/VR/babylon.vrExperienceHelper.ts


+ 2 - 0
src/Cameras/VR/babylon.webVRCamera.ts

@@ -35,6 +35,8 @@ module BABYLON {
         displayName?: string; //if there are more than one VRDisplays.
         controllerMeshes?: boolean; // should the native controller meshes be initialized
         defaultLightingOnControllers?: boolean; // creating a default HemiLight only on controllers
+        useCustomVRButton?: boolean; // if you don't want to use the default VR button of the helper
+        customVRButton?: HTMLButtonElement; //if you'd like to provide your own button to the VRHelper
     }
 
     export class WebVRFreeCamera extends FreeCamera implements PoseControlled {

+ 2 - 2
src/Collisions/babylon.collisionCoordinator.ts

@@ -139,7 +139,7 @@ module BABYLON {
             var submeshes: Array<SerializedSubMesh> = [];
             if (mesh.subMeshes) {
                 submeshes = mesh.subMeshes.map(function (sm, idx) {
-                    let boundingInfo = <BoundingInfo>sm.getBoundingInfo();
+                    let boundingInfo = sm.getBoundingInfo();
 
                     return {
                         position: idx,
@@ -165,7 +165,7 @@ module BABYLON {
                 geometryId = geometry ? geometry.id : null;
             }
 
-            let boundingInfo = <BoundingInfo>mesh.getBoundingInfo();
+            let boundingInfo = mesh.getBoundingInfo();
 
             return {
                 uniqueId: mesh.uniqueId,

+ 2 - 2
src/Culling/Octrees/babylon.octree.ts

@@ -97,14 +97,14 @@
 
         public static CreationFuncForMeshes = (entry: AbstractMesh, block: OctreeBlock<AbstractMesh>): void => {
             let boundingInfo = entry.getBoundingInfo();
-            if (!entry.isBlocked && boundingInfo && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+            if (!entry.isBlocked && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
                 block.entries.push(entry);
             }
         }
 
         public static CreationFuncForSubMeshes = (entry: SubMesh, block: OctreeBlock<SubMesh>): void => {
             let boundingInfo = entry.getBoundingInfo();
-            if (boundingInfo && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
+            if (boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
                 block.entries.push(entry);
             }
         }

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

@@ -531,7 +531,7 @@
         }
 
         public static get Version(): string {
-            return "3.1-beta-2";
+            return "3.1-beta-3";
         }
 
         // Updatable statics so stick with vars here

+ 24 - 10
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -14,7 +14,7 @@
 
         recreateShadowMap(): void;
 
-        forceCompilation(onCompiled: (generator: ShadowGenerator) => void, options?: { useInstances: boolean }): void;
+        forceCompilation(onCompiled?: (generator: ShadowGenerator) => void, options?: Partial<{ useInstances: boolean }>): void;
 
         serialize(): any;
         dispose(): void;
@@ -602,31 +602,47 @@
         /**
          * Force shader compilation including textures ready check
          */
-        public forceCompilation(onCompiled: (generator: ShadowGenerator) => void, options?: { useInstances: boolean }): void {
+        public forceCompilation(onCompiled?: (generator: ShadowGenerator) => void, options?: Partial<{ useInstances: boolean }>): void {
+            let localOptions = {
+                useInstances: false,
+                ...options
+            };
+
             let shadowMap = this.getShadowMap();
             if (!shadowMap) {
+                if (onCompiled) {
+                    onCompiled(this);
+                }
                 return;
             }
 
-            var subMeshes = new Array<SubMesh>();
-            var currentIndex = 0;
-
             let renderList = shadowMap.renderList;
-
             if (!renderList) {
+                if (onCompiled) {
+                    onCompiled(this);
+                }
                 return;
             }
 
+            var subMeshes = new Array<SubMesh>();
             for (var mesh of renderList) {
                 subMeshes.push(...mesh.subMeshes);
             }
+            if (subMeshes.length === 0) {
+                if (onCompiled) {
+                    onCompiled(this);
+                }
+                return;
+            }
+
+            var currentIndex = 0;
 
             var checkReady = () => {
                 if (!this._scene || !this._scene.getEngine()) {
                     return;
                 }
 
-                while (this.isReady(subMeshes[currentIndex], options ? options.useInstances : false)) {
+                while (this.isReady(subMeshes[currentIndex], localOptions.useInstances)) {
                     currentIndex++;
                     if (currentIndex >= subMeshes.length) {
                         if (onCompiled) {
@@ -638,9 +654,7 @@
                 setTimeout(checkReady, 16);
             };
 
-            if (subMeshes.length > 0) {
-                checkReady();
-            }
+            checkReady();
         }
 
         /**

+ 0 - 5
src/Lights/babylon.directionalLight.ts

@@ -118,11 +118,6 @@
                     }
 
                     var boundingInfo = mesh.getBoundingInfo();
-
-                    if (!boundingInfo) {
-                        continue;
-                    }
-
                     var boundingBox = boundingInfo.boundingBox;
 
                     for (var index = 0; index < boundingBox.vectorsWorld.length; index++) {

+ 15 - 0
src/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -434,6 +434,14 @@
                     }
                 }
 
+                // Transform nodes
+                if (parsedData.transformNodes !== undefined && parsedData.transformNodes !== null) {
+                    for (index = 0, cache = parsedData.transformNodes.length; index < cache; index++) {
+                        var parsedTransformNode = parsedData.transformNodes[index];
+                        TransformNode.Parse(parsedTransformNode, scene, rootUrl);
+                    }
+                }                
+
                 // Meshes
                 if (parsedData.meshes !== undefined && parsedData.meshes !== null) {
                     for (index = 0, cache = parsedData.meshes.length; index < cache; index++) {
@@ -498,6 +506,13 @@
                 loadedSounds = [];
 
                 // Connect parents & children and parse actions
+                for (index = 0, cache = scene.transformNodes.length; index < cache; index++) {
+                    var transformNode = scene.transformNodes[index];
+                    if (transformNode._waitingParentId) {
+                        transformNode.parent = scene.getLastEntryByID(transformNode._waitingParentId);
+                        transformNode._waitingParentId = null;
+                    }
+                }                
                 for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                     var mesh = scene.meshes[index];
                     if (mesh._waitingParentId) {

+ 9 - 3
src/Materials/babylon.material.ts

@@ -565,7 +565,13 @@
         /**
          * Force shader compilation including textures ready check
          */
-        public forceCompilation(mesh: AbstractMesh, onCompiled: (material: Material) => void, options?: { alphaTest: boolean, clipPlane: boolean }): void {
+        public forceCompilation(mesh: AbstractMesh, onCompiled?: (material: Material) => void, options?: Partial<{ alphaTest: Nullable<boolean>, clipPlane: boolean }>): void {
+            let localOptions = {
+                alphaTest: null,
+                clipPlane: false,
+                ...options
+            };
+
             var subMesh = new BaseSubMesh();
             var scene = this.getScene();
             var engine = scene.getEngine();
@@ -582,9 +588,9 @@
                 var alphaTestState = engine.getAlphaTesting();
                 var clipPlaneState = scene.clipPlane;
 
-                engine.setAlphaTesting(options ? options.alphaTest : this.needAlphaTesting());
+                engine.setAlphaTesting(localOptions.alphaTest || (!this.needAlphaBlendingForMesh(mesh) && this.needAlphaTesting()));
 
-                if (options && options.clipPlane) {
+                if (localOptions.clipPlane) {
                     scene.clipPlane = new Plane(0, 0, 0, 1);
                 }
 

+ 66 - 68
src/Mesh/babylon.abstractMesh.ts

@@ -42,8 +42,10 @@
             Y: 1,
             Z: 1
         };
-        private _facetDepthSort: boolean = false;                           // is the facet depth sort enabled
-        private _originalIndices: IndicesArray;                             // copy of the original indices array
+      
+        private _facetDepthSort: boolean = false;                           // is the facet depth sort to be computed
+        private _facetDepthSortEnabled: boolean = false;                    // is the facet depth sort initialized
+        private _depthSortedIndices: IndicesArray;                          // copy of the indices array to store them once sorted
         private _depthSortedFacets: {ind: number, sqDistance: number}[];    // array of depth sorted facets
         private _facetDepthSortFunction: (f1: {ind: number, sqDistance: number}, f2: {ind: number, sqDistance: number}) => number;  // facet depth sort function
         private _facetDepthSortFrom: Vector3;                               // location where to depth sort from
@@ -78,6 +80,7 @@
         /**
          * Boolean : must the facet be depth sorted on next call to `updateFacetData()` ?  
          * Works only for updatable meshes.  
+         * Doesn't work with multi-materials.  
          */
         public get mustDepthSortFacets(): boolean {
             return this._facetDepthSort;
@@ -487,7 +490,7 @@
             if (!this.subMeshes) {
                 return;
             }
-            
+
             for (var subMesh of this.subMeshes) {
                 subMesh._rebuild();
             }
@@ -571,10 +574,10 @@
             }
         }
 
-         /**
-         * Scaling property : a Vector3 depicting the mesh scaling along each local axis X, Y, Z.  
-         * Default : (1.0, 1.0, 1.0)
-         */
+        /**
+        * Scaling property : a Vector3 depicting the mesh scaling along each local axis X, Y, Z.  
+        * Default : (1.0, 1.0, 1.0)
+        */
         public get scaling(): Vector3 {
             return this._scaling;
         }
@@ -732,15 +735,17 @@
          * Returns the mesh BoundingInfo object or creates a new one and returns it if undefined.
          * Returns a BoundingInfo
          */
-        public getBoundingInfo(): Nullable<BoundingInfo> {
+        public getBoundingInfo(): BoundingInfo {
             if (this._masterMesh) {
                 return this._masterMesh.getBoundingInfo();
             }
 
             if (!this._boundingInfo) {
+                // this._boundingInfo is being created here
                 this._updateBoundingInfo();
             }
-            return this._boundingInfo;
+            // cannot be null.
+            return this._boundingInfo!;
         }
 
         /**
@@ -751,7 +756,7 @@
             let boundingVectors = this.getHierarchyBoundingVectors(includeDescendants);
             let sizeVec = boundingVectors.max.subtract(boundingVectors.min);
             let maxDimension = Math.max(sizeVec.x, sizeVec.y, sizeVec.z);
-            
+
             if (maxDimension === 0) {
                 return this;
             }
@@ -785,7 +790,7 @@
         public _activate(renderId: number): void {
             this._renderId = renderId;
         }
-   
+
         /**
          * Returns the latest update of the World matrix
          * Returns a Matrix.  
@@ -867,14 +872,14 @@
          * Return the minimum and maximum world vectors of the entire hierarchy under current mesh
          * @param includeDescendants Include bounding info from descendants as well (true by default).
          */
-        public getHierarchyBoundingVectors(includeDescendants = true): { min: Vector3, max: Vector3 }{
+        public getHierarchyBoundingVectors(includeDescendants = true): { min: Vector3, max: Vector3 } {
             this.computeWorldMatrix(true);
 
             let min: Vector3;
             let max: Vector3;
             let boundingInfo = this.getBoundingInfo();
-            
-            if (!this.subMeshes || !boundingInfo) {
+
+            if (!this.subMeshes) {
                 min = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
                 max = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
             } else {
@@ -891,7 +896,7 @@
                     childMesh.computeWorldMatrix(true);
                     let childBoundingInfo = childMesh.getBoundingInfo();
 
-                    if (childMesh.getTotalVertices() === 0 || !childBoundingInfo) {
+                    if (childMesh.getTotalVertices() === 0) {
                         continue;
                     }
                     let boundingBox = childBoundingInfo.boundingBox;
@@ -944,26 +949,6 @@
         }
 
         /**
-        * If you'd like to be called back after the mesh position, rotation or scaling has been updated.  
-        * @param func: callback function to add
-        *
-        * Returns the AbstractMesh. 
-        */
-        public registerAfterWorldMatrixUpdate(func: (mesh: AbstractMesh) => void): AbstractMesh {
-            this.onAfterWorldMatrixUpdateObservable.add(func);
-            return this;
-        }
-
-        /**
-         * Removes a registered callback function.  
-         * Returns the AbstractMesh.
-         */
-        public unregisterAfterWorldMatrixUpdate(func: (mesh: AbstractMesh) => void): AbstractMesh {
-            this.onAfterWorldMatrixUpdateObservable.removeCallback(func);
-            return this;
-        }
-
-        /**
          * Returns `true` if the mesh is within the frustum defined by the passed array of planes.  
          * A mesh is in the frustum if its bounding box intersects the frustum.  
          * Boolean returned.  
@@ -1130,10 +1115,8 @@
             let boundingInfo = this.getBoundingInfo();
 
             // Update octree
-            if (boundingInfo) {
-                var bbox = boundingInfo.boundingBox;
-                this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
-            }
+            var bbox = boundingInfo.boundingBox;
+            this._submeshesOctree.update(bbox.minimumWorld, bbox.maximumWorld, this.subMeshes);
 
             return this._submeshesOctree;
         }
@@ -1145,7 +1128,7 @@
             if (!this._positions) {
                 return this;
             }
-            
+
             // Transformation
             if (!subMesh._lastColliderWorldVertices || !subMesh._lastColliderTransformMatrix.equals(transformMatrix)) {
                 subMesh._lastColliderTransformMatrix = transformMatrix.clone();
@@ -1455,7 +1438,7 @@
             this._isDisposed = true;
 
             super.dispose();
-        } 
+        }
 
         /**
          * Adds the passed mesh as a child to the current mesh.  
@@ -1490,7 +1473,7 @@
             if (!this._facetPartitioning) {
                 this._facetPartitioning = new Array<number[]>();
             }
-            this._facetNb = ((<IndicesArray>this.getIndices()).length / 3)|0;
+            this._facetNb = ((<IndicesArray>this.getIndices()).length / 3) | 0;
             this._partitioningSubdivisions = (this._partitioningSubdivisions) ? this._partitioningSubdivisions : 10;   // default nb of partitioning subdivisions = 10
             this._partitioningBBoxRatio = (this._partitioningBBoxRatio) ? this._partitioningBBoxRatio : 1.01;          // default ratio 1.01 = the partitioning is 1% bigger than the bounding box
             for (var f = 0; f < this._facetNb; f++) {
@@ -1513,17 +1496,33 @@
             }
             var positions = this.getVerticesData(VertexBuffer.PositionKind);
             var indices = this.getIndices();
-            var indicesForComputeNormals = indices;
             var normals = this.getVerticesData(VertexBuffer.NormalKind);
             var bInfo = this.getBoundingInfo();
-            
-            if (!bInfo) {
-                return this;
-            }
 
-            if (this._facetDepthSort && !this._originalIndices) {
+            if (this._facetDepthSort && !this._facetDepthSortEnabled) {
                 // init arrays, matrix and sort function on first call
-                this._originalIndices = new Uint32Array(indices!);
+                this._facetDepthSortEnabled = true;
+                if (indices instanceof Uint16Array) {
+                    this._depthSortedIndices = new Uint16Array(indices!);
+                }
+                else if (indices instanceof Uint32Array) {
+                    this._depthSortedIndices = new Uint32Array(indices!);
+                } 
+                else {
+                    var needs32bits = false;
+                    for (var i = 0; i < indices!.length; i++) {
+                        if (indices![i] > 65535) {
+                            needs32bits = true;
+                            break;
+                        }
+                    }
+                    if (needs32bits) {
+                        this._depthSortedIndices = new Uint32Array(indices!);
+                    } 
+                    else {
+                        this._depthSortedIndices = new Uint16Array(indices!);
+                    }
+                }               
                 this._facetDepthSortFunction = function(f1, f2) {
                     return (f2.sqDistance - f1.sqDistance);
                 };
@@ -1533,7 +1532,7 @@
                 }
                 this._depthSortedFacets = [];
                 for (var f = 0; f < this._facetNb; f++) {
-                    var depthSortedFacet = {ind: f * 3, sqDistance: 0.0};
+                    var depthSortedFacet = { ind: f * 3, sqDistance: 0.0 };
                     this._depthSortedFacets.push(depthSortedFacet);
                 }
                 this._invertedMatrix = Matrix.Identity();
@@ -1561,25 +1560,25 @@
             this._facetParameters.subDiv = this._subDiv;
             this._facetParameters.ratio = this.partitioningBBoxRatio;
             this._facetParameters.depthSort = this._facetDepthSort;
-            if (this._facetDepthSort) {
+            if (this._facetDepthSort && this._facetDepthSortEnabled) {
                 this.computeWorldMatrix(true);
                 this._worldMatrix.invertToRef(this._invertedMatrix);
-                Vector3.TransformCoordinatesToRef(this._facetDepthSortFrom, this._invertedMatrix, this._facetDepthSortOrigin);   
+                Vector3.TransformCoordinatesToRef(this._facetDepthSortFrom, this._invertedMatrix, this._facetDepthSortOrigin);
                 this._facetParameters.distanceTo = this._facetDepthSortOrigin;
-                indicesForComputeNormals = this._originalIndices;
             }
             this._facetParameters.depthSortedFacets = this._depthSortedFacets;
-            VertexData.ComputeNormals(positions, indicesForComputeNormals, normals, this._facetParameters);
+            VertexData.ComputeNormals(positions, indices, normals, this._facetParameters);
 
-            if (this._facetDepthSort) {
+            if (this._facetDepthSort && this._facetDepthSortEnabled) {
                 this._depthSortedFacets.sort(this._facetDepthSortFunction);
-                for (var sorted = 0; sorted < this._facetNb; sorted++) {
-                    var sind = this._depthSortedFacets[sorted].ind;
-                    indices![sorted * 3] = this._originalIndices[sind];
-                    indices![sorted * 3 + 1] = this._originalIndices[sind + 1];
-                    indices![sorted * 3 + 2] = this._originalIndices[sind + 2];
+                var l = (this._depthSortedIndices.length / 3)|0;
+                for (var f = 0; f < l; f++) {
+                    var sind = this._depthSortedFacets[f].ind;
+                    this._depthSortedIndices[f * 3] = indices![sind];
+                    this._depthSortedIndices[f * 3 + 1] = indices![sind + 1];
+                    this._depthSortedIndices[f * 3 + 2] = indices![sind + 2];
                 }
-                this.updateIndices(indices!);
+                this.updateIndices(this._depthSortedIndices);
             }
 
             return this;
@@ -1656,10 +1655,6 @@
         public getFacetsAtLocalCoordinates(x: number, y: number, z: number): Nullable<number[]> {
             var bInfo = this.getBoundingInfo();
 
-            if (!bInfo) {
-                return null;
-            }
-
             var ox = Math.floor((x - bInfo.minimum.x * this._partitioningBBoxRatio) * this._subDiv.X * this._partitioningBBoxRatio / this._bbSize.x);
             var oy = Math.floor((y - bInfo.minimum.y * this._partitioningBBoxRatio) * this._subDiv.Y * this._partitioningBBoxRatio / this._bbSize.y);
             var oz = Math.floor((z - bInfo.minimum.z * this._partitioningBBoxRatio) * this._subDiv.Z * this._partitioningBBoxRatio / this._bbSize.z);
@@ -1768,7 +1763,7 @@
                 this._facetNormals = new Array<Vector3>();
                 this._facetPartitioning = new Array<number[]>();
                 this._facetParameters = null;
-                this._originalIndices = new Uint32Array(0);
+                this._depthSortedIndices = new Uint32Array(0);
             }
             return this;
         }
@@ -1779,7 +1774,10 @@
         public updateIndices(indices: IndicesArray): AbstractMesh {
             return this;
         }
-
+        /**
+         * The mesh Geometry. Actually used by the Mesh object.
+         * Returns a blank geometry object.
+         */
         /**
          * Creates new normals data for the mesh.
          * @param updatable.
@@ -1808,7 +1806,7 @@
             }
 
             if (this.isOcclusionQueryInProgress && this._occlusionQuery) {
-                
+
                 var isOcclusionQueryAvailable = engine.isQueryResultAvailable(this._occlusionQuery);
                 if (isOcclusionQueryAvailable) {
                     var occlusionQueryResult = engine.getQueryResult(this._occlusionQuery);

+ 1 - 7
src/Mesh/babylon.instancedMesh.ts

@@ -178,9 +178,7 @@
         public refreshBoundingInfo(): InstancedMesh {
             var meshBB = this._sourceMesh.getBoundingInfo();
 
-            if (meshBB) {
-                this._boundingInfo = new BoundingInfo(meshBB.minimum.clone(), meshBB.maximum.clone());
-            }
+            this._boundingInfo = new BoundingInfo(meshBB.minimum.clone(), meshBB.maximum.clone());
 
             this._updateBoundingInfo();
             return this;
@@ -210,10 +208,6 @@
 
             let boundingInfo = this.getBoundingInfo();
 
-            if (!boundingInfo) {
-                return this;
-            }
-
             this._currentLOD = <Mesh>this.sourceMesh.getLOD(camera, boundingInfo.boundingSphere);
 
             if (this._currentLOD === this.sourceMesh) {

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

@@ -372,10 +372,6 @@
             } else {
                 let boundingInfo = this.getBoundingInfo();
 
-                if (!boundingInfo) {
-                    return this;
-                }
-
                 bSphere =  boundingInfo.boundingSphere;
             }
 
@@ -2222,8 +2218,8 @@
 
         // Statics
         /**
-         * Returns a new Mesh object what is a deep copy of the passed mesh.   
-         * The parameter `parsedMesh` is the mesh to be copied.   
+         * Returns a new Mesh object parsed from the source provided.   
+         * The parameter `parsedMesh` is the source.   
          * The parameter `rootUrl` is a string, it's the root URL to prefix the `delayLoadingFile` property with
          */
         public static Parse(parsedMesh: any, scene: Scene, rootUrl: string): Mesh {
@@ -3178,10 +3174,6 @@
             meshes.forEach(function (mesh, index, array) {
                 let boundingInfo = mesh.getBoundingInfo();
 
-                if (!boundingInfo) {
-                    return;
-                }
-
                 let boundingBox = boundingInfo.boundingBox;
                 if (!minVector || !maxVector) {
                     minVector = boundingBox.minimumWorld;

+ 1 - 1
src/Mesh/babylon.mesh.vertexData.ts

@@ -2307,7 +2307,7 @@
             }
 
             // Loop : 1 indice triplet = 1 facet
-            var nbFaces = indices.length / 3;
+            var nbFaces = (indices.length / 3)|0;
             for (index = 0; index < nbFaces; index++) {
 
                 // get the indexes of the coordinates of each vertex of the facet

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

@@ -24,7 +24,7 @@
 
         private _mesh: AbstractMesh;
         private _renderingMesh: Mesh;
-        private _boundingInfo: Nullable<BoundingInfo>;
+        private _boundingInfo: BoundingInfo;
         private _linesIndexBuffer: Nullable<WebGLBuffer>;
         public _lastColliderWorldVertices: Nullable<Vector3[]>;
         public _trianglePlanes: Plane[];
@@ -64,7 +64,7 @@
         /**
          * Returns the submesh BoudingInfo object.  
          */
-        public getBoundingInfo(): Nullable<BoundingInfo> {
+        public getBoundingInfo(): BoundingInfo {
             if (this.IsGlobal) {
                 return this._mesh.getBoundingInfo();
             }
@@ -134,7 +134,7 @@
             var data = this._renderingMesh.getVerticesData(VertexBuffer.PositionKind);
 
             if (!data) {
-                this._boundingInfo = this._mesh._boundingInfo;
+                this._boundingInfo = this._mesh.getBoundingInfo();
                 return this;
             }
 
@@ -145,10 +145,6 @@
             if (this.indexStart === 0 && this.indexCount === indices.length) {
                 let boundingInfo = this._renderingMesh.getBoundingInfo();
 
-                if (!boundingInfo) {
-                    return this;
-                }
-
                 //the rendering mesh's bounding info can be used, it is the standard submesh for all indices.
                 extend = { minimum: boundingInfo.minimum.clone(), maximum: boundingInfo.maximum.clone() };
             } else {
@@ -161,10 +157,6 @@
         public _checkCollision(collider: Collider): boolean {
             let boundingInfo = this._renderingMesh.getBoundingInfo();
 
-            if (!boundingInfo) {
-                return false;
-            }
-
             return boundingInfo._checkCollision(collider);
         }
 

+ 122 - 0
src/Mesh/babylon.transformNode.ts

@@ -782,7 +782,129 @@ module BABYLON {
         }   
 
         protected _afterComputeWorldMatrix(): void {
+        }
 
+        /**
+        * If you'd like to be called back after the mesh position, rotation or scaling has been updated.  
+        * @param func: callback function to add
+        *
+        * Returns the TransformNode. 
+        */
+        public registerAfterWorldMatrixUpdate(func: (mesh: TransformNode) => void): TransformNode {
+            this.onAfterWorldMatrixUpdateObservable.add(func);
+            return this;
         }
+
+        /**
+         * Removes a registered callback function.  
+         * Returns the TransformNode.
+         */
+        public unregisterAfterWorldMatrixUpdate(func: (mesh: TransformNode) => void): TransformNode {
+            this.onAfterWorldMatrixUpdateObservable.removeCallback(func);
+            return this;
+        }        
+
+        public clone(name: string, newParent: Node): Nullable<TransformNode> {
+            var result = SerializationHelper.Clone(() => new TransformNode(name, this.getScene()), this);
+
+            result.name = name;
+            result.id = name;
+
+            if (newParent) {
+                result.parent = newParent;
+            }
+
+            return result;
+        }        
+
+        public serialize(serializationObject: any = null): any {
+            if (!serializationObject) {
+                serializationObject = {};
+            }
+
+            serializationObject.name = this.name;
+            serializationObject.id = this.id;
+            serializationObject.type = this.getClassName();
+
+            if (Tags && Tags.HasTags(this)) {
+                serializationObject.tags = Tags.GetTags(this);
+            }
+
+            serializationObject.position = this.position.asArray();
+
+            if (this.rotationQuaternion) {
+                serializationObject.rotationQuaternion = this.rotationQuaternion.asArray();
+            } else if (this.rotation) {
+                serializationObject.rotation = this.rotation.asArray();
+            }
+
+            serializationObject.scaling = this.scaling.asArray();
+            serializationObject.localMatrix = this.getPivotMatrix().asArray();
+
+            serializationObject.isEnabled = this.isEnabled();
+            serializationObject.infiniteDistance = this.infiniteDistance;
+
+            serializationObject.billboardMode = this.billboardMode;
+
+            // Parent
+            if (this.parent) {
+                serializationObject.parentId = this.parent.id;
+            }
+
+            // Metadata
+            if (this.metadata) {
+                serializationObject.metadata = this.metadata;
+            }
+
+            return serializationObject;
+        }
+
+        // Statics
+        /**
+         * Returns a new TransformNode object parsed from the source provided.   
+         * The parameter `parsedMesh` is the source.   
+         * The parameter `rootUrl` is a string, it's the root URL to prefix the `delayLoadingFile` property with
+         */
+        public static Parse(parsedTransformNode: any, scene: Scene, rootUrl: string): TransformNode {
+            var transformNode = new TransformNode(parsedTransformNode.name, scene);
+
+            transformNode.id = parsedTransformNode.id;
+
+            if (Tags) {
+                Tags.AddTagsTo(transformNode, parsedTransformNode.tags);
+            }
+
+            transformNode.position = Vector3.FromArray(parsedTransformNode.position);
+
+            if (parsedTransformNode.metadata !== undefined) {
+                transformNode.metadata = parsedTransformNode.metadata;
+            }
+
+            if (parsedTransformNode.rotationQuaternion) {
+                transformNode.rotationQuaternion = Quaternion.FromArray(parsedTransformNode.rotationQuaternion);
+            } else if (parsedTransformNode.rotation) {
+                transformNode.rotation = Vector3.FromArray(parsedTransformNode.rotation);
+            }
+
+            transformNode.scaling = Vector3.FromArray(parsedTransformNode.scaling);
+
+            if (parsedTransformNode.localMatrix) {
+                transformNode.setPivotMatrix(Matrix.FromArray(parsedTransformNode.localMatrix));
+            } else if (parsedTransformNode.pivotMatrix) {
+                transformNode.setPivotMatrix(Matrix.FromArray(parsedTransformNode.pivotMatrix));
+            }
+
+            transformNode.setEnabled(parsedTransformNode.isEnabled);
+            transformNode.infiniteDistance = parsedTransformNode.infiniteDistance;
+
+            transformNode.billboardMode = parsedTransformNode.billboardMode;
+
+            // Parent
+            if (parsedTransformNode.parentId) {
+                transformNode._waitingParentId = parsedTransformNode.parentId;
+            }
+         
+            return transformNode;
+        }        
     }
 }

+ 4 - 6
src/Particles/babylon.solidParticleSystem.ts

@@ -61,8 +61,8 @@
             private _normals: number[] = new Array<number>();
             private _colors: number[] = new Array<number>();
             private _uvs: number[] = new Array<number>();
-            private _indices32: IndicesArray;
-            private _positions32: Float32Array;
+            private _indices32: IndicesArray;           // used as depth sorted array if depth sort enabled, else used as typed indices
+            private _positions32: Float32Array;         // updated positions for the VBO
             private _normals32: Float32Array;           // updated normals for the VBO
             private _fixedNormal32: Float32Array;       // initial normal references
             private _colors32: Float32Array;
@@ -183,7 +183,7 @@
                 }
 
                 var vertexData = new VertexData();
-                vertexData.indices = this._indices32;
+                vertexData.indices = (this._depthSort) ? this._indices : this._indices32;
                 vertexData.set(this._positions32, VertexBuffer.PositionKind);
                 vertexData.set(this._normals32, VertexBuffer.NormalKind);
                 if (this._uvs32) {
@@ -1038,9 +1038,7 @@
 
                 let boundingInfo = this.mesh.getBoundingInfo();
 
-                if (boundingInfo) {
-                    boundingInfo.isLocked = val;
-                }
+                boundingInfo.isLocked = val;
             }
     
             public get isVisibilityBoxLocked(): boolean {

+ 2 - 2
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -331,7 +331,7 @@
             //For now pointDepth will not be used and will be automatically calculated.
             //Future reference - try and find the best place to add a reference to the pointDepth variable.
             var arraySize = pointDepth || ~~(Math.sqrt(pos.length / 3) - 1);
-            let boundingInfo = <BoundingInfo>(object.getBoundingInfo());
+            let boundingInfo = object.getBoundingInfo();
             var dim = Math.min(boundingInfo.boundingBox.extendSizeWorld.x, boundingInfo.boundingBox.extendSizeWorld.y);
             var minY = boundingInfo.boundingBox.extendSizeWorld.z;
 
@@ -418,7 +418,7 @@
             //If it is a heightfield, if should be centered.
             if (impostor.type === PhysicsImpostor.HeightmapImpostor) {
                 var mesh = <AbstractMesh>(<any>object);
-                let boundingInfo = <BoundingInfo>mesh.getBoundingInfo();
+                let boundingInfo = mesh.getBoundingInfo();
                 //calculate the correct body position:
                 var rotationQuaternion = mesh.rotationQuaternion;
                 mesh.rotationQuaternion = this._tmpUnityRotation;

+ 2 - 10
src/Physics/babylon.physicsImpostor.ts

@@ -15,7 +15,7 @@ module BABYLON {
         scaling: Vector3;
         rotation?: Vector3;
         parent?: any;
-        getBoundingInfo(): Nullable<BoundingInfo>;
+        getBoundingInfo(): BoundingInfo;
         computeWorldMatrix(force: boolean): Matrix;
         getWorldMatrix?(): Matrix;
         getChildMeshes?(directDescendantsOnly?: boolean): Array<AbstractMesh>;
@@ -234,12 +234,7 @@ module BABYLON {
                 //calculate the world matrix with no rotation
                 this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
                 let boundingInfo = this.object.getBoundingInfo();
-                let size: Vector3;
-                if (boundingInfo) {
-                    size = boundingInfo.boundingBox.extendSizeWorld.scale(2)
-                } else {
-                    size = Vector3.Zero();
-                }
+                let size = boundingInfo.boundingBox.extendSizeWorld.scale(2)
 
                 //bring back the rotation
                 this.object.rotationQuaternion = q;
@@ -255,9 +250,6 @@ module BABYLON {
         public getObjectCenter(): Vector3 {
             if (this.object.getBoundingInfo) {
                 let boundingInfo = this.object.getBoundingInfo();
-                if (!boundingInfo) {
-                    return this.object.position;
-                }
                 return boundingInfo.boundingBox.centerWorld;
             } else {
                 return this.object.position;

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

@@ -187,7 +187,7 @@
             for (; subIndex < subMeshes.length; subIndex++) {
                 subMesh = subMeshes.data[subIndex];
                 subMesh._alphaIndex = subMesh.getMesh().alphaIndex;
-                subMesh._distanceToCamera = (<BoundingInfo>subMesh.getBoundingInfo()).boundingSphere.centerWorld.subtract(cameraPosition).length();
+                subMesh._distanceToCamera = subMesh.getBoundingInfo().boundingSphere.centerWorld.subtract(cameraPosition).length();
             }
 
             let sortedArray = subMeshes.data.slice(0, subMeshes.length);

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

@@ -215,6 +215,12 @@
                 serializationObject.skeletons.push(scene.skeletons[index].serialize());
             }
 
+            // Transform nodes
+            serializationObject.transformNodes = [];
+            for (index = 0; index < scene.transformNodes.length; index++) {
+                serializationObject.transformNodes.push(scene.transformNodes[index].serialize());
+            }            
+
             // Geometries
             serializationObject.geometries = {};
 

+ 6 - 12
src/babylon.scene.ts

@@ -2903,9 +2903,7 @@
                 if (mesh.showSubMeshesBoundingBox) {
                     let boundingInfo = subMesh.getBoundingInfo();
 
-                    if (boundingInfo) {
-                        this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
-                    }
+                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);
                 }
 
                 if (material) {
@@ -3062,9 +3060,7 @@
             if (sourceMesh.showBoundingBox || this.forceShowBoundingBoxes) {
                 let boundingInfo = sourceMesh.getBoundingInfo();
 
-                if (boundingInfo) {
-                    this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);    
-                }
+                this.getBoundingBoxRenderer().renderList.push(boundingInfo.boundingBox);    
             }
 
             if (mesh && mesh.subMeshes) {
@@ -3957,13 +3953,11 @@
                 mesh.computeWorldMatrix(true);
                 let boundingInfo = mesh.getBoundingInfo();
 
-                if (boundingInfo) {
-                    var minBox = boundingInfo.boundingBox.minimumWorld;
-                    var maxBox = boundingInfo.boundingBox.maximumWorld;
+                var minBox = boundingInfo.boundingBox.minimumWorld;
+                var maxBox = boundingInfo.boundingBox.maximumWorld;
 
-                    Tools.CheckExtends(minBox, min, max);
-                    Tools.CheckExtends(maxBox, min, max);
-                }
+                Tools.CheckExtends(minBox, min, max);
+                Tools.CheckExtends(maxBox, min, max);
             }
 
             return {