Преглед изворни кода

Merge remote-tracking branch 'upstream/master' into Env

sebastien пре 7 година
родитељ
комит
3be6012b8b
47 измењених фајлова са 12898 додато и 12718 уклоњено
  1. 4 4
      Playground/debug.html
  2. 4 4
      Playground/index-local.html
  3. 4 4
      Playground/index.html
  4. 4 4
      Playground/indexStable.html
  5. 2 2
      Playground/js/index.js
  6. 28 9
      Tools/Gulp/config.json
  7. 1 1
      Tools/Gulp/gulpfile.js
  8. 12438 12438
      dist/preview release/babylon.d.ts
  9. 9 9
      dist/preview release/babylon.js
  10. 3 3
      dist/preview release/babylon.max.js
  11. 3 3
      dist/preview release/babylon.no-module.max.js
  12. 9 9
      dist/preview release/babylon.worker.js
  13. 3 3
      dist/preview release/es6.js
  14. 4 2
      dist/preview release/gui/babylon.gui.d.ts
  15. 19 8
      dist/preview release/gui/babylon.gui.js
  16. 4 4
      dist/preview release/gui/babylon.gui.min.js
  17. 4 2
      dist/preview release/gui/babylon.gui.module.d.ts
  18. 3 3
      dist/preview release/inspector/babylon.inspector.bundle.js
  19. 9 9
      dist/preview release/viewer/babylon.viewer.js
  20. 120 102
      dist/preview release/viewer/babylon.viewer.max.js
  21. 1 1
      dist/preview release/what's new.md
  22. 5 1
      gui/src/2D/controls/container.ts
  23. 6 4
      gui/src/3D/controls/button3D.ts
  24. 1 0
      gui/src/3D/controls/container3D.ts
  25. 9 4
      gui/src/3D/controls/control3D.ts
  26. 3 1
      gui/src/3D/controls/stackPanel3D.ts
  27. 2 1
      gui/src/3D/materials/fluentMaterial.ts
  28. 2 2
      inspector/src/tools/AbstractTool.ts
  29. 1 1
      inspector/src/tools/DisposeTool.ts
  30. 1 1
      inspector/src/tools/FullscreenTool.ts
  31. 1 1
      inspector/src/tools/LabelTool.ts
  32. 1 1
      inspector/src/tools/PauseScheduleTool.ts
  33. 1 1
      inspector/src/tools/PickTool.ts
  34. 1 1
      inspector/src/tools/PopupTool.ts
  35. 1 1
      inspector/src/tools/RefreshTool.ts
  36. 0 1
      loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts
  37. 20 20
      loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts
  38. 4 8
      loaders/src/glTF/babylon.glTFFileLoader.ts
  39. 0 4
      serializers/src/glTF/2.0/babylon.glTFExporter.ts
  40. 16 30
      src/Behaviors/Mesh/babylon.pointerDragBehavior.ts
  41. 1 1
      src/Gizmos/babylon.axisDragGizmo.ts
  42. 1 1
      src/Gizmos/babylon.axisScaleGizmo.ts
  43. 82 0
      src/Gizmos/babylon.gizmoManager.ts
  44. 1 1
      src/Gizmos/babylon.planeRotationGizmo.ts
  45. 4 4
      src/Mesh/babylon.mesh.ts
  46. 52 1
      src/Rendering/babylon.utilityLayerRenderer.ts
  47. 6 3
      src/babylon.scene.ts

+ 4 - 4
Playground/debug.html

@@ -152,7 +152,7 @@
                 </div>
             </div>
 
-            <div class="button uncheck" id="debugButton1600">Debug layer
+            <div class="button uncheck" id="debugButton1600">Inspector
                 <i class="fa fa-square-o" aria-hidden="true"></i>
             </div>
             <div class="button" id="metadataButton1600">Metadata</div>
@@ -245,7 +245,7 @@
                     <div class="option" id="minimapToggle1475">Minimap
                         <i class="fa fa-square-o" aria-hidden="true"></i>
                     </div>
-                    <div class="option" id="debugButton1475">Debug layer
+                    <div class="option" id="debugButton1475">Inspector
                         <i class="fa fa-square-o" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="metadataButton1475">Metadata</div>
@@ -332,7 +332,7 @@
                     <div class="option" id="minimapToggle1030">Minimap
                         <i class="fa fa-square-o" aria-hidden="true"></i>
                     </div>
-                    <div class="option" id="debugButton1030">Debug layer
+                    <div class="option" id="debugButton1030">Inspector
                         <i class="fa fa-square-o" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="metadataButton1030">Metadata</div>
@@ -416,7 +416,7 @@
                     <div class="option" id="minimapToggle750">Minimap
                         <i class="fa fa-square-o" aria-hidden="true"></i>
                     </div>
-                    <div class="option" id="debugButton750">Debug layer
+                    <div class="option" id="debugButton750">Inspector
                         <i class="fa fa-square-o" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="metadataButton750">Metadata</div>

+ 4 - 4
Playground/index-local.html

@@ -95,7 +95,7 @@
                     </div>
                 </div>
 
-                <div class="button uncheck" id="debugButton1600">Debug layer
+                <div class="button uncheck" id="debugButton1600">Inspector
                     <i class="fa fa-square-o" aria-hidden="true"></i>
                 </div>
                 <div class="button" id="metadataButton1600">Metadata</div>
@@ -187,7 +187,7 @@
                         <div class="option" id="minimapToggle1475">Minimap
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                        <div class="option" id="debugButton1475">Debug layer
+                        <div class="option" id="debugButton1475">Inspector
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
                         <div class="option" id="metadataButton1475">Metadata</div>
@@ -274,7 +274,7 @@
                         <div class="option" id="minimapToggle1030">Minimap
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                        <div class="option" id="debugButton1030">Debug layer
+                        <div class="option" id="debugButton1030">Inspector
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
                         <div class="option" id="metadataButton1030">Metadata</div>
@@ -358,7 +358,7 @@
                         <div class="option" id="minimapToggle750">Minimap
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                        <div class="option" id="debugButton750">Debug layer
+                        <div class="option" id="debugButton750">Inspector
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
                         <div class="option" id="metadataButton750">Metadata</div>

+ 4 - 4
Playground/index.html

@@ -130,7 +130,7 @@
                     </div>
                 </div>
 
-                <div class="button uncheck" id="debugButton1600">Debug layer
+                <div class="button uncheck" id="debugButton1600">Inspector
                     <i class="fa fa-square-o" aria-hidden="true"></i>
                 </div>
                 <div class="button" id="metadataButton1600">Metadata</div>
@@ -222,7 +222,7 @@
                         <div class="option" id="minimapToggle1475">Minimap
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                        <div class="option" id="debugButton1475">Debug layer
+                        <div class="option" id="debugButton1475">Inspector
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
                         <div class="option" id="metadataButton1475">Metadata</div>
@@ -309,7 +309,7 @@
                         <div class="option" id="minimapToggle1030">Minimap
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                        <div class="option" id="debugButton1030">Debug layer
+                        <div class="option" id="debugButton1030">Inspector
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
                         <div class="option" id="metadataButton1030">Metadata</div>
@@ -393,7 +393,7 @@
                         <div class="option" id="minimapToggle750">Minimap
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                        <div class="option" id="debugButton750">Debug layer
+                        <div class="option" id="debugButton750">Inspector
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
                         <div class="option" id="metadataButton750">Metadata</div>

+ 4 - 4
Playground/indexStable.html

@@ -123,7 +123,7 @@
                     </div>
                 </div>
 
-                <div class="button uncheck" id="debugButton1600">Debug layer
+                <div class="button uncheck" id="debugButton1600">Inspector
                     <i class="fa fa-square-o" aria-hidden="true"></i>
                 </div>
                 <div class="button" id="metadataButton1600">Metadata</div>
@@ -213,7 +213,7 @@
                         <div class="option" id="minimapToggle1475">Minimap
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                        <div class="option" id="debugButton1475">Debug layer
+                        <div class="option" id="debugButton1475">Inspector
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
                         <div class="option" id="metadataButton1475">Metadata</div>
@@ -300,7 +300,7 @@
                         <div class="option" id="minimapToggle1030">Minimap
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                        <div class="option" id="debugButton1030">Debug layer
+                        <div class="option" id="debugButton1030">Inspector
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
                         <div class="option" id="metadataButton1030">Metadata</div>
@@ -384,7 +384,7 @@
                         <div class="option" id="minimapToggle750">Minimap
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                        <div class="option" id="debugButton750">Debug layer
+                        <div class="option" id="debugButton750">Inspector
                             <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
                         <div class="option" id="metadataButton750">Metadata</div>

+ 2 - 2
Playground/js/index.js

@@ -756,11 +756,11 @@
 
             if (debugButton.classList.contains('uncheck')) {
                 setToMultipleID("debugButton", "removeClass", 'uncheck');
-                setToMultipleID("debugButton", "innerHTML", 'Debug layer<i class="fa fa-check-square" aria-hidden="true"></i>');
+                setToMultipleID("debugButton", "innerHTML", 'Inspector<i class="fa fa-check-square" aria-hidden="true"></i>');
                 scene.debugLayer.show();
             } else {
                 setToMultipleID("debugButton", "addClass", 'uncheck');
-                setToMultipleID("debugButton", "innerHTML", 'Debug layer<i class="fa fa-square-o" aria-hidden="true"></i>');
+                setToMultipleID("debugButton", "innerHTML", 'Inspector<i class="fa fa-square-o" aria-hidden="true"></i>');
                 scene.debugLayer.hide();
             }
         }

+ 28 - 9
Tools/Gulp/config.json

@@ -95,6 +95,8 @@
             "physics",
             "textureFormats",
             "debug",
+            "utilityLayer",
+            "gizmos",
             "morphTargets",
             "octrees",
             "vr",
@@ -1021,15 +1023,7 @@
                 "../../src/Debug/babylon.rayHelper.js",
                 "../../src/Debug/babylon.debugLayer.js",
                 "../../src/Debug/babylon.physicsViewer.js",
-                "../../src/Rendering/babylon.boundingBoxRenderer.js",
-                "../../src/Rendering/babylon.utilityLayerRenderer.js",
-                "../../src/Gizmos/babylon.gizmo.js",
-                "../../src/Gizmos/babylon.axisDragGizmo.js",
-                "../../src/Gizmos/babylon.axisScaleGizmo.js",
-                "../../src/Gizmos/babylon.planeRotationGizmo.js",
-                "../../src/Gizmos/babylon.positionGizmo.js",
-                "../../src/Gizmos/babylon.rotationGizmo.js",
-                "../../src/Gizmos/babylon.scaleGizmo.js"
+                "../../src/Rendering/babylon.boundingBoxRenderer.js"
             ],
             "dependUpon": [
                 "shaderMaterial",
@@ -1040,6 +1034,31 @@
             ],
             "shaders": []
         },
+        "utilityLayer": {
+            "files": [
+                "../../src/Rendering/babylon.utilityLayerRenderer.js"
+            ],
+            "dependUpon": [
+                "core"
+            ]
+        },
+        "gizmos": {
+            "files": [
+                "../../src/Gizmos/babylon.gizmo.js",
+                "../../src/Gizmos/babylon.axisDragGizmo.js",
+                "../../src/Gizmos/babylon.axisScaleGizmo.js",
+                "../../src/Gizmos/babylon.planeRotationGizmo.js",
+                "../../src/Gizmos/babylon.positionGizmo.js",
+                "../../src/Gizmos/babylon.rotationGizmo.js",
+                "../../src/Gizmos/babylon.scaleGizmo.js",
+                "../../src/Gizmos/babylon.gizmoManager.js"
+            ],
+            "dependUpon": [
+                "core",
+                "utilityLayer",
+                "meshBehaviors"
+            ]
+        },
         "morphTargets": {
             "files": [
                 "../../src/Morph/babylon.morphTarget.js",

+ 1 - 1
Tools/Gulp/gulpfile.js

@@ -957,7 +957,7 @@ gulp.task("typedoc-all", function (cb) {
  * Validate compile the code and check the comments and style case convention through typedoc
  */
 gulp.task("typedoc-check", function (cb) {
-    runSequence("typescript-compile", "typedoc-generate", "typedoc-validate", cb);
+    runSequence("typescript-compile", "gui", "loaders", "serializers", "typedoc-generate", "typedoc-validate", cb);
 });
 
 /**

Разлика између датотеке није приказан због своје велике величине
+ 12438 - 12438
dist/preview release/babylon.d.ts


Разлика између датотеке није приказан због своје велике величине
+ 9 - 9
dist/preview release/babylon.js


+ 3 - 3
dist/preview release/babylon.max.js

@@ -34287,7 +34287,7 @@ var BABYLON;
             for (index = 0; index < meshes.length; index++) {
                 if (meshes[index]) {
                     meshes[index].computeWorldMatrix(true);
-                    otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], true);
+                    otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], true, true);
                     otherVertexData.transform(meshes[index].getWorldMatrix());
                     if (vertexData) {
                         vertexData.merge(otherVertexData);
@@ -34319,11 +34319,11 @@ var BABYLON;
             }
             // Subdivide
             if (subdivideWithSubMeshes) {
-                //-- Suppresions du submesh global
+                //-- removal of global submesh
                 meshSubclass.releaseSubMeshes();
                 index = 0;
                 var offset = 0;
-                //-- aplique la subdivision en fonction du tableau d'indices
+                //-- apply subdivision according to index table
                 while (index < indiceArray.length) {
                     BABYLON.SubMesh.CreateFromIndices(0, offset, indiceArray[index], meshSubclass);
                     offset += indiceArray[index];

+ 3 - 3
dist/preview release/babylon.no-module.max.js

@@ -34254,7 +34254,7 @@ var BABYLON;
             for (index = 0; index < meshes.length; index++) {
                 if (meshes[index]) {
                     meshes[index].computeWorldMatrix(true);
-                    otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], true);
+                    otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], true, true);
                     otherVertexData.transform(meshes[index].getWorldMatrix());
                     if (vertexData) {
                         vertexData.merge(otherVertexData);
@@ -34286,11 +34286,11 @@ var BABYLON;
             }
             // Subdivide
             if (subdivideWithSubMeshes) {
-                //-- Suppresions du submesh global
+                //-- removal of global submesh
                 meshSubclass.releaseSubMeshes();
                 index = 0;
                 var offset = 0;
-                //-- aplique la subdivision en fonction du tableau d'indices
+                //-- apply subdivision according to index table
                 while (index < indiceArray.length) {
                     BABYLON.SubMesh.CreateFromIndices(0, offset, indiceArray[index], meshSubclass);
                     offset += indiceArray[index];

Разлика између датотеке није приказан због своје велике величине
+ 9 - 9
dist/preview release/babylon.worker.js


+ 3 - 3
dist/preview release/es6.js

@@ -34254,7 +34254,7 @@ var BABYLON;
             for (index = 0; index < meshes.length; index++) {
                 if (meshes[index]) {
                     meshes[index].computeWorldMatrix(true);
-                    otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], true);
+                    otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], true, true);
                     otherVertexData.transform(meshes[index].getWorldMatrix());
                     if (vertexData) {
                         vertexData.merge(otherVertexData);
@@ -34286,11 +34286,11 @@ var BABYLON;
             }
             // Subdivide
             if (subdivideWithSubMeshes) {
-                //-- Suppresions du submesh global
+                //-- removal of global submesh
                 meshSubclass.releaseSubMeshes();
                 index = 0;
                 var offset = 0;
-                //-- aplique la subdivision en fonction du tableau d'indices
+                //-- apply subdivision according to index table
                 while (index < indiceArray.length) {
                     BABYLON.SubMesh.CreateFromIndices(0, offset, indiceArray[index], meshSubclass);
                     offset += indiceArray[index];

+ 4 - 2
dist/preview release/gui/babylon.gui.d.ts

@@ -1022,7 +1022,7 @@ declare module BABYLON.GUI {
          * @param control defines the control to add
          * @returns the current container
          */
-        addControl(control: Control): Container;
+        addControl(control: Nullable<Control>): Container;
         /**
          * Removes a control from the current container
          * @param control defines the control to remove
@@ -2172,6 +2172,8 @@ declare module BABYLON.GUI {
         forcePointerUp(pointerId?: Nullable<number>): void;
         /** @hidden */
         _processObservables(type: number, pickedPoint: Vector3, pointerId: number, buttonIndex: number): boolean;
+        /** @hidden */
+        _disposeNode(): void;
         /**
          * Releases all associated resources
          */
@@ -2246,7 +2248,7 @@ declare module BABYLON.GUI {
          */
         contentScaleRatio: number;
         protected _disposeFacadeTexture(): void;
-        private _resetContent();
+        protected _resetContent(): void;
         /**
          * Creates a new button
          * @param name defines the control name

+ 19 - 8
dist/preview release/gui/babylon.gui.js

@@ -2925,6 +2925,9 @@ var BABYLON;
              * @returns the current container
              */
             Container.prototype.addControl = function (control) {
+                if (!control) {
+                    return this;
+                }
                 var index = this._children.indexOf(control);
                 if (index !== -1) {
                     return this;
@@ -6842,7 +6845,8 @@ var BABYLON;
                         this._activeEffect.setFloat("borderWidth", this.borderWidth);
                         this._activeEffect.setFloat("edgeSmoothingValue", this.edgeSmoothingValue);
                         this._activeEffect.setFloat("borderMinValue", this.borderMinValue);
-                        this._activeEffect.setVector3("scaleFactor", mesh.getBoundingInfo().boundingBox.extendSizeWorld);
+                        mesh.getBoundingInfo().boundingBox.extendSize.multiplyToRef(mesh.scaling, BABYLON.Tmp.Vector3[0]);
+                        this._activeEffect.setVector3("scaleFactor", BABYLON.Tmp.Vector3[0]);
                     }
                     if (defines.HOVERLIGHT) {
                         this._activeEffect.setDirectColor4("hoverColor", this.hoverColor);
@@ -7268,6 +7272,13 @@ var BABYLON;
                 }
                 return false;
             };
+            /** @hidden */
+            Control3D.prototype._disposeNode = function () {
+                if (this._node) {
+                    this._node.dispose();
+                    this._node = null;
+                }
+            };
             /**
              * Releases all associated resources
              */
@@ -7278,10 +7289,7 @@ var BABYLON;
                 this.onPointerOutObservable.clear();
                 this.onPointerUpObservable.clear();
                 this.onPointerClickObservable.clear();
-                if (this._node) {
-                    this._node.dispose();
-                    this._node = null;
-                }
+                this._disposeNode();
                 // Behaviors
                 for (var _i = 0, _a = this._behaviors; _i < _a.length; _i++) {
                     var behavior = _a[_i];
@@ -7365,6 +7373,7 @@ var BABYLON;
                 if (index !== -1) {
                     this._children.splice(index, 1);
                     control.parent = null;
+                    control._disposeNode();
                 }
                 return this;
             };
@@ -7483,10 +7492,10 @@ var BABYLON;
                     return this._content;
                 },
                 set: function (value) {
+                    this._content = value;
                     if (!this._host || !this._host.utilityLayer) {
                         return;
                     }
-                    this._content = value;
                     if (!this._facadeTexture) {
                         this._facadeTexture = new BABYLON.GUI.AdvancedDynamicTexture("Facade", this._contentResolution, this._contentResolution, this._host.utilityLayer.utilityLayerScene, true, BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
                         this._facadeTexture.rootContainer.scaleX = this._contentScaleRatio;
@@ -7530,13 +7539,14 @@ var BABYLON;
                 material.specularColor = BABYLON.Color3.Black();
                 mesh.material = material;
                 this._currentMaterial = material;
+                this._resetContent();
             };
             /**
              * Releases all associated resources
              */
             Button3D.prototype.dispose = function () {
                 _super.prototype.dispose.call(this);
-                this._disposeFaceTexture();
+                this._disposeFacadeTexture();
                 if (this._currentMaterial) {
                     this._currentMaterial.dispose();
                 }
@@ -7842,8 +7852,9 @@ var BABYLON;
                     }
                     controlCount++;
                     child.mesh.computeWorldMatrix(true);
+                    child.mesh.getWorldMatrix().multiplyToRef(currentInverseWorld, BABYLON.Tmp.Matrix[0]);
                     var boundingBox = child.mesh.getBoundingInfo().boundingBox;
-                    var extendSize = BABYLON.Vector3.TransformNormal(boundingBox.extendSizeWorld, currentInverseWorld);
+                    var extendSize = BABYLON.Vector3.TransformNormal(boundingBox.extendSize, BABYLON.Tmp.Matrix[0]);
                     extendSizes.push(extendSize);
                     if (this._isVertical) {
                         height += extendSize.y;

Разлика између датотеке није приказан због своје велике величине
+ 4 - 4
dist/preview release/gui/babylon.gui.min.js


+ 4 - 2
dist/preview release/gui/babylon.gui.module.d.ts

@@ -1027,7 +1027,7 @@ declare module BABYLON.GUI {
          * @param control defines the control to add
          * @returns the current container
          */
-        addControl(control: Control): Container;
+        addControl(control: Nullable<Control>): Container;
         /**
          * Removes a control from the current container
          * @param control defines the control to remove
@@ -2177,6 +2177,8 @@ declare module BABYLON.GUI {
         forcePointerUp(pointerId?: Nullable<number>): void;
         /** @hidden */
         _processObservables(type: number, pickedPoint: Vector3, pointerId: number, buttonIndex: number): boolean;
+        /** @hidden */
+        _disposeNode(): void;
         /**
          * Releases all associated resources
          */
@@ -2251,7 +2253,7 @@ declare module BABYLON.GUI {
          */
         contentScaleRatio: number;
         protected _disposeFacadeTexture(): void;
-        private _resetContent();
+        protected _resetContent(): void;
         /**
          * Creates a new button
          * @param name defines the control name

Разлика између датотеке није приказан због своје велике величине
+ 3 - 3
dist/preview release/inspector/babylon.inspector.bundle.js


Разлика између датотеке није приказан због своје велике величине
+ 9 - 9
dist/preview release/viewer/babylon.viewer.js


+ 120 - 102
dist/preview release/viewer/babylon.viewer.max.js

@@ -34375,7 +34375,7 @@ var BABYLON;
             for (index = 0; index < meshes.length; index++) {
                 if (meshes[index]) {
                     meshes[index].computeWorldMatrix(true);
-                    otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], true);
+                    otherVertexData = BABYLON.VertexData.ExtractFromMesh(meshes[index], true, true);
                     otherVertexData.transform(meshes[index].getWorldMatrix());
                     if (vertexData) {
                         vertexData.merge(otherVertexData);
@@ -34407,11 +34407,11 @@ var BABYLON;
             }
             // Subdivide
             if (subdivideWithSubMeshes) {
-                //-- Suppresions du submesh global
+                //-- removal of global submesh
                 meshSubclass.releaseSubMeshes();
                 index = 0;
                 var offset = 0;
-                //-- aplique la subdivision en fonction du tableau d'indices
+                //-- apply subdivision according to index table
                 while (index < indiceArray.length) {
                     BABYLON.SubMesh.CreateFromIndices(0, offset, indiceArray[index], meshSubclass);
                     offset += indiceArray[index];
@@ -104349,8 +104349,8 @@ var BABYLON;
                 }
             }
             var createLoaders = {
-                1: GLTFFileLoader.CreateGLTFLoaderV1,
-                2: GLTFFileLoader.CreateGLTFLoaderV2
+                1: GLTFFileLoader._CreateGLTFLoaderV1,
+                2: GLTFFileLoader._CreateGLTFLoaderV2
             };
             var createLoader = createLoaders[version.major];
             if (!createLoader) {
@@ -106168,7 +106168,7 @@ var BABYLON;
         }());
         GLTF1.GLTFLoader = GLTFLoader;
         ;
-        BABYLON.GLTFFileLoader.CreateGLTFLoaderV1 = function () { return new GLTFLoader(); };
+        BABYLON.GLTFFileLoader._CreateGLTFLoaderV1 = function () { return new GLTFLoader(); };
     })(GLTF1 = BABYLON.GLTF1 || (BABYLON.GLTF1 = {}));
 })(BABYLON || (BABYLON = {}));
 
@@ -106749,15 +106749,21 @@ var BABYLON;
 //# sourceMappingURL=babylon.glTFMaterialsCommonExtension.js.map
 
 
+
+
+//# sourceMappingURL=babylon.glTFLoaderInterfaces.js.map
+
+
+/**
+ * Defines the module used to import/export glTF 2.0 assets
+ */
 var BABYLON;
 (function (BABYLON) {
     var GLTF2;
     (function (GLTF2) {
-        /** @hidden */
         var _ArrayItem = /** @class */ (function () {
             function _ArrayItem() {
             }
-            /** @hidden */
             _ArrayItem.Assign = function (values) {
                 if (values) {
                     for (var index = 0; index < values.length; index++) {
@@ -106767,25 +106773,6 @@ var BABYLON;
             };
             return _ArrayItem;
         }());
-        GLTF2._ArrayItem = _ArrayItem;
-    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
-})(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=babylon.glTFLoaderUtilities.js.map
-
-
-
-
-//# sourceMappingURL=babylon.glTFLoaderInterfaces.js.map
-
-
-/**
- * Defines the module used to import/export glTF 2.0 assets
- */
-var BABYLON;
-(function (BABYLON) {
-    var GLTF2;
-    (function (GLTF2) {
         /**
          * Loader for loading a glTF 2.0 asset
          */
@@ -107031,19 +107018,19 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._setupData = function () {
-                GLTF2._ArrayItem.Assign(this._gltf.accessors);
-                GLTF2._ArrayItem.Assign(this._gltf.animations);
-                GLTF2._ArrayItem.Assign(this._gltf.buffers);
-                GLTF2._ArrayItem.Assign(this._gltf.bufferViews);
-                GLTF2._ArrayItem.Assign(this._gltf.cameras);
-                GLTF2._ArrayItem.Assign(this._gltf.images);
-                GLTF2._ArrayItem.Assign(this._gltf.materials);
-                GLTF2._ArrayItem.Assign(this._gltf.meshes);
-                GLTF2._ArrayItem.Assign(this._gltf.nodes);
-                GLTF2._ArrayItem.Assign(this._gltf.samplers);
-                GLTF2._ArrayItem.Assign(this._gltf.scenes);
-                GLTF2._ArrayItem.Assign(this._gltf.skins);
-                GLTF2._ArrayItem.Assign(this._gltf.textures);
+                _ArrayItem.Assign(this._gltf.accessors);
+                _ArrayItem.Assign(this._gltf.animations);
+                _ArrayItem.Assign(this._gltf.buffers);
+                _ArrayItem.Assign(this._gltf.bufferViews);
+                _ArrayItem.Assign(this._gltf.cameras);
+                _ArrayItem.Assign(this._gltf.images);
+                _ArrayItem.Assign(this._gltf.materials);
+                _ArrayItem.Assign(this._gltf.meshes);
+                _ArrayItem.Assign(this._gltf.nodes);
+                _ArrayItem.Assign(this._gltf.samplers);
+                _ArrayItem.Assign(this._gltf.scenes);
+                _ArrayItem.Assign(this._gltf.skins);
+                _ArrayItem.Assign(this._gltf.textures);
                 if (this._gltf.nodes) {
                     var nodeParents = {};
                     for (var _i = 0, _a = this._gltf.nodes; _i < _a.length; _i++) {
@@ -107226,7 +107213,7 @@ var BABYLON;
                     throw new Error(context + ": Invalid recursive node hierarchy");
                 }
                 var promises = new Array();
-                var babylonMesh = new BABYLON.Mesh(node.name || "node" + node._index, this._babylonScene, node._parent._babylonMesh);
+                var babylonMesh = new BABYLON.Mesh(node.name || "node" + node._index, this._babylonScene, node._parent ? node._parent._babylonMesh : null);
                 node._babylonMesh = babylonMesh;
                 GLTFLoader._LoadTransform(node, babylonMesh);
                 if (node.mesh != undefined) {
@@ -107254,7 +107241,7 @@ var BABYLON;
                 if (!primitives || primitives.length === 0) {
                     throw new Error(context + ": Primitives are missing");
                 }
-                GLTF2._ArrayItem.Assign(primitives);
+                _ArrayItem.Assign(primitives);
                 if (primitives.length === 1) {
                     var primitive = primitives[0];
                     promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive, babylonMesh));
@@ -107294,7 +107281,7 @@ var BABYLON;
                 }
                 else {
                     var material = GLTFLoader._GetProperty(context + "/material}", this._gltf.materials, primitive.material);
-                    promises.push(this._loadMaterialAsync("#/materials/" + material._index, material, babylonMesh, babylonDrawMode, function (babylonMaterial) {
+                    promises.push(this._loadMaterialAsync("#/materials/" + material._index, material, mesh, babylonMesh, babylonDrawMode, function (babylonMaterial) {
                         babylonMesh.material = babylonMaterial;
                     }));
                 }
@@ -107485,7 +107472,7 @@ var BABYLON;
                     return babylonBone;
                 }
                 var babylonParentBone = null;
-                if (node._parent._babylonMesh !== this._rootBabylonMesh) {
+                if (node._parent && node._parent._babylonMesh !== this._rootBabylonMesh) {
                     babylonParentBone = this._loadBone(node._parent, skin, babylonBones);
                 }
                 var boneIndex = skin.joints.indexOf(node._index);
@@ -107575,8 +107562,8 @@ var BABYLON;
                 var babylonAnimationGroup = new BABYLON.AnimationGroup(animation.name || "animation" + animation._index, this._babylonScene);
                 animation._babylonAnimationGroup = babylonAnimationGroup;
                 var promises = new Array();
-                GLTF2._ArrayItem.Assign(animation.channels);
-                GLTF2._ArrayItem.Assign(animation.samplers);
+                _ArrayItem.Assign(animation.channels);
+                _ArrayItem.Assign(animation.samplers);
                 for (var _i = 0, _a = animation.channels; _i < _a.length; _i++) {
                     var channel = _a[_i];
                     promises.push(this._loadAnimationChannelAsync(context + "/channels/" + channel._index, context, animation, channel, babylonAnimationGroup));
@@ -107930,8 +107917,8 @@ var BABYLON;
                 return Promise.all(promises).then(function () { });
             };
             /** @hidden */
-            GLTFLoader.prototype._loadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) {
-                var promise = GLTF2.GLTFLoaderExtension._LoadMaterialAsync(this, context, material, babylonMesh, babylonDrawMode, assign);
+            GLTFLoader.prototype._loadMaterialAsync = function (context, material, mesh, babylonMesh, babylonDrawMode, assign) {
+                var promise = GLTF2.GLTFLoaderExtension._LoadMaterialAsync(this, context, material, mesh, babylonMesh, babylonDrawMode, assign);
                 if (promise) {
                     return promise;
                 }
@@ -107939,7 +107926,7 @@ var BABYLON;
                 var babylonData = material._babylonData[babylonDrawMode];
                 if (!babylonData) {
                     var promises = new Array();
-                    var name_3 = material.name || "materialSG_" + material._index;
+                    var name_3 = material.name || "material_" + material._index;
                     var babylonMaterial = this._createMaterial(name_3, babylonDrawMode);
                     promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                     promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial));
@@ -108332,7 +108319,7 @@ var BABYLON;
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;
-        BABYLON.GLTFFileLoader.CreateGLTFLoaderV2 = function () { return new GLTFLoader(); };
+        BABYLON.GLTFFileLoader._CreateGLTFLoaderV2 = function () { return new GLTFLoader(); };
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
@@ -108352,11 +108339,15 @@ var BABYLON;
              * @param loader defines the GLTFLoader to use
              */
             function GLTFLoaderExtension(loader) {
-                /** Gets or sets a boolean indicating if the extension is enabled */
+                /**
+                 * Gets or sets a boolean indicating if the extension is enabled
+                 */
                 this.enabled = true;
                 this._loader = loader;
             }
-            /** Release all resources */
+            /**
+             * Release all resources
+             */
             GLTFLoaderExtension.prototype.dispose = function () {
                 delete this._loader;
             };
@@ -108371,12 +108362,16 @@ var BABYLON;
              * @hidden
              */
             GLTFLoaderExtension.prototype._loadNodeAsync = function (context, node) { return null; };
-            /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
+            /**
+             * Override this method to modify the default behavior for loading mesh primitive vertex data.
+             * @hidden
+             */
             GLTFLoaderExtension.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) { return null; };
-            /** Override this method to modify the default behavior for loading materials.
+            /**
+             * Override this method to modify the default behavior for loading materials.
              * @hidden
              */
-            GLTFLoaderExtension.prototype._loadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) { return null; };
+            GLTFLoaderExtension.prototype._loadMaterialAsync = function (context, material, mesh, babylonMesh, babylonDrawMode, assign) { return null; };
             /**
              * Override this method to modify the default behavior for loading textures.
              * @hidden
@@ -108401,7 +108396,7 @@ var BABYLON;
                 if (!extension) {
                     return null;
                 }
-                // Clear out the extension before executing the action to avoid recursing into the same property.
+                // Clear out the extension before executing the action to avoid infinite recursion.
                 delete extensions[this.name];
                 try {
                     return actionAsync(context + "/extensions/" + this.name, extension);
@@ -108415,6 +108410,29 @@ var BABYLON;
              * Helper method called by the loader to allow extensions to override loading scenes.
              * @hidden
              */
+            GLTFLoaderExtension.prototype._loadExtrasValueAsync = function (context, property, actionAsync) {
+                if (!property.extras) {
+                    return null;
+                }
+                var extras = property.extras;
+                var value = extras[this.name];
+                if (value === undefined) {
+                    return null;
+                }
+                // Clear out the extras value before executing the action to avoid infinite recursion.
+                delete extras[this.name];
+                try {
+                    return actionAsync(context + "/extras/" + this.name, value);
+                }
+                finally {
+                    // Restore the extras value after executing the action.
+                    extras[this.name] = value;
+                }
+            };
+            /**
+             * Helper method called by the loader to allow extensions to override loading scenes.
+             * @hidden
+             */
             GLTFLoaderExtension._LoadSceneAsync = function (loader, context, scene) {
                 return loader._applyExtensions(function (extension) { return extension._loadSceneAsync(context, scene); });
             };
@@ -108436,8 +108454,8 @@ var BABYLON;
              * Helper method called by the loader to allow extensions to override loading materials.
              * @hidden
              */
-            GLTFLoaderExtension._LoadMaterialAsync = function (loader, context, material, babylonMesh, babylonDrawMode, assign) {
-                return loader._applyExtensions(function (extension) { return extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign); });
+            GLTFLoaderExtension._LoadMaterialAsync = function (loader, context, material, mesh, babylonMesh, babylonDrawMode, assign) {
+                return loader._applyExtensions(function (extension) { return extension._loadMaterialAsync(context, material, mesh, babylonMesh, babylonDrawMode, assign); });
             };
             /**
              * Helper method called by the loader to allow extensions to override loading textures.
@@ -108574,7 +108592,7 @@ var BABYLON;
                         return firstPromise;
                     });
                 };
-                MSFT_lod.prototype._loadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) {
+                MSFT_lod.prototype._loadMaterialAsync = function (context, material, mesh, babylonMesh, babylonDrawMode, assign) {
                     var _this = this;
                     // Don't load material LODs if already loading a node LOD.
                     if (this._loadingNodeLOD) {
@@ -108591,7 +108609,7 @@ var BABYLON;
                                     _this._loadMaterialSignals[materialLOD._index] = new BABYLON.Deferred();
                                 }
                             }
-                            var promise = _this._loader._loadMaterialAsync("#/materials/" + materialLOD._index, materialLOD, babylonMesh, babylonDrawMode, indexLOD === 0 ? assign : function () { }).then(function () {
+                            var promise = _this._loader._loadMaterialAsync("#/materials/" + materialLOD._index, materialLOD, mesh, babylonMesh, babylonDrawMode, indexLOD === 0 ? assign : function () { }).then(function () {
                                 if (indexLOD !== 0) {
                                     var babylonDataLOD = materialLOD._babylonData;
                                     assign(babylonDataLOD[babylonDrawMode].material);
@@ -108681,29 +108699,28 @@ var BABYLON;
             /** @hidden */
             var MSFT_minecraftMesh = /** @class */ (function (_super) {
                 __extends(MSFT_minecraftMesh, _super);
-                function MSFT_minecraftMesh(loader) {
-                    var _this = _super.call(this, loader) || this;
+                function MSFT_minecraftMesh() {
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
                     _this.name = NAME;
-                    _this._onMaterialLoaded = function (material) {
-                        if (material.needAlphaBlending()) {
-                            material.forceDepthWrite = true;
-                            material.separateCullingPass = true;
-                        }
-                        material.backFaceCulling = material.forceDepthWrite;
-                        material.twoSidedLighting = true;
-                    };
-                    var meshes = loader._gltf.meshes;
-                    if (meshes && meshes.length) {
-                        for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
-                            var mesh = meshes_1[_i];
-                            if (mesh && mesh.extras && mesh.extras.MSFT_minecraftMesh) {
-                                _this._loader.onMaterialLoadedObservable.add(_this._onMaterialLoaded);
-                                break;
-                            }
-                        }
-                    }
                     return _this;
                 }
+                MSFT_minecraftMesh.prototype._loadMaterialAsync = function (context, material, mesh, babylonMesh, babylonDrawMode, assign) {
+                    var _this = this;
+                    return this._loadExtrasValueAsync(context, mesh, function (extensionContext, value) {
+                        if (value) {
+                            return _this._loader._loadMaterialAsync(context, material, mesh, babylonMesh, babylonDrawMode, function (babylonMaterial) {
+                                if (babylonMaterial.needAlphaBlending()) {
+                                    babylonMaterial.forceDepthWrite = true;
+                                    babylonMaterial.separateCullingPass = true;
+                                }
+                                babylonMaterial.backFaceCulling = babylonMaterial.forceDepthWrite;
+                                babylonMaterial.twoSidedLighting = true;
+                                assign(babylonMaterial);
+                            });
+                        }
+                        return null;
+                    });
+                };
                 return MSFT_minecraftMesh;
             }(GLTF2.GLTFLoaderExtension));
             Extensions.MSFT_minecraftMesh = MSFT_minecraftMesh;
@@ -108726,29 +108743,28 @@ var BABYLON;
             /** @hidden */
             var MSFT_sRGBFactors = /** @class */ (function (_super) {
                 __extends(MSFT_sRGBFactors, _super);
-                function MSFT_sRGBFactors(loader) {
-                    var _this = _super.call(this, loader) || this;
+                function MSFT_sRGBFactors() {
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
                     _this.name = NAME;
-                    _this._onMaterialLoaded = function (material) {
-                        if (!material.albedoTexture) {
-                            material.albedoColor.toLinearSpaceToRef(material.albedoColor);
-                        }
-                        if (!material.reflectivityTexture) {
-                            material.reflectivityColor.toLinearSpaceToRef(material.reflectivityColor);
-                        }
-                    };
-                    var materials = loader._gltf.materials;
-                    if (materials && materials.length) {
-                        for (var _i = 0, materials_1 = materials; _i < materials_1.length; _i++) {
-                            var material = materials_1[_i];
-                            if (material && material.extras && material.extras.MSFT_sRGBFactors) {
-                                _this._loader.onMaterialLoadedObservable.add(_this._onMaterialLoaded);
-                                break;
-                            }
-                        }
-                    }
                     return _this;
                 }
+                MSFT_sRGBFactors.prototype._loadMaterialAsync = function (context, material, mesh, babylonMesh, babylonDrawMode, assign) {
+                    var _this = this;
+                    return this._loadExtrasValueAsync(context, material, function (extensionContext, value) {
+                        if (value) {
+                            return _this._loader._loadMaterialAsync(context, material, mesh, babylonMesh, babylonDrawMode, function (babylonMaterial) {
+                                if (!babylonMaterial.albedoTexture) {
+                                    babylonMaterial.albedoColor.toLinearSpaceToRef(babylonMaterial.albedoColor);
+                                }
+                                if (!babylonMaterial.reflectivityTexture) {
+                                    babylonMaterial.reflectivityColor.toLinearSpaceToRef(babylonMaterial.reflectivityColor);
+                                }
+                                assign(babylonMaterial);
+                            });
+                        }
+                        return null;
+                    });
+                };
                 return MSFT_sRGBFactors;
             }(GLTF2.GLTFLoaderExtension));
             Extensions.MSFT_sRGBFactors = MSFT_sRGBFactors;
@@ -108870,7 +108886,7 @@ var BABYLON;
                     return _this;
                 }
                 /** @hidden */
-                KHR_materials_pbrSpecularGlossiness.prototype._loadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) {
+                KHR_materials_pbrSpecularGlossiness.prototype._loadMaterialAsync = function (context, material, mesh, babylonMesh, babylonDrawMode, assign) {
                     var _this = this;
                     return this._loadExtensionAsync(context, material, function (extensionContext, extension) {
                         material._babylonData = material._babylonData || {};
@@ -108949,7 +108965,7 @@ var BABYLON;
                     _this.name = NAME;
                     return _this;
                 }
-                KHR_materials_unlit.prototype._loadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) {
+                KHR_materials_unlit.prototype._loadMaterialAsync = function (context, material, mesh, babylonMesh, babylonDrawMode, assign) {
                     var _this = this;
                     return this._loadExtensionAsync(context, material, function () {
                         material._babylonData = material._babylonData || {};
@@ -109007,6 +109023,8 @@ var BABYLON;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
+//# sourceMappingURL=KHR_materials_unlit.js.map
+
 
 
 var BABYLON;

+ 1 - 1
dist/preview release/what's new.md

@@ -22,7 +22,7 @@
 - UtilityLayer class to render another scene as a layer on top of an existing scene ([TrevorDev](https://github.com/TrevorDev))
 - AnimationGroup has now onAnimationGroupEnd observable ([RaananW](https://github.com/RaananW))
 - Pointer drag behavior to enable drag and drop with mouse or 6dof controller on a mesh ([TrevorDev](https://github.com/TrevorDev))
-- Gizmo class used to manipulate meshes in a scene, position, rotation, scale gizmos ([TrevorDev](https://github.com/TrevorDev))
+- Gizmo and gizmoManager class used to manipulate meshes in a scene, position, rotation, scale gizmos ([TrevorDev](https://github.com/TrevorDev))
 - Added a new `mesh.ignoreNonUniformScaling` to turn off non uniform scaling compensation ([Deltakosh](https://github.com/deltakosh))
 
 ### glTF Loader

+ 5 - 1
gui/src/2D/controls/container.ts

@@ -131,7 +131,11 @@ module BABYLON.GUI {
          * @param control defines the control to add
          * @returns the current container
          */
-        public addControl(control: Control): Container {
+        public addControl(control: Nullable<Control>): Container {
+            if (!control) {
+                return this;
+            }
+
            var index = this._children.indexOf(control);
 
             if (index !== -1) {

+ 6 - 4
gui/src/3D/controls/button3D.ts

@@ -51,7 +51,7 @@ module BABYLON.GUI {
             }
         }
 
-        private _resetContent() {
+        protected _resetContent() {
             this._disposeFacadeTexture();
             this.content = this._content;
         }
@@ -101,12 +101,12 @@ module BABYLON.GUI {
         }
 
         public set content(value: Control) {
+            this._content = value;
+
             if (!this._host || !this._host.utilityLayer) {
                 return;
             }
 
-            this._content = value;
-
             if (!this._facadeTexture) {
                 this._facadeTexture = new BABYLON.GUI.AdvancedDynamicTexture("Facade", this._contentResolution, this._contentResolution, this._host.utilityLayer.utilityLayerScene, true, BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
                 this._facadeTexture.rootContainer.scaleX = this._contentScaleRatio;
@@ -157,6 +157,8 @@ module BABYLON.GUI {
 
             mesh.material = material;
             this._currentMaterial = material;
+
+            this._resetContent();
         }
 
         /**
@@ -165,7 +167,7 @@ module BABYLON.GUI {
         public dispose() {
             super.dispose();
 
-            this._disposeFaceTexture();
+            this._disposeFacadeTexture();
 
             if (this._currentMaterial) {
                 this._currentMaterial.dispose();

+ 1 - 0
gui/src/3D/controls/container3D.ts

@@ -79,6 +79,7 @@ module BABYLON.GUI {
                 this._children.splice(index, 1);
 
                 control.parent = null;
+                control._disposeNode();
             }
 
             return this;

+ 9 - 4
gui/src/3D/controls/control3D.ts

@@ -365,6 +365,14 @@ module BABYLON.GUI {
             return false;
         }        
 
+        /** @hidden */
+        public _disposeNode(): void {
+            if (this._node) {
+                this._node.dispose();
+                this._node = null;
+            }
+        }
+
         /**
          * Releases all associated resources
          */
@@ -376,10 +384,7 @@ module BABYLON.GUI {
             this.onPointerUpObservable.clear();
             this.onPointerClickObservable.clear();
 
-            if (this._node) {
-                this._node.dispose();
-                this._node = null;
-            }
+            this._disposeNode();
 
             // Behaviors
             for (var behavior of this._behaviors) {

+ 3 - 1
gui/src/3D/controls/stackPanel3D.ts

@@ -55,8 +55,10 @@ module BABYLON.GUI {
 
                 controlCount++;
                 child.mesh.computeWorldMatrix(true);
+                child.mesh.getWorldMatrix().multiplyToRef(currentInverseWorld, Tmp.Matrix[0]);
+
                 let boundingBox = child.mesh.getBoundingInfo().boundingBox;
-                let extendSize = Vector3.TransformNormal(boundingBox.extendSizeWorld, currentInverseWorld);
+                let extendSize = Vector3.TransformNormal(boundingBox.extendSize, Tmp.Matrix[0]);
                 extendSizes.push(extendSize);
 
                 if (this._isVertical) {

+ 2 - 1
gui/src/3D/materials/fluentMaterial.ts

@@ -225,7 +225,8 @@ module BABYLON.GUI {
                     this._activeEffect.setFloat("edgeSmoothingValue", this.edgeSmoothingValue);
                     this._activeEffect.setFloat("borderMinValue", this.borderMinValue);
 
-                    this._activeEffect.setVector3("scaleFactor", mesh.getBoundingInfo().boundingBox.extendSizeWorld);
+                    mesh.getBoundingInfo().boundingBox.extendSize.multiplyToRef(mesh.scaling, Tmp.Vector3[0]);
+                    this._activeEffect.setVector3("scaleFactor", Tmp.Vector3[0]);
                 }
 
                 if (defines.HOVERLIGHT) {

+ 2 - 2
inspector/src/tools/AbstractTool.ts

@@ -3,11 +3,11 @@ module INSPECTOR {
         private _elem: HTMLElement;
         protected _inspector: Inspector;
 
-        constructor(icon: string, parent: HTMLElement, inspector: Inspector, tooltip: string) {
+        constructor(iconSet: string, icon: string, parent: HTMLElement, inspector: Inspector, tooltip: string) {
             this._inspector = inspector;
 
             this._elem = Inspector.DOCUMENT.createElement('i');
-            this._elem.className = `tool fa ${icon}`;
+            this._elem.className = `tool ${iconSet} ${icon}`;
             parent.appendChild(this._elem);
 
             this._elem.addEventListener('click', (e) => {

+ 1 - 1
inspector/src/tools/DisposeTool.ts

@@ -6,7 +6,7 @@ module INSPECTOR {
     export class DisposeTool extends AbstractTool {
 
         constructor(parent:HTMLElement, inspector:Inspector) {
-            super('fa-times', parent, inspector, 'Close the inspector panel');
+            super('fa', 'fa-times', parent, inspector, 'Close the inspector panel');
         }
 
         // Action : refresh the whole panel

+ 1 - 1
inspector/src/tools/FullscreenTool.ts

@@ -3,7 +3,7 @@ module INSPECTOR {
     export class FullscreenTool extends AbstractTool {
 
         constructor(parent:HTMLElement, inspector:Inspector) {
-            super('fa-expand', parent, inspector, 'Open the scene in fullscreen, press Esc to exit');
+            super('fa', 'fa-expand', parent, inspector, 'Open the scene in fullscreen, press Esc to exit');
         }
 
         // Action : refresh the whole panel

+ 1 - 1
inspector/src/tools/LabelTool.ts

@@ -10,7 +10,7 @@ module INSPECTOR {
         private _guiLoaded: boolean = false;
 
         constructor(parent: HTMLElement, inspector: Inspector) {
-            super('fa-tags', parent, inspector, 'Display mesh names on the canvas');
+            super('fa', 'fa-tags', parent, inspector, 'Display mesh names on the canvas');
 
             this._scene = inspector.scene;
         }

+ 1 - 1
inspector/src/tools/PauseScheduleTool.ts

@@ -5,7 +5,7 @@ module INSPECTOR {
         private _isPause : boolean = false;
 
         constructor(parent:HTMLElement, inspector:Inspector) {
-            super('fa-pause', parent, inspector, 'Pause the automatic update of properties');
+            super('fa', 'fa-pause', parent, inspector, 'Pause the automatic update of properties');
         }
 
         // Action : refresh the whole panel

+ 1 - 1
inspector/src/tools/PickTool.ts

@@ -6,7 +6,7 @@ module INSPECTOR {
         private _pickHandler: (evt: Event) => void;
 
         constructor(parent:HTMLElement, inspector:Inspector) {
-            super('fa-mouse-pointer', parent, inspector, 'Select a mesh in the scene');
+            super('fa', 'fa-mouse-pointer', parent, inspector, 'Select a mesh in the scene');
             
             // Create handler
             this._pickHandler = this._pickMesh.bind(this);

+ 1 - 1
inspector/src/tools/PopupTool.ts

@@ -3,7 +3,7 @@ module INSPECTOR {
     export class PopupTool extends AbstractTool {
 
         constructor(parent:HTMLElement, inspector:Inspector) {
-            super('fa-external-link-alt', parent, inspector, 'Open the inspector in a popup');
+            super('fas', 'fa-external-link-alt', parent, inspector, 'Open the inspector in a popup');
         }
 
         // Action : refresh the whole panel

+ 1 - 1
inspector/src/tools/RefreshTool.ts

@@ -3,7 +3,7 @@ module INSPECTOR {
     export class RefreshTool extends AbstractTool {
 
         constructor(parent:HTMLElement, inspector:Inspector) {
-            super('fa-sync', parent, inspector, 'Refresh the current tab');
+            super('fa', 'fa-sync', parent, inspector, 'Refresh the current tab');
         }
 
         // Action : refresh the whole panel

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

@@ -17,7 +17,6 @@ module BABYLON.GLTF2.Extensions {
     export class KHR_materials_pbrSpecularGlossiness extends GLTFLoaderExtension {
         public readonly name = NAME;
 
-        /** @hidden */
         protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
             return this._loadExtensionAsync<IKHRMaterialsPbrSpecularGlossiness>(context, material, (extensionContext, extension) => {
                 material._babylonData = material._babylonData || {};

+ 20 - 20
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -40,8 +40,8 @@ module BABYLON.GLTF2 {
          */
         protected _loadSceneAsync(context: string, node: _ILoaderScene): Nullable<Promise<void>> { return null; }
 
-        /** 
-         * Override this method to modify the default behavior for loading nodes. 
+        /**
+         * Override this method to modify the default behavior for loading nodes.
          * @hidden
          */
         protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>> { return null; }
@@ -58,22 +58,22 @@ module BABYLON.GLTF2 {
          */
         protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> { return null; }
 
-        /** 
-         * Override this method to modify the default behavior for loading textures. 
+        /**
+         * Override this method to modify the default behavior for loading textures.
          * @hidden
          */
         protected _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Nullable<Promise<void>> { return null; }
 
-        /** 
-         * Override this method to modify the default behavior for loading uris. 
+        /**
+         * Override this method to modify the default behavior for loading uris.
          * @hidden
          */
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>> { return null; }
 
         // #endregion
 
-        /** 
-         * Helper method called by a loader extension to load an glTF extension. 
+        /**
+         * Helper method called by a loader extension to load an glTF extension.
          * @hidden
          */
         protected _loadExtensionAsync<TProperty, TResult = void>(context: string, property: IProperty, actionAsync: (extensionContext: string, extension: TProperty) => Nullable<Promise<TResult>>): Nullable<Promise<TResult>> {
@@ -128,48 +128,48 @@ module BABYLON.GLTF2 {
             }
         }
 
-        /** 
-         * Helper method called by the loader to allow extensions to override loading scenes. 
+        /**
+         * Helper method called by the loader to allow extensions to override loading scenes.
          * @hidden
          */
         public static _LoadSceneAsync(loader: GLTFLoader, context: string, scene: _ILoaderScene): Nullable<Promise<void>> {
             return loader._applyExtensions(extension => extension._loadSceneAsync(context, scene));
         }
 
-        /** 
-         * Helper method called by the loader to allow extensions to override loading nodes. 
+        /**
+         * Helper method called by the loader to allow extensions to override loading nodes.
          * @hidden
          */
         public static _LoadNodeAsync(loader: GLTFLoader, context: string, node: _ILoaderNode): Nullable<Promise<void>> {
             return loader._applyExtensions(extension => extension._loadNodeAsync(context, node));
         }
 
-        /** 
-         * Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. 
+        /**
+         * Helper method called by the loader to allow extensions to override loading mesh primitive vertex data.
          * @hidden
          */
         public static _LoadVertexDataAsync(loader: GLTFLoader, context: string, primitive: _ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> {
             return loader._applyExtensions(extension => extension._loadVertexDataAsync(context, primitive, babylonMesh));
         }
 
-        /** 
-         * Helper method called by the loader to allow extensions to override loading materials. 
+        /**
+         * Helper method called by the loader to allow extensions to override loading materials.
          * @hidden
          */
         public static _LoadMaterialAsync(loader: GLTFLoader, context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
             return loader._applyExtensions(extension => extension._loadMaterialAsync(context, material, mesh, babylonMesh, babylonDrawMode, assign));
         }
 
-        /** 
-         * Helper method called by the loader to allow extensions to override loading textures. 
+        /**
+         * Helper method called by the loader to allow extensions to override loading textures.
          * @hidden
          */
         public static _LoadTextureAsync(loader: GLTFLoader, context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Nullable<Promise<void>> {
             return loader._applyExtensions(extension => extension._loadTextureAsync(context, textureInfo, assign));
         }
 
-        /** 
-         * Helper method called by the loader to allow extensions to override loading uris. 
+        /**
+         * Helper method called by the loader to allow extensions to override loading uris.
          * @hidden
          */
         public static _LoadUriAsync(loader: GLTFLoader, context: string, uri: string): Nullable<Promise<ArrayBufferView>> {

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

@@ -188,16 +188,10 @@ module BABYLON {
      * File loader for loading glTF files into a scene.
      */
     export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
-        /**
-         * Factory function that creates a glTF 1.0 loader
-         * @hidden
-         */
+        /** @hidden */
         public static _CreateGLTFLoaderV1: () => IGLTFLoader;
 
-        /**
-         * Factory function that creates a glTF 2.0 loader
-         * @hidden
-         */
+        /** @hidden */
         public static _CreateGLTFLoaderV2: () => IGLTFLoader;
 
         // #region Common options
@@ -227,12 +221,14 @@ module BABYLON {
          * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders.
          * Textures always loads asynchronously. For example, the success callback can compute the bounding information of the loaded meshes when incremental loading is disabled.
          * Defaults to true.
+         * @hidden
          */
         public static IncrementalLoading = true;
 
         /**
          * Set this property to true in order to work with homogeneous coordinates, available with some converters and exporters.
          * Defaults to false. See https://en.wikipedia.org/wiki/Homogeneous_coordinates.
+         * @hidden
          */
         public static HomogeneousCoordinates = false;
 

+ 0 - 4
serializers/src/glTF/2.0/babylon.glTFExporter.ts

@@ -1,9 +1,5 @@
 /// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
 
-/**
- * Module for the Babylon glTF 2.0 exporter.  Should ONLY be used internally
- * @hidden 
- */
 module BABYLON.GLTF2 {
     /** 
      * Utility interface for storing vertex attribute data

+ 16 - 30
src/Behaviors/Mesh/babylon.pointerDragBehavior.ts

@@ -6,7 +6,7 @@ module BABYLON {
         private _attachedNode: Node; 
         private _dragPlane: Mesh;
         private _scene:Scene;
-        private _pointerObserver:Nullable<Observer<PointerInfoPre>>;
+        private _pointerObserver:Nullable<Observer<PointerInfo>>;
         private static _planeScene:Scene;
         private _draggingID = -1;
         
@@ -38,9 +38,9 @@ module BABYLON {
         
         /**
          * Creates a pointer drag behavior that can be attached to a mesh
-         * @param options The drag axis or normal of the plane that will be dragged across. pointerObservableScene can be used to listen to drag events from another scene(eg. if the attached mesh is in an overlay scene).
+         * @param options The drag axis or normal of the plane that will be dragged across.
          */
-        constructor(private options:{dragAxis?:Vector3, dragPlaneNormal?:Vector3, pointerObservableScene?:Scene}){
+        constructor(private options:{dragAxis?:Vector3, dragPlaneNormal?:Vector3}){
             var optionCount = 0;
             if(options.dragAxis){
                 optionCount++;
@@ -74,9 +74,6 @@ module BABYLON {
          */
         public attach(ownerNode: Mesh): void {
             this._scene = ownerNode.getScene();
-            if(!this.options.pointerObservableScene){
-                this.options.pointerObservableScene = this._scene;
-            }
             this._attachedNode = ownerNode;
 
             // Initialize drag plane to not interfere with existing scene
@@ -95,43 +92,32 @@ module BABYLON {
                 return this._attachedNode == m || m.isDescendantOf(this._attachedNode)
             }
 
-            this._pointerObserver = this.options.pointerObservableScene!.onPrePointerObservable.add((pointerInfoPre, eventState)=>{
+            this._pointerObserver = this._scene.onPointerObservable.add((pointerInfo, eventState)=>{
                 if(!this.enabled){
                     return;
                 }
-                // Check if attached mesh is picked
-                var pickInfo = pointerInfoPre.ray ? this._scene.pickWithRay(pointerInfoPre.ray, pickPredicate) : this._scene.pick(this._scene.pointerX, this._scene.pointerY, pickPredicate);
-                if(pickInfo){
-                    pickInfo.ray = pointerInfoPre.ray;
-                    if(!pickInfo.ray){
-                        pickInfo.ray = this.options.pointerObservableScene!.createPickingRay(this._scene.pointerX, this._scene.pointerY, Matrix.Identity(), this._scene.activeCamera);
-                    }
-                    if(pickInfo.hit && pointerInfoPre.type == BABYLON.PointerEventTypes.POINTERDOWN){
-                        pointerInfoPre.skipOnPointerObservable = true;
-                    }
-                }
                 
-                if (pointerInfoPre.type == BABYLON.PointerEventTypes.POINTERDOWN) {
-                    if(!dragging && pickInfo && pickInfo.hit && pickInfo.pickedMesh && pickInfo.ray){
-                        this._updateDragPlanePosition(pickInfo.ray);
-                        var pickedPoint = this._pickWithRayOnDragPlane(pickInfo.ray);
+                if (pointerInfo.type == BABYLON.PointerEventTypes.POINTERDOWN) {
+                    if(!dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)){
+                        this._updateDragPlanePosition(pointerInfo.pickInfo.ray);
+                        var pickedPoint = this._pickWithRayOnDragPlane(pointerInfo.pickInfo.ray);
                         if(pickedPoint){
                             dragging = true;
-                            this._draggingID = (<PointerEvent>pointerInfoPre.event).pointerId;
+                            this._draggingID = (<PointerEvent>pointerInfo.event).pointerId;
                             lastPosition.copyFrom(pickedPoint);
                             this.onDragStartObservable.notifyObservers({dragPlanePoint: pickedPoint});
                         }
                     }
-                }else if(pointerInfoPre.type == BABYLON.PointerEventTypes.POINTERUP){
-                    if(this._draggingID == (<PointerEvent>pointerInfoPre.event).pointerId){
+                }else if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERUP){
+                    if(this._draggingID == (<PointerEvent>pointerInfo.event).pointerId){
                         dragging = false;
                         this._draggingID = -1;
                         this.onDragEndObservable.notifyObservers({dragPlanePoint: lastPosition});
                     }
-                }else if(pointerInfoPre.type == BABYLON.PointerEventTypes.POINTERMOVE){
-                    if(this._draggingID == (<PointerEvent>pointerInfoPre.event).pointerId && dragging && pickInfo && pickInfo.ray){
-                        var pickedPoint = this._pickWithRayOnDragPlane(pickInfo.ray);
-                        this._updateDragPlanePosition(pickInfo.ray);
+                }else if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERMOVE){
+                    if(this._draggingID == (<PointerEvent>pointerInfo.event).pointerId && dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.ray){
+                        var pickedPoint = this._pickWithRayOnDragPlane(pointerInfo.pickInfo.ray);
+                        this._updateDragPlanePosition(pointerInfo.pickInfo.ray);
                         if (pickedPoint) {
                             // depending on the drag mode option drag accordingly
                             if(this.options.dragAxis){
@@ -195,7 +181,7 @@ module BABYLON {
          */
         public detach(): void {
             if(this._pointerObserver){
-                this._scene.onPrePointerObservable.remove(this._pointerObserver);
+                this._scene.onPointerObservable.remove(this._pointerObserver);
             }
         }
     }

+ 1 - 1
src/Gizmos/babylon.axisDragGizmo.ts

@@ -35,7 +35,7 @@ module BABYLON {
             this._rootMesh.lookAt(this._rootMesh.position.subtract(dragAxis));
 
             // Add drag behavior to handle events when the gizmo is dragged
-            this._dragBehavior = new PointerDragBehavior({dragAxis: dragAxis, pointerObservableScene: gizmoLayer.originalScene});
+            this._dragBehavior = new PointerDragBehavior({dragAxis: dragAxis});
             this._dragBehavior.moveAttached = false;
             this._rootMesh.addBehavior(this._dragBehavior);
             this._dragBehavior.onDragObservable.add((event)=>{

+ 1 - 1
src/Gizmos/babylon.axisScaleGizmo.ts

@@ -35,7 +35,7 @@ module BABYLON {
             this._rootMesh.lookAt(this._rootMesh.position.subtract(dragAxis));
 
             // Add drag behavior to handle events when the gizmo is dragged
-            this._dragBehavior = new PointerDragBehavior({dragAxis: dragAxis, pointerObservableScene: gizmoLayer.originalScene});
+            this._dragBehavior = new PointerDragBehavior({dragAxis: dragAxis});
             this._dragBehavior.moveAttached = false;
             this._rootMesh.addBehavior(this._dragBehavior);
 

+ 82 - 0
src/Gizmos/babylon.gizmoManager.ts

@@ -0,0 +1,82 @@
+module BABYLON {
+    /**
+     * Helps setup gizmo's in the scene to rotate/scale/position meshes
+     */
+    export class GizmoManager implements IDisposable{
+
+        private _gizmoLayer:UtilityLayerRenderer;
+        // Set of gizmos that are currently in the scene for each mesh
+        private _gizmoSet:{[meshID: string]: {positionGizmo: PositionGizmo, rotationGizmo: RotationGizmo}} = {}
+        private _pointerObserver:Nullable<Observer<PointerInfo>> = null;
+
+        /**
+         * Instatiates a gizmo manager
+         * @param scene the scene to overlay the gizmos on top of
+         * @param options If only a single gizmo should exist at one time
+         */
+        constructor(private scene:Scene, options?:{singleGizmo?:boolean}){
+            this._gizmoLayer = new UtilityLayerRenderer(scene);
+
+            // Options parsing
+            if(!options){
+                options = {}
+            }
+            if(options.singleGizmo === undefined){
+                options.singleGizmo = true;
+            }
+
+            // Instatiate/dispose gizmos based on pointer actions
+            this._pointerObserver = scene.onPointerObservable.add((pointerInfo, state)=>{
+                if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERDOWN){
+                    if(pointerInfo.pickInfo && pointerInfo.pickInfo.pickedMesh){
+                        if(!this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId]){
+                            if(options!.singleGizmo){
+                                this._clearGizmos();
+                            }                            
+                            // Enable gizmo when mesh is selected
+                            this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId] = {positionGizmo: new PositionGizmo(this._gizmoLayer), rotationGizmo: new RotationGizmo(this._gizmoLayer)}
+                            this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId].positionGizmo.attachedMesh = pointerInfo.pickInfo.pickedMesh;
+                            this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId].rotationGizmo.attachedMesh = pointerInfo.pickInfo.pickedMesh;
+                        }else{
+                            if(!options!.singleGizmo){
+                                // Disable gizmo when clicked again
+                                this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId].positionGizmo.dispose();
+                                this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId].rotationGizmo.dispose();
+                                delete this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId];
+                            }
+                        }
+                    }else {
+                        if(options!.singleGizmo){
+                            // Disable gizmo when clicked away
+                            if(pointerInfo.pickInfo && pointerInfo.pickInfo.ray){
+                                var gizmoPick = this._gizmoLayer.utilityLayerScene.pickWithRay(pointerInfo.pickInfo.ray);
+                                if(gizmoPick && !gizmoPick.hit){
+                                    this._clearGizmos();
+                                }
+                            }
+                        }
+                    }
+                }
+            })
+        }
+
+        /**
+         * Disposes of the gizmo manager
+         */
+        public dispose(){
+            this.scene.onPointerObservable.remove(this._pointerObserver);
+            this._clearGizmos();
+            this._gizmoLayer.dispose();
+        }
+
+        private _clearGizmos(){
+            for(var key in this._gizmoSet){
+                if(this._gizmoSet.hasOwnProperty(key)){
+                    this._gizmoSet[key].positionGizmo.dispose();
+                    this._gizmoSet[key].rotationGizmo.dispose();
+                    delete this._gizmoSet[key];
+                }
+            }
+        }
+    }
+}

+ 1 - 1
src/Gizmos/babylon.planeRotationGizmo.ts

@@ -29,7 +29,7 @@ module BABYLON {
             this._rootMesh.lookAt(this._rootMesh.position.subtract(planeNormal));
 
             // Add drag behavior to handle events when the gizmo is dragged
-            this._dragBehavior = new PointerDragBehavior({dragPlaneNormal: planeNormal, pointerObservableScene: gizmoLayer.originalScene});
+            this._dragBehavior = new PointerDragBehavior({dragPlaneNormal: planeNormal});
             this._dragBehavior.moveAttached = false;
             this._rootMesh.addBehavior(this._dragBehavior);
 

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

@@ -3392,7 +3392,7 @@
             for (index = 0; index < meshes.length; index++) {
                 if (meshes[index]) {
                     meshes[index].computeWorldMatrix(true);
-                    otherVertexData = VertexData.ExtractFromMesh(meshes[index], true);
+                    otherVertexData = VertexData.ExtractFromMesh(meshes[index], true, true);
                     otherVertexData.transform(meshes[index].getWorldMatrix());
 
                     if (vertexData) {
@@ -3432,12 +3432,12 @@
             // Subdivide
             if (subdivideWithSubMeshes) {
 
-                //-- Suppresions du submesh global
+                //-- removal of global submesh
                 meshSubclass.releaseSubMeshes();
                 index = 0;
                 var offset = 0;
 
-                //-- aplique la subdivision en fonction du tableau d'indices
+                //-- apply subdivision according to index table
                 while (index < indiceArray.length) {
                     SubMesh.CreateFromIndices(0, offset, indiceArray[index], meshSubclass);
                     offset += indiceArray[index];
@@ -3448,4 +3448,4 @@
             return meshSubclass;
         }
     }
-}
+}

+ 52 - 1
src/Rendering/babylon.utilityLayerRenderer.ts

@@ -12,9 +12,13 @@ module BABYLON {
          *  If the utility layer should automatically be rendered on top of existing scene
         */
         public shouldRender:boolean = true;
-
+        /**
+         * If set to true, only pointer down onPointerObservable events will be blocked when picking is occluded by original scene
+         */
+        public onlyCheckPointerDownEvents = true;
         private _afterRenderObserver:Nullable<Observer<Scene>>;
         private _sceneDisposeObserver:Nullable<Observer<Scene>>;
+        private _originalPointerObserver:Nullable<Observer<PointerInfoPre>>;
         /**
          * Instantiates a UtilityLayerRenderer
          * @param originalScene the original scene that will be rendered on top of
@@ -24,6 +28,50 @@ module BABYLON {
             this.utilityLayerScene = new BABYLON.Scene(originalScene.getEngine());
             originalScene.getEngine().scenes.pop();
 
+            // Detach controls on utility scene, events will be fired by logic below to handle picking priority
+            this.utilityLayerScene.detachControl();
+            this._originalPointerObserver = originalScene.onPrePointerObservable.add((prePointerInfo, eventState)=>{
+                var utilityScenePick = prePointerInfo.ray ? this.utilityLayerScene.pickWithRay(prePointerInfo.ray) : this.utilityLayerScene.pick(originalScene.pointerX, originalScene.pointerY);
+                if(!prePointerInfo.ray && utilityScenePick){
+                    prePointerInfo.ray = utilityScenePick.ray;
+                }
+
+                // always fire the prepointer oversvable
+                this.utilityLayerScene.onPrePointerObservable.notifyObservers(prePointerInfo)
+
+                // allow every non pointer down event to flow to the utility layer
+                if(this.onlyCheckPointerDownEvents && prePointerInfo.type != BABYLON.PointerEventTypes.POINTERDOWN){
+                    if(!prePointerInfo.skipOnPointerObservable){
+                        this.utilityLayerScene.onPointerObservable.notifyObservers(new PointerInfo(prePointerInfo.type, prePointerInfo.event, utilityScenePick))
+                    }
+                    return;
+                }
+
+                if(this.utilityLayerScene.autoClearDepthAndStencil){
+                    // If this layer is an overlay, check if this layer was hit and if so, skip pointer events for the main scene
+                    if(utilityScenePick && utilityScenePick.hit){
+                        
+                        if(!prePointerInfo.skipOnPointerObservable){
+                            this.utilityLayerScene.onPointerObservable.notifyObservers(new PointerInfo(prePointerInfo.type, prePointerInfo.event, utilityScenePick))
+                        }
+                        prePointerInfo.skipOnPointerObservable = true;
+                    }
+                }else{
+                    var originalScenePick = prePointerInfo.ray ? originalScene.pickWithRay(prePointerInfo.ray) : originalScene.pick(originalScene.pointerX, originalScene.pointerY);
+
+                    // If the layer can be occluded by the original scene, only fire pointer events to the first layer that hit they ray
+                    if(originalScenePick && utilityScenePick){
+                        if(utilityScenePick.distance < originalScenePick.distance){
+                            if(!prePointerInfo.skipOnPointerObservable){
+                                this.utilityLayerScene.onPointerObservable.notifyObservers(new PointerInfo(prePointerInfo.type, prePointerInfo.event, utilityScenePick))
+                            }
+                            prePointerInfo.skipOnPointerObservable = true;
+                        }
+                    }
+                }
+                
+            })
+
             // Render directly on top of existing scene without clearing
             this.utilityLayerScene.autoClear = false;
 
@@ -58,6 +106,9 @@ module BABYLON {
             if(this._sceneDisposeObserver){
                 this.originalScene.onDisposeObservable.remove(this._sceneDisposeObserver);
             }
+            if(this._originalPointerObserver){
+                this.originalScene.onPrePointerObservable.remove(this._originalPointerObserver);
+            }
             this.utilityLayerScene.dispose();
         }
 

+ 6 - 3
src/babylon.scene.ts

@@ -1271,7 +1271,7 @@
         }
 
         /**
-         * Gets the debug layer associated with the scene
+         * Gets the debug layer (aka Inspector) associated with the scene
          * @see http://doc.babylonjs.com/features/playground_debuglayer
          */
         public get debugLayer(): DebugLayer {
@@ -5716,11 +5716,14 @@
             if (!PickingInfo) {
                 return null;
             }
-
-            return this._internalPick(world => {
+            var result = this._internalPick(world => {
                 this.createPickingRayToRef(x, y, world, this._tempPickingRay!, camera || null);
                 return this._tempPickingRay!;
             }, predicate, fastCheck);
+            if(result){
+                result.ray = this.createPickingRay(x, y, Matrix.Identity(), camera || null);
+            }
+            return result;
         }
 
         /** Launch a ray to try to pick a sprite in the scene