Browse Source

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

sebastien 7 years ago
parent
commit
412c24f43e
72 changed files with 18328 additions and 17630 deletions
  1. 1 0
      .gitignore
  2. 6960 6936
      Playground/babylon.d.txt
  3. 2 0
      Playground/js/index.js
  4. 5 3
      Tools/Gulp/config.json
  5. 10390 10279
      dist/preview release/babylon.d.ts
  6. 10 10
      dist/preview release/babylon.js
  7. 28 10
      dist/preview release/babylon.max.js
  8. 28 10
      dist/preview release/babylon.no-module.max.js
  9. 10 10
      dist/preview release/babylon.worker.js
  10. 28 10
      dist/preview release/es6.js
  11. 1 1
      dist/preview release/gltf2Interface/package.json
  12. 22 9
      dist/preview release/gui/babylon.gui.d.ts
  13. 65 13
      dist/preview release/gui/babylon.gui.js
  14. 2 2
      dist/preview release/gui/babylon.gui.min.js
  15. 22 9
      dist/preview release/gui/babylon.gui.module.d.ts
  16. 1 1
      dist/preview release/gui/package.json
  17. 3 3
      dist/preview release/inspector/babylon.inspector.bundle.js
  18. 34 30
      dist/preview release/inspector/babylon.inspector.css
  19. 50 50
      dist/preview release/inspector/babylon.inspector.js
  20. 4 4
      dist/preview release/inspector/babylon.inspector.min.js
  21. 1 1
      dist/preview release/inspector/package.json
  22. 2 2
      dist/preview release/loaders/package.json
  23. 1 1
      dist/preview release/materialsLibrary/package.json
  24. 1 1
      dist/preview release/postProcessesLibrary/package.json
  25. 1 1
      dist/preview release/proceduralTexturesLibrary/package.json
  26. 2 2
      dist/preview release/serializers/package.json
  27. 8 8
      dist/preview release/viewer/babylon.viewer.js
  28. 28 10
      dist/preview release/viewer/babylon.viewer.max.js
  29. 1 1
      dist/preview release/viewer/package.json
  30. 2 1
      dist/preview release/what's new.md
  31. 54 4
      gui/src/3D/controls/button3D.ts
  32. 1 1
      gui/src/3D/controls/container3D.ts
  33. 7 7
      gui/src/3D/controls/control3D.ts
  34. 2 2
      gui/src/3D/controls/holographicButton.ts
  35. 7 1
      gui/src/3D/gui3DManager.ts
  36. 6 4
      inspector/sass/_detailPanel.scss
  37. 6 6
      inspector/sass/_tabPanel.scss
  38. 6 4
      inspector/sass/_tree.scss
  39. 5 2
      inspector/sass/defines.scss
  40. 3 3
      inspector/sass/tabs/_gltfTab.scss
  41. 49 48
      inspector/src/Inspector.ts
  42. 11 2
      inspector/src/tabs/GLTFTab.ts
  43. 1 1
      inspector/src/tabs/TabBar.ts
  44. 1 1
      inspector/src/tools/PopupTool.ts
  45. 1 1
      inspector/src/tools/RefreshTool.ts
  46. 4 4
      inspector/test/index.js
  47. 1 1
      loaders/src/glTF/1.0/babylon.glTFLoader.ts
  48. 1 1
      loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts
  49. 1 1
      loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts
  50. 2 2
      loaders/src/glTF/2.0/Extensions/MSFT_lod.ts
  51. 16 20
      loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts
  52. 16 20
      loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts
  53. 17 7
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  54. 52 13
      loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts
  55. 7 2
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  56. 0 20
      loaders/src/glTF/2.0/babylon.glTFLoaderUtilities.ts
  57. 6 4
      loaders/src/glTF/babylon.glTFFileLoader.ts
  58. 1 1
      package.json
  59. 3 3
      sandbox/index-local.html
  60. 4 3
      sandbox/index.html
  61. 23 10
      sandbox/index.js
  62. 10 2
      src/Behaviors/Mesh/babylon.pointerDragBehavior.ts
  63. 1 1
      src/Engine/babylon.engine.ts
  64. 6 0
      src/Gizmos/babylon.axisDragGizmo.ts
  65. 64 0
      src/Gizmos/babylon.axisScaleGizmo.ts
  66. 18 2
      src/Gizmos/babylon.gizmo.ts
  67. 95 0
      src/Gizmos/babylon.planeRotationGizmo.ts
  68. 7 1
      src/Gizmos/babylon.positionGizmo.ts
  69. 41 0
      src/Gizmos/babylon.rotationGizmo.ts
  70. 41 0
      src/Gizmos/babylon.scaleGizmo.ts
  71. 16 7
      src/Mesh/babylon.transformNode.ts
  72. 2 0
      src/Rendering/babylon.utilityLayerRenderer.ts

+ 1 - 0
.gitignore

@@ -182,3 +182,4 @@ Viewer/dist/viewer.max.js
 Viewer/tests/unit/src/**/*.js
 Viewer/tests/Lib/**/*.js
 Viewer/tests/commons/**/*.js
+.sass-cache/

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


+ 2 - 0
Playground/js/index.js

@@ -458,6 +458,8 @@
 
             } catch (e) {
                 showError(e.message, e);
+                // Also log error in console to help debug playgrounds
+                console.error(e);
             }
         };
         window.addEventListener("resize",

+ 5 - 3
Tools/Gulp/config.json

@@ -1025,7 +1025,11 @@
                 "../../src/Rendering/babylon.utilityLayerRenderer.js",
                 "../../src/Gizmos/babylon.gizmo.js",
                 "../../src/Gizmos/babylon.axisDragGizmo.js",
-                "../../src/Gizmos/babylon.positionGizmo.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"
             ],
             "dependUpon": [
                 "shaderMaterial",
@@ -1561,7 +1565,6 @@
             {
                 "files": [
                     "../../loaders/src/glTF/babylon.glTFFileLoader.ts",
-                    "../../loaders/src/glTF/2.0/babylon.glTFLoaderUtilities.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
@@ -1586,7 +1589,6 @@
                     "../../loaders/src/glTF/1.0/babylon.glTFLoaderExtension.ts",
                     "../../loaders/src/glTF/1.0/babylon.glTFBinaryExtension.ts",
                     "../../loaders/src/glTF/1.0/babylon.glTFMaterialsCommonExtension.ts",
-                    "../../loaders/src/glTF/2.0/babylon.glTFLoaderUtilities.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",

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


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


+ 28 - 10
dist/preview release/babylon.max.js

@@ -12069,7 +12069,7 @@ var BABYLON;
              * Returns the current version of the framework
              */
             get: function () {
-                return "3.3.0-alpha.2";
+                return "3.3.0-alpha.3";
             },
             enumerable: true,
             configurable: true
@@ -18470,6 +18470,11 @@ var BABYLON;
             _this.billboardMode = TransformNode.BILLBOARDMODE_NONE;
             _this.scalingDeterminant = 1;
             _this.infiniteDistance = false;
+            /**
+             * Gets or sets a boolean indicating that non uniform scaling (when at least one component is different from others) should be ignored.
+             * By default the system will update normals to compensate
+             */
+            _this.ignoreNonUniformScaling = false;
             _this.position = BABYLON.Vector3.Zero();
             _this._localWorld = BABYLON.Matrix.Zero();
             _this._worldMatrix = BABYLON.Matrix.Zero();
@@ -18981,7 +18986,7 @@ var BABYLON;
             if (this._nonUniformScaling === value) {
                 return false;
             }
-            this._nonUniformScaling = true;
+            this._nonUniformScaling = value;
             return true;
         };
         /**
@@ -19236,14 +19241,16 @@ var BABYLON;
                 this._worldMatrix.multiplyToRef(this._pivotMatrixInverse, this._worldMatrix);
             }
             // Normal matrix
-            if (this.scaling.isNonUniform) {
-                this._updateNonUniformScalingState(true);
-            }
-            else if (this.parent && this.parent._nonUniformScaling) {
-                this._updateNonUniformScalingState(this.parent._nonUniformScaling);
-            }
-            else {
-                this._updateNonUniformScalingState(false);
+            if (!this.ignoreNonUniformScaling) {
+                if (this.scaling.isNonUniform) {
+                    this._updateNonUniformScalingState(true);
+                }
+                else if (this.parent && this.parent._nonUniformScaling) {
+                    this._updateNonUniformScalingState(this.parent._nonUniformScaling);
+                }
+                else {
+                    this._updateNonUniformScalingState(false);
+                }
             }
             this._afterComputeWorldMatrix();
             // Absolute position
@@ -19387,6 +19394,9 @@ var BABYLON;
             BABYLON.serialize()
         ], TransformNode.prototype, "infiniteDistance", void 0);
         __decorate([
+            BABYLON.serialize()
+        ], TransformNode.prototype, "ignoreNonUniformScaling", void 0);
+        __decorate([
             BABYLON.serializeAsVector3()
         ], TransformNode.prototype, "position", void 0);
         return TransformNode;
@@ -45103,6 +45113,14 @@ var BABYLON;
             },
             /**
              * Sets the transparency mode of the material.
+             *
+             * | Value | Type                                | Description |
+             * | ----- | ----------------------------------- | ----------- |
+             * | 0     | OPAQUE                              |             |
+             * | 1     | ALPHATEST                           |             |
+             * | 2     | ALPHABLEND                          |             |
+             * | 3     | ALPHATESTANDBLEND                   |             |
+             *
              */
             set: function (value) {
                 if (this._transparencyMode === value) {

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

@@ -12036,7 +12036,7 @@ var BABYLON;
              * Returns the current version of the framework
              */
             get: function () {
-                return "3.3.0-alpha.2";
+                return "3.3.0-alpha.3";
             },
             enumerable: true,
             configurable: true
@@ -18437,6 +18437,11 @@ var BABYLON;
             _this.billboardMode = TransformNode.BILLBOARDMODE_NONE;
             _this.scalingDeterminant = 1;
             _this.infiniteDistance = false;
+            /**
+             * Gets or sets a boolean indicating that non uniform scaling (when at least one component is different from others) should be ignored.
+             * By default the system will update normals to compensate
+             */
+            _this.ignoreNonUniformScaling = false;
             _this.position = BABYLON.Vector3.Zero();
             _this._localWorld = BABYLON.Matrix.Zero();
             _this._worldMatrix = BABYLON.Matrix.Zero();
@@ -18948,7 +18953,7 @@ var BABYLON;
             if (this._nonUniformScaling === value) {
                 return false;
             }
-            this._nonUniformScaling = true;
+            this._nonUniformScaling = value;
             return true;
         };
         /**
@@ -19203,14 +19208,16 @@ var BABYLON;
                 this._worldMatrix.multiplyToRef(this._pivotMatrixInverse, this._worldMatrix);
             }
             // Normal matrix
-            if (this.scaling.isNonUniform) {
-                this._updateNonUniformScalingState(true);
-            }
-            else if (this.parent && this.parent._nonUniformScaling) {
-                this._updateNonUniformScalingState(this.parent._nonUniformScaling);
-            }
-            else {
-                this._updateNonUniformScalingState(false);
+            if (!this.ignoreNonUniformScaling) {
+                if (this.scaling.isNonUniform) {
+                    this._updateNonUniformScalingState(true);
+                }
+                else if (this.parent && this.parent._nonUniformScaling) {
+                    this._updateNonUniformScalingState(this.parent._nonUniformScaling);
+                }
+                else {
+                    this._updateNonUniformScalingState(false);
+                }
             }
             this._afterComputeWorldMatrix();
             // Absolute position
@@ -19354,6 +19361,9 @@ var BABYLON;
             BABYLON.serialize()
         ], TransformNode.prototype, "infiniteDistance", void 0);
         __decorate([
+            BABYLON.serialize()
+        ], TransformNode.prototype, "ignoreNonUniformScaling", void 0);
+        __decorate([
             BABYLON.serializeAsVector3()
         ], TransformNode.prototype, "position", void 0);
         return TransformNode;
@@ -45070,6 +45080,14 @@ var BABYLON;
             },
             /**
              * Sets the transparency mode of the material.
+             *
+             * | Value | Type                                | Description |
+             * | ----- | ----------------------------------- | ----------- |
+             * | 0     | OPAQUE                              |             |
+             * | 1     | ALPHATEST                           |             |
+             * | 2     | ALPHABLEND                          |             |
+             * | 3     | ALPHATESTANDBLEND                   |             |
+             *
              */
             set: function (value) {
                 if (this._transparencyMode === value) {

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


+ 28 - 10
dist/preview release/es6.js

@@ -12036,7 +12036,7 @@ var BABYLON;
              * Returns the current version of the framework
              */
             get: function () {
-                return "3.3.0-alpha.2";
+                return "3.3.0-alpha.3";
             },
             enumerable: true,
             configurable: true
@@ -18437,6 +18437,11 @@ var BABYLON;
             _this.billboardMode = TransformNode.BILLBOARDMODE_NONE;
             _this.scalingDeterminant = 1;
             _this.infiniteDistance = false;
+            /**
+             * Gets or sets a boolean indicating that non uniform scaling (when at least one component is different from others) should be ignored.
+             * By default the system will update normals to compensate
+             */
+            _this.ignoreNonUniformScaling = false;
             _this.position = BABYLON.Vector3.Zero();
             _this._localWorld = BABYLON.Matrix.Zero();
             _this._worldMatrix = BABYLON.Matrix.Zero();
@@ -18948,7 +18953,7 @@ var BABYLON;
             if (this._nonUniformScaling === value) {
                 return false;
             }
-            this._nonUniformScaling = true;
+            this._nonUniformScaling = value;
             return true;
         };
         /**
@@ -19203,14 +19208,16 @@ var BABYLON;
                 this._worldMatrix.multiplyToRef(this._pivotMatrixInverse, this._worldMatrix);
             }
             // Normal matrix
-            if (this.scaling.isNonUniform) {
-                this._updateNonUniformScalingState(true);
-            }
-            else if (this.parent && this.parent._nonUniformScaling) {
-                this._updateNonUniformScalingState(this.parent._nonUniformScaling);
-            }
-            else {
-                this._updateNonUniformScalingState(false);
+            if (!this.ignoreNonUniformScaling) {
+                if (this.scaling.isNonUniform) {
+                    this._updateNonUniformScalingState(true);
+                }
+                else if (this.parent && this.parent._nonUniformScaling) {
+                    this._updateNonUniformScalingState(this.parent._nonUniformScaling);
+                }
+                else {
+                    this._updateNonUniformScalingState(false);
+                }
             }
             this._afterComputeWorldMatrix();
             // Absolute position
@@ -19354,6 +19361,9 @@ var BABYLON;
             BABYLON.serialize()
         ], TransformNode.prototype, "infiniteDistance", void 0);
         __decorate([
+            BABYLON.serialize()
+        ], TransformNode.prototype, "ignoreNonUniformScaling", void 0);
+        __decorate([
             BABYLON.serializeAsVector3()
         ], TransformNode.prototype, "position", void 0);
         return TransformNode;
@@ -45070,6 +45080,14 @@ var BABYLON;
             },
             /**
              * Sets the transparency mode of the material.
+             *
+             * | Value | Type                                | Description |
+             * | ----- | ----------------------------------- | ----------- |
+             * | 0     | OPAQUE                              |             |
+             * | 1     | ALPHATEST                           |             |
+             * | 2     | ALPHABLEND                          |             |
+             * | 3     | ALPHATESTANDBLEND                   |             |
+             *
              */
             set: function (value) {
                 if (this._transparencyMode === value) {

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

@@ -1,7 +1,7 @@
 {
     "name": "babylonjs-gltf2interface",
     "description": "A typescript declaration of babylon's gltf2 inteface.",
-    "version": "3.3.0-alpha.2",
+    "version": "3.3.0-alpha.3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 22 - 9
dist/preview release/gui/babylon.gui.d.ts

@@ -1868,6 +1868,7 @@ declare module BABYLON.GUI {
 declare module BABYLON.GUI {
     /**
      * Class used to manage 3D user interface
+     * @see http://doc.babylonjs.com/how_to/gui3d
      */
     class GUI3DManager implements BABYLON.IDisposable {
         private _scene;
@@ -1920,7 +1921,7 @@ declare module BABYLON.GUI {
          */
         addControl(control: Control3D): GUI3DManager;
         /**
-         * Removes the control from the root child list
+         * Removes a control from the root child list
          * @param control defines the control to remove
          * @returns the current container
          */
@@ -2048,9 +2049,9 @@ declare module BABYLON.GUI {
         private _enterCount;
         private _downPointerIds;
         private _isVisible;
-        /** Gets or sets the control position */
+        /** Gets or sets the control position  in world space */
         position: Vector3;
-        /** Gets or sets the control scaling */
+        /** Gets or sets the control scaling  in world space */
         scaling: Vector3;
         /** Callback used to start pointer enter animation */
         pointerEnterAnimation: () => void;
@@ -2061,11 +2062,11 @@ declare module BABYLON.GUI {
         /** Callback used to start pointer up animation */
         pointerUpAnimation: () => void;
         /**
-        * An event triggered when the pointer move over the control.
+        * An event triggered when the pointer move over the control
         */
         onPointerMoveObservable: Observable<Vector3>;
         /**
-         * An event triggered when the pointer move out of the control.
+         * An event triggered when the pointer move out of the control
          */
         onPointerOutObservable: Observable<Control3D>;
         /**
@@ -2073,11 +2074,11 @@ declare module BABYLON.GUI {
          */
         onPointerDownObservable: Observable<Vector3WithInfo>;
         /**
-         * An event triggered when pointer up
+         * An event triggered when pointer is up
          */
         onPointerUpObservable: Observable<Vector3WithInfo>;
         /**
-         * An event triggered when a control is clicked on
+         * An event triggered when a control is clicked on (with a mouse)
          */
         onPointerClickObservable: Observable<Vector3WithInfo>;
         /**
@@ -2130,7 +2131,7 @@ declare module BABYLON.GUI {
         readonly typeName: string;
         protected _getTypeName(): string;
         /**
-         * Gets the mesh used to render this control
+         * Gets the transform node used by this control
          */
         readonly node: Nullable<TransformNode>;
         /**
@@ -2211,7 +2212,7 @@ declare module BABYLON.GUI {
         protected _arrangeChildren(): void;
         protected _createNode(scene: Scene): Nullable<TransformNode>;
         /**
-         * Removes the control from the children of this control
+         * Removes a control from the children of this control
          * @param control defines the control to remove
          * @returns the current container
          */
@@ -2234,6 +2235,18 @@ declare module BABYLON.GUI {
         protected _currentMaterial: Material;
         private _facadeTexture;
         private _content;
+        private _contentResolution;
+        private _contentScaleRatio;
+        /**
+         * Gets or sets the texture resolution used to render content (512 by default)
+         */
+        contentResolution: int;
+        /**
+         * Gets or sets the texture scale ratio used to render content (2 by default)
+         */
+        contentScaleRatio: number;
+        protected _disposeFaceTexture(): void;
+        private _resetContent();
         /**
          * Creates a new button
          * @param name defines the control name

+ 65 - 13
dist/preview release/gui/babylon.gui.js

@@ -6478,6 +6478,7 @@ var BABYLON;
     (function (GUI) {
         /**
          * Class used to manage 3D user interface
+         * @see http://doc.babylonjs.com/how_to/gui3d
          */
         var GUI3DManager = /** @class */ (function () {
             /**
@@ -6509,6 +6510,9 @@ var BABYLON;
                 this._rootContainer._host = this;
                 // Events
                 this._pointerObserver = this._scene.onPrePointerObservable.add(function (pi, state) {
+                    if (pi.skipOnPointerObservable) {
+                        return;
+                    }
                     var pointerEvent = (pi.event);
                     if (_this._scene.isPointerCaptured(pointerEvent.pointerId)) {
                         return;
@@ -6616,7 +6620,7 @@ var BABYLON;
                 return this;
             };
             /**
-             * Removes the control from the root child list
+             * Removes a control from the root child list
              * @param control defines the control to remove
              * @returns the current container
              */
@@ -6970,16 +6974,16 @@ var BABYLON;
                 this._enterCount = 0;
                 this._downPointerIds = {};
                 this._isVisible = true;
-                /** Gets or sets the control position */
+                /** Gets or sets the control position  in world space */
                 this.position = new BABYLON.Vector3(0, 0, 0);
-                /** Gets or sets the control scaling */
+                /** Gets or sets the control scaling  in world space */
                 this.scaling = new BABYLON.Vector3(1, 1, 1);
                 /**
-                * An event triggered when the pointer move over the control.
+                * An event triggered when the pointer move over the control
                 */
                 this.onPointerMoveObservable = new BABYLON.Observable();
                 /**
-                 * An event triggered when the pointer move out of the control.
+                 * An event triggered when the pointer move out of the control
                  */
                 this.onPointerOutObservable = new BABYLON.Observable();
                 /**
@@ -6987,11 +6991,11 @@ var BABYLON;
                  */
                 this.onPointerDownObservable = new BABYLON.Observable();
                 /**
-                 * An event triggered when pointer up
+                 * An event triggered when pointer is up
                  */
                 this.onPointerUpObservable = new BABYLON.Observable();
                 /**
-                 * An event triggered when a control is clicked on
+                 * An event triggered when a control is clicked on (with a mouse)
                  */
                 this.onPointerClickObservable = new BABYLON.Observable();
                 /**
@@ -7101,7 +7105,7 @@ var BABYLON;
             };
             Object.defineProperty(Control3D.prototype, "node", {
                 /**
-                 * Gets the mesh used to render this control
+                 * Gets the transform node used by this control
                  */
                 get: function () {
                     return this._node;
@@ -7346,7 +7350,7 @@ var BABYLON;
                 return new BABYLON.TransformNode("ContainerNode", scene);
             };
             /**
-             * Removes the control from the children of this control
+             * Removes a control from the children of this control
              * @param control defines the control to remove
              * @returns the current container
              */
@@ -7395,6 +7399,8 @@ var BABYLON;
              */
             function Button3D(name) {
                 var _this = _super.call(this, name) || this;
+                _this._contentResolution = 512;
+                _this._contentScaleRatio = 2;
                 // Default animations
                 _this.pointerEnterAnimation = function () {
                     if (!_this.mesh) {
@@ -7419,6 +7425,50 @@ var BABYLON;
                 };
                 return _this;
             }
+            Object.defineProperty(Button3D.prototype, "contentResolution", {
+                /**
+                 * Gets or sets the texture resolution used to render content (512 by default)
+                 */
+                get: function () {
+                    return this._contentResolution;
+                },
+                set: function (value) {
+                    if (this._contentResolution === value) {
+                        return;
+                    }
+                    this._contentResolution = value;
+                    this._resetContent();
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(Button3D.prototype, "contentScaleRatio", {
+                /**
+                 * Gets or sets the texture scale ratio used to render content (2 by default)
+                 */
+                get: function () {
+                    return this._contentScaleRatio;
+                },
+                set: function (value) {
+                    if (this._contentScaleRatio === value) {
+                        return;
+                    }
+                    this._contentScaleRatio = value;
+                    this._resetContent();
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Button3D.prototype._disposeFaceTexture = function () {
+                if (this._facadeTexture) {
+                    this._facadeTexture.dispose();
+                    this._facadeTexture = null;
+                }
+            };
+            Button3D.prototype._resetContent = function () {
+                this._disposeFaceTexture();
+                this.content = this._content;
+            };
             Object.defineProperty(Button3D.prototype, "content", {
                 /**
                  * Gets or sets the GUI 2D content used to display the button's facade
@@ -7430,10 +7480,11 @@ var BABYLON;
                     if (!this._host || !this._host.utilityLayer) {
                         return;
                     }
+                    this._content = value;
                     if (!this._facadeTexture) {
-                        this._facadeTexture = new BABYLON.GUI.AdvancedDynamicTexture("Facade", 512, 512, this._host.utilityLayer.utilityLayerScene, true, BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
-                        this._facadeTexture.rootContainer.scaleX = 2;
-                        this._facadeTexture.rootContainer.scaleY = 2;
+                        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;
+                        this._facadeTexture.rootContainer.scaleY = this._contentScaleRatio;
                         this._facadeTexture.premulAlpha = true;
                     }
                     this._facadeTexture.addControl(value);
@@ -7479,6 +7530,7 @@ var BABYLON;
              */
             Button3D.prototype.dispose = function () {
                 _super.prototype.dispose.call(this);
+                this._disposeFaceTexture();
                 if (this._currentMaterial) {
                     this._currentMaterial.dispose();
                 }
@@ -7525,7 +7577,6 @@ var BABYLON;
                 return _this;
             }
             Object.defineProperty(HolographicButton.prototype, "text", {
-                // private _imageUrl: string;
                 /**
                  * Gets or sets text for the button
                  */
@@ -7603,6 +7654,7 @@ var BABYLON;
                 return "HolographicButton";
             };
             HolographicButton.prototype._rebuildContent = function () {
+                this._disposeFaceTexture();
                 var panel = new GUI.StackPanel();
                 panel.isVertical = true;
                 if (this._imageUrl) {

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


+ 22 - 9
dist/preview release/gui/babylon.gui.module.d.ts

@@ -1873,6 +1873,7 @@ declare module BABYLON.GUI {
 declare module BABYLON.GUI {
     /**
      * Class used to manage 3D user interface
+     * @see http://doc.babylonjs.com/how_to/gui3d
      */
     class GUI3DManager implements BABYLON.IDisposable {
         private _scene;
@@ -1925,7 +1926,7 @@ declare module BABYLON.GUI {
          */
         addControl(control: Control3D): GUI3DManager;
         /**
-         * Removes the control from the root child list
+         * Removes a control from the root child list
          * @param control defines the control to remove
          * @returns the current container
          */
@@ -2053,9 +2054,9 @@ declare module BABYLON.GUI {
         private _enterCount;
         private _downPointerIds;
         private _isVisible;
-        /** Gets or sets the control position */
+        /** Gets or sets the control position  in world space */
         position: Vector3;
-        /** Gets or sets the control scaling */
+        /** Gets or sets the control scaling  in world space */
         scaling: Vector3;
         /** Callback used to start pointer enter animation */
         pointerEnterAnimation: () => void;
@@ -2066,11 +2067,11 @@ declare module BABYLON.GUI {
         /** Callback used to start pointer up animation */
         pointerUpAnimation: () => void;
         /**
-        * An event triggered when the pointer move over the control.
+        * An event triggered when the pointer move over the control
         */
         onPointerMoveObservable: Observable<Vector3>;
         /**
-         * An event triggered when the pointer move out of the control.
+         * An event triggered when the pointer move out of the control
          */
         onPointerOutObservable: Observable<Control3D>;
         /**
@@ -2078,11 +2079,11 @@ declare module BABYLON.GUI {
          */
         onPointerDownObservable: Observable<Vector3WithInfo>;
         /**
-         * An event triggered when pointer up
+         * An event triggered when pointer is up
          */
         onPointerUpObservable: Observable<Vector3WithInfo>;
         /**
-         * An event triggered when a control is clicked on
+         * An event triggered when a control is clicked on (with a mouse)
          */
         onPointerClickObservable: Observable<Vector3WithInfo>;
         /**
@@ -2135,7 +2136,7 @@ declare module BABYLON.GUI {
         readonly typeName: string;
         protected _getTypeName(): string;
         /**
-         * Gets the mesh used to render this control
+         * Gets the transform node used by this control
          */
         readonly node: Nullable<TransformNode>;
         /**
@@ -2216,7 +2217,7 @@ declare module BABYLON.GUI {
         protected _arrangeChildren(): void;
         protected _createNode(scene: Scene): Nullable<TransformNode>;
         /**
-         * Removes the control from the children of this control
+         * Removes a control from the children of this control
          * @param control defines the control to remove
          * @returns the current container
          */
@@ -2239,6 +2240,18 @@ declare module BABYLON.GUI {
         protected _currentMaterial: Material;
         private _facadeTexture;
         private _content;
+        private _contentResolution;
+        private _contentScaleRatio;
+        /**
+         * Gets or sets the texture resolution used to render content (512 by default)
+         */
+        contentResolution: int;
+        /**
+         * Gets or sets the texture scale ratio used to render content (2 by default)
+         */
+        contentScaleRatio: number;
+        protected _disposeFaceTexture(): void;
+        private _resetContent();
         /**
          * Creates a new button
          * @param name defines the control name

+ 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.3.0-alpha.2",
+    "version": "3.3.0-alpha.3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

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


+ 34 - 30
dist/preview release/inspector/babylon.inspector.css

@@ -1,7 +1,7 @@
-@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css);
+@import url(https://use.fontawesome.com/releases/v5.0.13/css/all.css);
 @import url(https://fonts.googleapis.com/css?family=Inconsolata);
 
-@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css);
+@import url(https://use.fontawesome.com/releases/v5.0.13/css/all.css);
 @import url(https://fonts.googleapis.com/css?family=Inconsolata);
 .insp-wrapper {
   user-select: none;
@@ -44,11 +44,11 @@
       font-size: 1em; }
       .insp-wrapper .insp-right-panel .top-panel .tab-panel-content {
         width: 100%;
-        height: calc(100% - 40px); }
+        height: calc(100% - 50px); }
       .insp-wrapper .insp-right-panel .top-panel .more-tabs-panel {
         position: absolute;
         z-index: 10;
-        top: 40px;
+        top: 50px;
         right: 0;
         width: 100px;
         display: none;
@@ -70,7 +70,7 @@
             background-color: #454545; }
   .insp-wrapper .tooltip {
     position: absolute;
-    top: 40px;
+    top: 50px;
     right: 0;
     color: #f29766;
     display: none;
@@ -115,15 +115,15 @@
         height: 1em;
         line-height: 1em;
         display: inline-block;
-        font-family: 'FontAwesome', sans-serif;
-        content: "\f10c";
+        font-family: "Font Awesome 5 Free", sans-serif;
+        content: "\f111";
         margin-right: 10px; }
       .insp-wrapper .tab-panel .scene-actions .action-radio.active:before {
         width: 1em;
         height: 1em;
         line-height: 1em;
         display: inline-block;
-        font-family: 'FontAwesome', sans-serif;
+        font-family: "Font Awesome 5 Free", sans-serif;
         content: "\f192";
         color: #5db0d7;
         margin-right: 10px; }
@@ -132,15 +132,15 @@
         height: 1em;
         line-height: 1em;
         display: inline-block;
-        font-family: 'FontAwesome', sans-serif;
-        content: "\f096";
+        font-family: "Font Awesome 5 Free", sans-serif;
+        content: "\f0c8";
         margin-right: 10px; }
       .insp-wrapper .tab-panel .scene-actions .action.active:before {
         width: 1em;
         height: 1em;
         line-height: 1em;
         display: inline-block;
-        font-family: 'FontAwesome', sans-serif;
+        font-family: "Font Awesome 5 Free", sans-serif;
         content: "\f14a";
         color: #5db0d7;
         margin-right: 10px; }
@@ -263,15 +263,15 @@
       height: 1em;
       line-height: 1em;
       display: inline-block;
-      font-family: 'FontAwesome', sans-serif;
-      content: "\f096";
+      font-family: "Font Awesome 5 Free", sans-serif;
+      content: "\f0c8";
       margin-right: 10px; }
     .insp-wrapper .tab-panel .gltf-actions .gltf-checkbox.active:before {
       width: 1em;
       height: 1em;
       line-height: 1em;
       display: inline-block;
-      font-family: 'FontAwesome', sans-serif;
+      font-family: "Font Awesome 5 Free", sans-serif;
       content: "\f14a";
       color: #5db0d7;
       margin-right: 10px; }
@@ -304,7 +304,7 @@
   .insp-wrapper .insp-tree {
     overflow-y: auto;
     overflow-x: hidden;
-    height: calc(50% - 40px - 30px); }
+    height: calc(50% - 50px - 30px); }
     .insp-wrapper .insp-tree .line {
       padding: 3px;
       cursor: pointer; }
@@ -319,15 +319,17 @@
         height: 1em;
         line-height: 1em;
         display: inline-block;
-        font-family: 'FontAwesome', sans-serif;
-        content: "\f078"; }
+        font-family: "Font Awesome 5 Free", sans-serif;
+        content: "\f107";
+        font-weight: 900; }
       .insp-wrapper .insp-tree .line.folded:before {
         width: 1em;
         height: 1em;
         line-height: 1em;
         display: inline-block;
-        font-family: 'FontAwesome', sans-serif;
-        content: "\f054"; }
+        font-family: "Font Awesome 5 Free", sans-serif;
+        content: "\f105";
+        font-weight: 900; }
       .insp-wrapper .insp-tree .line.unfolded.transformNode > span:first-of-type {
         color: #f29766; }
       .insp-wrapper .insp-tree .line.folded.transformNode > span:first-of-type {
@@ -366,13 +368,15 @@
           .insp-wrapper .insp-details .base-row .prop-value.clickable:hover, .insp-wrapper .insp-details .row .prop-value.clickable:hover, .insp-wrapper .insp-details .header-row .prop-value.clickable:hover {
             background-color: #383838; }
           .insp-wrapper .insp-details .base-row .prop-value.clickable:after, .insp-wrapper .insp-details .row .prop-value.clickable:after, .insp-wrapper .insp-details .header-row .prop-value.clickable:after {
-            font-family: 'FontAwesome', sans-serif;
-            content: "\00a0 \00a0 \00a0 \f054"; }
+            font-family: "Font Awesome 5 Free", sans-serif;
+            content: "\00a0 \00a0 \00a0 \f105";
+            font-weight: 900; }
     .insp-wrapper .insp-details .row:nth-child(even) {
       background-color: #2c2c2c; }
     .insp-wrapper .insp-details .row.unfolded .prop-value.clickable:after {
-      font-family: 'FontAwesome', sans-serif;
-      content: "\00a0 \00a0 \00a0 \f078"; }
+      font-family: "Font Awesome 5 Free", sans-serif;
+      content: "\00a0 \00a0 \00a0 \f107";
+      font-weight: 900; }
     .insp-wrapper .insp-details .header-row {
       background-color: #2c2c2c;
       color: #ccc;
@@ -423,7 +427,7 @@
           max-width: 110px;
           max-height: 110px; }
   .insp-wrapper .tabbar {
-    height: 40px;
+    height: 50px;
     display: flex;
     align-items: center;
     border-bottom: 1px solid #383838;
@@ -432,11 +436,11 @@
     overflow-y: hidden;
     box-sizing: border-box; }
     .insp-wrapper .tabbar .tab {
-      height: calc(40px - 2px);
+      height: calc(50px - 2px);
       width: auto;
       padding: 0 10px 0 10px;
       color: #ccc;
-      line-height: 40px;
+      line-height: 50px;
       text-align: center;
       cursor: pointer;
       margin: 0 5px 0 5px;
@@ -449,8 +453,8 @@
       .insp-wrapper .tabbar .tab.active {
         border-bottom: 1px solid #f29766; }
     .insp-wrapper .tabbar .more-tabs {
-      width: 40px;
-      height: 40px;
+      width: 50px;
+      height: 50px;
       display: flex;
       justify-content: center;
       align-items: center;
@@ -467,8 +471,8 @@
   .insp-wrapper .toolbar {
     display: flex; }
     .insp-wrapper .toolbar .tool {
-      width: 40px;
-      height: 40px;
+      width: 50px;
+      height: 50px;
       display: flex;
       justify-content: center;
       align-items: center;

+ 50 - 50
dist/preview release/inspector/babylon.inspector.js

@@ -146,10 +146,14 @@ var INSPECTOR;
                 INSPECTOR.Helpers.SEND_EVENT('resize');
                 this._tabbar.updateWidth();
             }
-            // Refresh the inspector if the browser is not edge
-            if (!INSPECTOR.Helpers.IsBrowserEdge()) {
-                this.refresh();
-            }
+            /*
+            * Refresh the inspector if the browser is not edge
+            *   Why not ?! Condition commented on 180525
+            *   To be tested
+            */
+            // if (!Helpers.IsBrowserEdge()) {
+            this.refresh();
+            // }
             // Check custom css colors
             if (newColors) {
                 var bColor = newColors.backgroundColor || '#242424';
@@ -297,52 +301,48 @@ var INSPECTOR;
          */
         Inspector.prototype.openPopup = function (firstTime) {
             var _this = this;
-            if (INSPECTOR.Helpers.IsBrowserEdge()) {
-                console.warn('Inspector - Popup mode is disabled in Edge, as the popup DOM cannot be updated from the main window for security reasons');
+            // Create popup
+            var popup = window.open('', 'Babylon.js INSPECTOR', 'toolbar=no,resizable=yes,menubar=no,width=750,height=1000');
+            if (!popup) {
+                return;
             }
-            else {
-                // Create popup
-                var popup = window.open('', 'Babylon.js INSPECTOR', 'toolbar=no,resizable=yes,menubar=no,width=750,height=1000');
-                if (!popup) {
-                    return;
-                }
-                popup.document.title = 'Babylon.js INSPECTOR';
-                // Get the inspector style      
-                var styles = Inspector.DOCUMENT.querySelectorAll('style');
-                for (var s = 0; s < styles.length; s++) {
-                    popup.document.body.appendChild(styles[s].cloneNode(true));
+            popup.document.title = "Babylon.js INSPECTOR";
+            popup.document.body.innerHTML = "Coucou!";
+            // Get the inspector style      
+            var styles = Inspector.DOCUMENT.querySelectorAll('style');
+            for (var s = 0; s < styles.length; s++) {
+                popup.document.body.appendChild(styles[s].cloneNode(true));
+            }
+            var links = document.querySelectorAll('link');
+            for (var l = 0; l < links.length; l++) {
+                var link = popup.document.createElement("link");
+                link.rel = "stylesheet";
+                link.href = links[l].href;
+                popup.document.head.appendChild(link);
+            }
+            // Dispose the right panel if existing
+            if (!firstTime) {
+                this.dispose();
+            }
+            // set the mode as popup
+            this._popupMode = true;
+            // Save the HTML document
+            Inspector.DOCUMENT = popup.document;
+            Inspector.WINDOW = popup;
+            // Build the inspector wrapper
+            this._c2diwrapper = INSPECTOR.Helpers.CreateDiv('insp-wrapper', popup.document.body);
+            // add inspector     
+            var inspector = INSPECTOR.Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
+            inspector.classList.add('popupmode');
+            // and build it in the popup  
+            this._buildInspector(inspector);
+            // Rebuild it
+            this.refresh();
+            popup.addEventListener('resize', function () {
+                if (_this._tabbar) {
+                    _this._tabbar.updateWidth();
                 }
-                var links = document.querySelectorAll('link');
-                for (var l = 0; l < links.length; l++) {
-                    var link = popup.document.createElement("link");
-                    link.rel = "stylesheet";
-                    link.href = links[l].href;
-                    popup.document.head.appendChild(link);
-                }
-                // Dispose the right panel if existing
-                if (!firstTime) {
-                    this.dispose();
-                }
-                // set the mode as popup
-                this._popupMode = true;
-                // Save the HTML document
-                Inspector.DOCUMENT = popup.document;
-                Inspector.WINDOW = popup;
-                // Build the inspector wrapper
-                this._c2diwrapper = INSPECTOR.Helpers.CreateDiv('insp-wrapper', popup.document.body);
-                // add inspector     
-                var inspector = INSPECTOR.Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
-                inspector.classList.add('popupmode');
-                // and build it in the popup  
-                this._buildInspector(inspector);
-                // Rebuild it
-                this.refresh();
-                popup.addEventListener('resize', function () {
-                    if (_this._tabbar) {
-                        _this._tabbar.updateWidth();
-                    }
-                });
-            }
+            });
         };
         Inspector.prototype.getActiveTabIndex = function () {
             return this._tabbar.getActiveTabIndex();
@@ -4608,7 +4608,7 @@ var INSPECTOR;
     var PopupTool = /** @class */ (function (_super) {
         __extends(PopupTool, _super);
         function PopupTool(parent, inspector) {
-            return _super.call(this, 'fa-external-link', parent, inspector, 'Open the inspector in a popup') || this;
+            return _super.call(this, 'fa-external-link-alt', parent, inspector, 'Open the inspector in a popup') || this;
         }
         // Action : refresh the whole panel
         PopupTool.prototype.action = function () {
@@ -4634,7 +4634,7 @@ var INSPECTOR;
     var RefreshTool = /** @class */ (function (_super) {
         __extends(RefreshTool, _super);
         function RefreshTool(parent, inspector) {
-            return _super.call(this, 'fa-refresh', parent, inspector, 'Refresh the current tab') || this;
+            return _super.call(this, 'fa-sync', parent, inspector, 'Refresh the current tab') || this;
         }
         // Action : refresh the whole panel
         RefreshTool.prototype.action = function () {

File diff suppressed because it is too large
+ 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.3.0-alpha.2",
+    "version": "3.3.0-alpha.3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 2 - 2
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.3.0-alpha.2",
+    "version": "3.3.0-alpha.3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "3.3.0-alpha.2"
+        "babylonjs-gltf2interface": "3.3.0-alpha.3"
     },
     "peerDependencies": {
         "babylonjs": ">=3.2.0-alpha"

+ 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.3.0-alpha.2",
+    "version": "3.3.0-alpha.3",
     "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.3.0-alpha.2",
+    "version": "3.3.0-alpha.3",
     "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.3.0-alpha.2",
+    "version": "3.3.0-alpha.3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 2 - 2
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.3.0-alpha.2",
+    "version": "3.3.0-alpha.3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "3.3.0-alpha.2"
+        "babylonjs-gltf2interface": "3.3.0-alpha.3"
     },
     "peerDependencies": {
         "babylonjs": ">=3.2.0-alpha"

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


+ 28 - 10
dist/preview release/viewer/babylon.viewer.max.js

@@ -12157,7 +12157,7 @@ var BABYLON;
              * Returns the current version of the framework
              */
             get: function () {
-                return "3.3.0-alpha.2";
+                return "3.3.0-alpha.3";
             },
             enumerable: true,
             configurable: true
@@ -18558,6 +18558,11 @@ var BABYLON;
             _this.billboardMode = TransformNode.BILLBOARDMODE_NONE;
             _this.scalingDeterminant = 1;
             _this.infiniteDistance = false;
+            /**
+             * Gets or sets a boolean indicating that non uniform scaling (when at least one component is different from others) should be ignored.
+             * By default the system will update normals to compensate
+             */
+            _this.ignoreNonUniformScaling = false;
             _this.position = BABYLON.Vector3.Zero();
             _this._localWorld = BABYLON.Matrix.Zero();
             _this._worldMatrix = BABYLON.Matrix.Zero();
@@ -19069,7 +19074,7 @@ var BABYLON;
             if (this._nonUniformScaling === value) {
                 return false;
             }
-            this._nonUniformScaling = true;
+            this._nonUniformScaling = value;
             return true;
         };
         /**
@@ -19324,14 +19329,16 @@ var BABYLON;
                 this._worldMatrix.multiplyToRef(this._pivotMatrixInverse, this._worldMatrix);
             }
             // Normal matrix
-            if (this.scaling.isNonUniform) {
-                this._updateNonUniformScalingState(true);
-            }
-            else if (this.parent && this.parent._nonUniformScaling) {
-                this._updateNonUniformScalingState(this.parent._nonUniformScaling);
-            }
-            else {
-                this._updateNonUniformScalingState(false);
+            if (!this.ignoreNonUniformScaling) {
+                if (this.scaling.isNonUniform) {
+                    this._updateNonUniformScalingState(true);
+                }
+                else if (this.parent && this.parent._nonUniformScaling) {
+                    this._updateNonUniformScalingState(this.parent._nonUniformScaling);
+                }
+                else {
+                    this._updateNonUniformScalingState(false);
+                }
             }
             this._afterComputeWorldMatrix();
             // Absolute position
@@ -19475,6 +19482,9 @@ var BABYLON;
             BABYLON.serialize()
         ], TransformNode.prototype, "infiniteDistance", void 0);
         __decorate([
+            BABYLON.serialize()
+        ], TransformNode.prototype, "ignoreNonUniformScaling", void 0);
+        __decorate([
             BABYLON.serializeAsVector3()
         ], TransformNode.prototype, "position", void 0);
         return TransformNode;
@@ -45191,6 +45201,14 @@ var BABYLON;
             },
             /**
              * Sets the transparency mode of the material.
+             *
+             * | Value | Type                                | Description |
+             * | ----- | ----------------------------------- | ----------- |
+             * | 0     | OPAQUE                              |             |
+             * | 1     | ALPHATEST                           |             |
+             * | 2     | ALPHABLEND                          |             |
+             * | 3     | ALPHATESTANDBLEND                   |             |
+             *
              */
             set: function (value) {
                 if (this._transparencyMode === value) {

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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-viewer",
     "description": "A simple-to-use viewer based on BabylonJS to display 3D elements natively",
-    "version": "3.3.0-alpha.2",
+    "version": "3.3.0-alpha.3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

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

@@ -22,7 +22,8 @@
 - 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 gizmo ([TrevorDev](https://github.com/TrevorDev))
+- Gizmo 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
 

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

@@ -7,8 +7,54 @@ module BABYLON.GUI {
     export class Button3D extends Control3D {
         /** @hidden */
         protected _currentMaterial: Material;
-        private _facadeTexture: AdvancedDynamicTexture;
+        private _facadeTexture: Nullable<AdvancedDynamicTexture>;
         private _content: Control;
+        private _contentResolution = 512;
+        private _contentScaleRatio = 2;
+
+        /**
+         * Gets or sets the texture resolution used to render content (512 by default)
+         */
+        public get contentResolution(): int {
+            return this._contentResolution;
+        }
+
+        public set contentResolution(value: int) {
+            if (this._contentResolution === value) {
+                return;
+            }
+
+            this._contentResolution = value;
+            this._resetContent();
+        }
+
+        /**
+         * Gets or sets the texture scale ratio used to render content (2 by default)
+         */
+        public get contentScaleRatio(): number {
+            return this._contentScaleRatio;
+        }
+
+        public set contentScaleRatio(value: number) {
+            if (this._contentScaleRatio === value) {
+                return;
+            }
+
+            this._contentScaleRatio = value;
+            this._resetContent();
+        }   
+        
+        protected _disposeFacadeTexture() {
+            if (this._facadeTexture) {
+                this._facadeTexture.dispose();
+                this._facadeTexture = null;
+            }
+        }
+
+        private _resetContent() {
+            this._disposeFacadeTexture();
+            this.content = this._content;
+        }
 
         /**
          * Creates a new button
@@ -59,10 +105,12 @@ module BABYLON.GUI {
                 return;
             }
 
+            this._content = value;
+
             if (!this._facadeTexture) {
-                this._facadeTexture = new BABYLON.GUI.AdvancedDynamicTexture("Facade", 512, 512, this._host.utilityLayer.utilityLayerScene, true, BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
-                this._facadeTexture.rootContainer.scaleX = 2;
-                this._facadeTexture.rootContainer.scaleY = 2;
+                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;
+                this._facadeTexture.rootContainer.scaleY = this._contentScaleRatio;
                 this._facadeTexture.premulAlpha = true;
             }
             
@@ -117,6 +165,8 @@ module BABYLON.GUI {
         public dispose() {
             super.dispose();
 
+            this._disposeFaceTexture();
+
             if (this._currentMaterial) {
                 this._currentMaterial.dispose();
             }

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

@@ -68,7 +68,7 @@ module BABYLON.GUI {
         }
 
         /**
-         * Removes the control from the children of this control
+         * Removes a control from the children of this control
          * @param control defines the control to remove
          * @returns the current container
          */

+ 7 - 7
gui/src/3D/controls/control3D.ts

@@ -13,9 +13,9 @@ module BABYLON.GUI {
         private _downPointerIds:{[id:number] : boolean} = {};
         private _isVisible = true;
     
-        /** Gets or sets the control position */
+        /** Gets or sets the control position  in world space */
         public position = new Vector3(0, 0, 0);
-        /** Gets or sets the control scaling */
+        /** Gets or sets the control scaling  in world space */
         public scaling = new Vector3(1, 1, 1);
 
         /** Callback used to start pointer enter animation */
@@ -28,12 +28,12 @@ module BABYLON.GUI {
         public pointerUpAnimation: () => void;
 
         /**
-        * An event triggered when the pointer move over the control.
+        * An event triggered when the pointer move over the control
         */
         public onPointerMoveObservable = new Observable<Vector3>();
 
         /**
-         * An event triggered when the pointer move out of the control.
+         * An event triggered when the pointer move out of the control
          */
         public onPointerOutObservable = new Observable<Control3D>();
 
@@ -43,12 +43,12 @@ module BABYLON.GUI {
         public onPointerDownObservable = new Observable<Vector3WithInfo>();
 
         /**
-         * An event triggered when pointer up
+         * An event triggered when pointer is up
          */
         public onPointerUpObservable = new Observable<Vector3WithInfo>();
 
         /**
-         * An event triggered when a control is clicked on
+         * An event triggered when a control is clicked on (with a mouse)
          */
         public onPointerClickObservable = new Observable<Vector3WithInfo>();
 
@@ -175,7 +175,7 @@ module BABYLON.GUI {
         }
 
         /**
-         * Gets the mesh used to render this control
+         * Gets the transform node used by this control
          */
         public get node(): Nullable<TransformNode> {
             return this._node;

+ 2 - 2
gui/src/3D/controls/holographicButton.ts

@@ -16,8 +16,6 @@ module BABYLON.GUI {
         private _plateMaterial: StandardMaterial;
         private _pickedPointObserver: Nullable<Observer<Nullable<Vector3>>>;
 
-        // private _imageUrl: string;
-
         /**
          * Gets or sets text for the button
          */
@@ -108,6 +106,8 @@ module BABYLON.GUI {
         }        
 
         private _rebuildContent(): void {
+            this._disposeFacadeTexture();
+
             let panel = new StackPanel();
             panel.isVertical = true;
 

+ 7 - 1
gui/src/3D/gui3DManager.ts

@@ -3,6 +3,7 @@
 module BABYLON.GUI {
     /**
      * Class used to manage 3D user interface
+     * @see http://doc.babylonjs.com/how_to/gui3d
      */
     export class GUI3DManager implements BABYLON.IDisposable {
         private _scene: Scene;
@@ -56,6 +57,11 @@ module BABYLON.GUI {
             
             // Events
             this._pointerObserver = this._scene.onPrePointerObservable.add((pi, state) => {
+
+                if (pi.skipOnPointerObservable) {
+                    return;
+                }
+
                 let pointerEvent = <PointerEvent>(pi.event);
                 if (this._scene.isPointerCaptured(pointerEvent.pointerId)) {
                     return;
@@ -163,7 +169,7 @@ module BABYLON.GUI {
         }
 
         /**
-         * Removes the control from the root child list
+         * Removes a control from the root child list
          * @param control defines the control to remove
          * @returns the current container
          */

+ 6 - 4
inspector/sass/_detailPanel.scss

@@ -38,8 +38,9 @@
                 background-color:$background-lighter2;
             }
             &:after {
-                font-family: 'FontAwesome', sans-serif;
-                content: "\00a0 \00a0 \00a0 \f054"; // 4 space before + chevron right
+                font-family: $font-family-icons;
+                content: "\00a0 \00a0 \00a0 \f105"; // 4 space before + angle-right
+                font-weight: 900; // To display solid font family
             }
         }   
     }
@@ -64,8 +65,9 @@
     }
     &.unfolded {          
         .prop-value.clickable:after {
-            font-family: 'FontAwesome', sans-serif;
-            content: "\00a0 \00a0 \00a0 \f078"; // 4 space before + chevron down
+            font-family: $font-family-icons;
+            content: "\00a0 \00a0 \00a0 \f107"; // 4 space before + angle-down
+            font-weight: 900; // To display solid font family
         }
     }
   }

+ 6 - 6
inspector/sass/_tabPanel.scss

@@ -43,8 +43,8 @@
                 height     : 1em;
                 line-height: 1em;
                 display    : inline-block;
-                font-family: 'FontAwesome', sans-serif;
-                content    : "\f10c";
+                font-family: $font-family-icons;
+                content    : "\f111";
                 margin-right:10px;
             }
             // radio button active
@@ -54,7 +54,7 @@
                     height     : 1em;
                     line-height: 1em;
                     display    : inline-block;
-                    font-family: 'FontAwesome', sans-serif;
+                    font-family: $font-family-icons;
                     content    : "\f192";
                     color      : $color-bot;
                     margin-right:10px;
@@ -70,8 +70,8 @@
                 height     : 1em;
                 line-height: 1em;
                 display    : inline-block;
-                font-family: 'FontAwesome', sans-serif;
-                content    : "\f096";
+                font-family: $font-family-icons;
+                content    : "\f0c8";
                 margin-right:10px;
             }
                 
@@ -81,7 +81,7 @@
                     height     : 1em;
                     line-height: 1em;
                     display    : inline-block;
-                    font-family: 'FontAwesome', sans-serif;
+                    font-family: $font-family-icons;
                     content    : "\f14a";
                     color      : $color-bot;
                     margin-right:10px;

+ 6 - 4
inspector/sass/_tree.scss

@@ -34,16 +34,18 @@
             height     : 1em;
             line-height: 1em;
             display    : inline-block;
-            font-family: 'FontAwesome', sans-serif;
-            content    : "\f078";            
+            font-family: $font-family-icons;
+            content    : "\f107";
+            font-weight: 900;          
         }
         &.folded:before{            
             width      : 1em;
             height     : 1em;
             line-height: 1em;
             display    : inline-block;
-            font-family: 'FontAwesome', sans-serif;
-            content    : "\f054";
+            font-family: $font-family-icons;
+            content    : "\f105";
+            font-weight: 900;
         }
         
         &.unfolded.transformNode > span:first-of-type{

+ 5 - 2
inspector/sass/defines.scss

@@ -1,4 +1,5 @@
-@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css);
+// @import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css);
+@import url(https://use.fontawesome.com/releases/v5.0.13/css/all.css);
 @import url(https://fonts.googleapis.com/css?family=Inconsolata);
 
 $font               : 'Inconsolata', sans-serif;
@@ -20,5 +21,7 @@ $background-lighter2: lighten($color: $background-lighter, $amount : 5%);
 $background-lighter3: lighten($color: $background-lighter2, $amount: 5%);
 
 $resizebar-width    : 10px;
-$tabbar-height      : 40px;
+$tabbar-height      : 50px;
 $searchbar-height   : 30px;
+
+$font-family-icons  : 'Font Awesome 5 Free', sans-serif;

+ 3 - 3
inspector/sass/tabs/_gltfTab.scss

@@ -29,8 +29,8 @@
                 height     : 1em;
                 line-height: 1em;
                 display    : inline-block;
-                font-family: 'FontAwesome', sans-serif;
-                content    : "\f096";
+                font-family: $font-family-icons;
+                content    : "\f0c8";
                 margin-right:10px;
             }
 
@@ -40,7 +40,7 @@
                     height     : 1em;
                     line-height: 1em;
                     display    : inline-block;
-                    font-family: 'FontAwesome', sans-serif;
+                    font-family: $font-family-icons;
                     content    : "\f14a";
                     color      : $color-bot;
                     margin-right:10px;

+ 49 - 48
inspector/src/Inspector.ts

@@ -200,10 +200,14 @@ module INSPECTOR {
                 this._tabbar.updateWidth();
             }
 
-            // Refresh the inspector if the browser is not edge
-            if (!Helpers.IsBrowserEdge()) {
+            /*
+            * Refresh the inspector if the browser is not edge
+            *   Why not ?! Condition commented on 180525
+            *   To be tested
+            */
+            // if (!Helpers.IsBrowserEdge()) {
                 this.refresh();
-            }
+            // }
 
             // Check custom css colors
             if (newColors) {
@@ -365,52 +369,49 @@ module INSPECTOR {
          */
         public openPopup(firstTime?: boolean) {
 
-            if (Helpers.IsBrowserEdge()) {
-                console.warn('Inspector - Popup mode is disabled in Edge, as the popup DOM cannot be updated from the main window for security reasons');
-            } else {
-                // Create popup
-                let popup = window.open('', 'Babylon.js INSPECTOR', 'toolbar=no,resizable=yes,menubar=no,width=750,height=1000');
-                if (!popup) {
-                    return;
-                }
-                popup.document.title = 'Babylon.js INSPECTOR';
-                // Get the inspector style      
-                let styles = Inspector.DOCUMENT.querySelectorAll('style');
-                for (let s = 0; s < styles.length; s++) {
-                    popup.document.body.appendChild(styles[s].cloneNode(true));
-                }
-                let links = document.querySelectorAll('link');
-                for (let l = 0; l < links.length; l++) {
-                    let link = popup.document.createElement("link");
-                    link.rel = "stylesheet";
-                    link.href = (links[l] as HTMLLinkElement).href;
-                    popup.document.head.appendChild(link);
-                }
-                // Dispose the right panel if existing
-                if (!firstTime) {
-                    this.dispose();
-                }
-                // set the mode as popup
-                this._popupMode = true;
-                // Save the HTML document
-                Inspector.DOCUMENT = popup.document;
-                Inspector.WINDOW = popup;
-                // Build the inspector wrapper
-                this._c2diwrapper = Helpers.CreateDiv('insp-wrapper', popup.document.body);
-                // add inspector     
-                let inspector = Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
-                inspector.classList.add('popupmode');
-                // and build it in the popup  
-                this._buildInspector(inspector);
-                // Rebuild it
-                this.refresh();
-
-                popup.addEventListener('resize', () => {
-                    if (this._tabbar) {
-                        this._tabbar.updateWidth()
-                    }
-                });
+            // Create popup
+            let popup = window.open('', 'Babylon.js INSPECTOR', 'toolbar=no,resizable=yes,menubar=no,width=750,height=1000');
+            if (!popup) {
+                return;
             }
+            popup.document.title = "Babylon.js INSPECTOR";
+            popup.document.body.innerHTML = "Coucou!";
+            // Get the inspector style      
+            let styles = Inspector.DOCUMENT.querySelectorAll('style');
+            for (let s = 0; s < styles.length; s++) {
+                popup.document.body.appendChild(styles[s].cloneNode(true));
+            }
+            let links = document.querySelectorAll('link');
+            for (let l = 0; l < links.length; l++) {
+                let link = popup.document.createElement("link");
+                link.rel = "stylesheet";
+                link.href = (links[l] as HTMLLinkElement).href;
+                popup.document.head.appendChild(link);
+            }
+            // Dispose the right panel if existing
+            if (!firstTime) {
+                this.dispose();
+            }
+            // set the mode as popup
+            this._popupMode = true;
+            // Save the HTML document
+            Inspector.DOCUMENT = popup.document;
+            Inspector.WINDOW = popup;
+            // Build the inspector wrapper
+            this._c2diwrapper = Helpers.CreateDiv('insp-wrapper', popup.document.body);
+            // add inspector     
+            let inspector = Helpers.CreateDiv('insp-right-panel', this._c2diwrapper);
+            inspector.classList.add('popupmode');
+            // and build it in the popup  
+            this._buildInspector(inspector);
+            // Rebuild it
+            this.refresh();
+
+            popup.addEventListener('resize', () => {
+                if (this._tabbar) {
+                    this._tabbar.updateWidth()
+                }
+            });
         }
 
         public getActiveTabIndex(): number {

+ 11 - 2
inspector/src/tabs/GLTFTab.ts

@@ -19,6 +19,10 @@ module INSPECTOR {
         private _detailsPanel: DetailPanel | null = null;
         private _split: any;
 
+        public static get IsSupported(): boolean {
+            return !!(BABYLON.SceneLoader && BABYLON.GLTFFileLoader && BABYLON.GLTF2.GLTFLoader) || !!BABYLON.GLTF2Export;
+        }
+
         /** @hidden */
         public static _Initialize(): void {
             // Must register with OnPluginActivatedObservable as early as possible to
@@ -45,8 +49,13 @@ module INSPECTOR {
                 this._closeDetailsPanel();
             });
 
-            this._addImport();
-            this._addExport();
+            if (BABYLON.SceneLoader && BABYLON.GLTFFileLoader && BABYLON.GLTF2.GLTFLoader) {
+                this._addImport();
+            }
+
+            if (BABYLON.GLTF2Export) {
+                this._addExport();
+            }
         }
 
         public dispose() {

+ 1 - 1
inspector/src/tabs/TabBar.ts

@@ -32,7 +32,7 @@ module INSPECTOR {
             this._tabs.push(this._meshTab);
             this._tabs.push(new LightTab(this, this._inspector));
             this._tabs.push(new MaterialTab(this, this._inspector));
-            if (BABYLON.GLTF2Export) {
+            if (GLTFTab.IsSupported) {
                 this._tabs.push(new GLTFTab(this, this._inspector));
             }
             if (BABYLON.GUI) {

+ 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', parent, inspector, 'Open the inspector in a popup');
+            super('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-refresh', parent, inspector, 'Refresh the current tab');
+            super('fa-sync', parent, inspector, 'Refresh the current tab');
         }
 
         // Action : refresh the whole panel

+ 4 - 4
inspector/test/index.js

@@ -77,10 +77,10 @@ var Test = (function () {
         }
 
         let t = 0;
-        // scene.registerBeforeRender(() => {
-        //     ground.rotation.y += 0.01;
-        //     ground.position.y = Math.cos(t += 0.01);
-        // });
+        scene.registerBeforeRender(() => {
+            ground.rotation.y += 0.01;
+            ground.position.y = Math.cos(t += 0.01);
+        });
 
         scene.createDefaultCameraOrLight(true);
         scene.activeCamera.attachControl(canvas);

+ 1 - 1
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -1820,5 +1820,5 @@ module BABYLON.GLTF1 {
         }
     };
 
-    GLTFFileLoader.CreateGLTFLoaderV1 = () => new GLTFLoader();
+    GLTFFileLoader._CreateGLTFLoaderV1 = () => new GLTFLoader();
 }

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

@@ -18,7 +18,7 @@ module BABYLON.GLTF2.Extensions {
         public readonly name = NAME;
 
         /** @hidden */
-        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+        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 || {};
                 let babylonData = material._babylonData[babylonDrawMode];

+ 1 - 1
loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts

@@ -9,7 +9,7 @@ module BABYLON.GLTF2.Extensions {
     export class KHR_materials_unlit extends GLTFLoaderExtension {
         public readonly name = NAME;
 
-        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
             return this._loadExtensionAsync<{}>(context, material, () => {
                 material._babylonData = material._babylonData || {};
                 let babylonData = material._babylonData[babylonDrawMode];

+ 2 - 2
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -121,7 +121,7 @@ module BABYLON.GLTF2.Extensions {
             });
         }
 
-        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
             // Don't load material LODs if already loading a node LOD.
             if (this._loadingNodeLOD) {
                 return null;
@@ -142,7 +142,7 @@ module BABYLON.GLTF2.Extensions {
                         }
                     }
 
-                    const promise = this._loader._loadMaterialAsync(`#/materials/${materialLOD._index}`, materialLOD, babylonMesh, babylonDrawMode, indexLOD === 0 ? assign : () => {}).then(() => {
+                    const promise = this._loader._loadMaterialAsync(`#/materials/${materialLOD._index}`, materialLOD, mesh, babylonMesh, babylonDrawMode, indexLOD === 0 ? assign : () => {}).then(() => {
                         if (indexLOD !== 0) {
                             const babylonDataLOD = materialLOD._babylonData!;
                             assign(babylonDataLOD[babylonDrawMode].material);

+ 16 - 20
loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts

@@ -7,29 +7,25 @@ module BABYLON.GLTF2.Extensions {
     export class MSFT_minecraftMesh extends GLTFLoaderExtension {
         public readonly name = NAME;
 
-        constructor(loader: GLTFLoader) {
-            super(loader);
+        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+            return this._loadExtrasValueAsync<boolean>(context, mesh, (extensionContext, value) => {
+                if (value) {
+                    return this._loader._loadMaterialAsync(context, material, mesh, babylonMesh, babylonDrawMode, (babylonMaterial: PBRMaterial) => {
+                        if (babylonMaterial.needAlphaBlending()) {
+                            babylonMaterial.forceDepthWrite = true;
+                            babylonMaterial.separateCullingPass = true;
+                        }
 
-            const meshes = loader._gltf.meshes;
-            if (meshes && meshes.length) {
-                for (const mesh of meshes) {
-                    if (mesh && mesh.extras && mesh.extras.MSFT_minecraftMesh) {
-                        this._loader.onMaterialLoadedObservable.add(this._onMaterialLoaded);
-                        break;
-                    }
-                }
-            }
-        }
+                        babylonMaterial.backFaceCulling = babylonMaterial.forceDepthWrite;
+                        babylonMaterial.twoSidedLighting = true;
 
-        private _onMaterialLoaded = (material: PBRMaterial): void => {
-            if (material.needAlphaBlending()) {
-                material.forceDepthWrite = true;
-                material.separateCullingPass = true;
-            }
+                        assign(babylonMaterial);
+                    });
+                }
 
-            material.backFaceCulling = material.forceDepthWrite;
-            material.twoSidedLighting = true;
-        };
+                return null;
+            });
+        }
     }
 
     GLTFLoader._Register(NAME, loader => new MSFT_minecraftMesh(loader));

+ 16 - 20
loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts

@@ -7,29 +7,25 @@ module BABYLON.GLTF2.Extensions {
     export class MSFT_sRGBFactors extends GLTFLoaderExtension {
         public readonly name = NAME;
 
-        constructor(loader: GLTFLoader) {
-            super(loader);
+        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+            return this._loadExtrasValueAsync<boolean>(context, material, (extensionContext, value) => {
+                if (value) {
+                    return this._loader._loadMaterialAsync(context, material, mesh, babylonMesh, babylonDrawMode, (babylonMaterial: PBRMaterial) => {
+                        if (!babylonMaterial.albedoTexture) {
+                            babylonMaterial.albedoColor.toLinearSpaceToRef(babylonMaterial.albedoColor);
+                        }
 
-            const materials = loader._gltf.materials;
-            if (materials && materials.length) {
-                for (const material of materials) {
-                    if (material && material.extras && material.extras.MSFT_sRGBFactors) {
-                        this._loader.onMaterialLoadedObservable.add(this._onMaterialLoaded);
-                        break;
-                    }
-                }
-            }
-        }
+                        if (!babylonMaterial.reflectivityTexture) {
+                            babylonMaterial.reflectivityColor.toLinearSpaceToRef(babylonMaterial.reflectivityColor);
+                        }
 
-        private _onMaterialLoaded = (material: PBRMaterial): void => {
-            if (!material.albedoTexture) {
-                material.albedoColor.toLinearSpaceToRef(material.albedoColor);
-            }
+                        assign(babylonMaterial);
+                    });
+                }
 
-            if (!material.reflectivityTexture) {
-                material.reflectivityColor.toLinearSpaceToRef(material.reflectivityColor);
-            }
-        };
+                return null;
+            });
+        }
     }
 
     GLTFLoader._Register(NAME, loader => new MSFT_sRGBFactors(loader));

+ 17 - 7
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -10,6 +10,16 @@ module BABYLON.GLTF2 {
         _total?: number;
     }
 
+    class _ArrayItem {
+        public static Assign(values?: _IArrayItem[]): void {
+            if (values) {
+                for (let index = 0; index < values.length; index++) {
+                    values[index]._index = index;
+                }
+            }
+        }
+    }
+
     /**
      * Loader for loading a glTF 2.0 asset
      */
@@ -520,7 +530,7 @@ module BABYLON.GLTF2 {
 
             const promises = new Array<Promise<void>>();
 
-            const babylonMesh = new Mesh(node.name || `node${node._index}`, this._babylonScene, node._parent._babylonMesh);
+            const babylonMesh = new Mesh(node.name || `node${node._index}`, this._babylonScene, node._parent ? node._parent._babylonMesh : null);
             node._babylonMesh = babylonMesh;
 
             GLTFLoader._LoadTransform(node, babylonMesh);
@@ -598,7 +608,7 @@ module BABYLON.GLTF2 {
             }
             else {
                 const material = GLTFLoader._GetProperty(`${context}/material}`, this._gltf.materials, primitive.material);
-                promises.push(this._loadMaterialAsync(`#/materials/${material._index}`, material, babylonMesh, babylonDrawMode, babylonMaterial => {
+                promises.push(this._loadMaterialAsync(`#/materials/${material._index}`, material, mesh, babylonMesh, babylonDrawMode, babylonMaterial => {
                     babylonMesh.material = babylonMaterial;
                 }));
             }
@@ -822,7 +832,7 @@ module BABYLON.GLTF2 {
             }
 
             let babylonParentBone: Nullable<Bone> = null;
-            if (node._parent._babylonMesh !== this._rootBabylonMesh) {
+            if (node._parent && node._parent._babylonMesh !== this._rootBabylonMesh) {
                 babylonParentBone = this._loadBone(node._parent, skin, babylonBones);
             }
 
@@ -1336,8 +1346,8 @@ module BABYLON.GLTF2 {
         }
 
         /** @hidden */
-        public _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void> {
-            const promise = GLTFLoaderExtension._LoadMaterialAsync(this, context, material, babylonMesh, babylonDrawMode, assign);
+        public _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void> {
+            const promise = GLTFLoaderExtension._LoadMaterialAsync(this, context, material, mesh, babylonMesh, babylonDrawMode, assign);
             if (promise) {
                 return promise;
             }
@@ -1347,7 +1357,7 @@ module BABYLON.GLTF2 {
             if (!babylonData) {
                 const promises = new Array<Promise<void>>();
 
-                const name = material.name || `materialSG_${material._index}`;
+                const name = material.name || `material_${material._index}`;
                 const babylonMaterial = this._createMaterial(name, babylonDrawMode);
 
                 promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
@@ -1799,5 +1809,5 @@ module BABYLON.GLTF2 {
         }
     }
 
-    GLTFFileLoader.CreateGLTFLoaderV2 = () => new GLTFLoader();
+    GLTFFileLoader._CreateGLTFLoaderV2 = () => new GLTFLoader();
 }

+ 52 - 13
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -5,9 +5,14 @@ module BABYLON.GLTF2 {
      * Abstract class that can be implemented to extend existing glTF loader behavior.
      */
     export abstract class GLTFLoaderExtension implements IGLTFLoaderExtension, IDisposable {
-        /** Gets or sets a boolean indicating if the extension is enabled */
+        /**
+         * Gets or sets a boolean indicating if the extension is enabled
+         */
         public enabled = true;
-        /** Gets or sets extension name */
+
+        /**
+         * Gets or sets extension name
+         */
         public abstract readonly name: string;
 
         protected _loader: GLTFLoader;
@@ -20,15 +25,17 @@ module BABYLON.GLTF2 {
             this._loader = loader;
         }
 
-        /** Release all resources */
+        /**
+         * Release all resources
+         */
         public dispose(): void {
             delete this._loader;
         }
 
         // #region Overridable Methods
 
-        /** 
-         * Override this method to modify the default behavior for loading scenes. 
+        /**
+         * Override this method to modify the default behavior for loading scenes.
          * @hidden
          */
         protected _loadSceneAsync(context: string, node: _ILoaderScene): Nullable<Promise<void>> { return null; }
@@ -39,18 +46,22 @@ module BABYLON.GLTF2 {
          */
         protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>> { 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
+         */
         protected _loadVertexDataAsync(context: string, primitive: _ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> { 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
          */
-        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> { return null; }
+        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. 
          * @hidden
-         */ 
+         */
         protected _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Nullable<Promise<void>> { return null; }
 
         /** 
@@ -65,7 +76,7 @@ module BABYLON.GLTF2 {
          * 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) => Promise<TResult>): Nullable<Promise<TResult>> {
+        protected _loadExtensionAsync<TProperty, TResult = void>(context: string, property: IProperty, actionAsync: (extensionContext: string, extension: TProperty) => Nullable<Promise<TResult>>): Nullable<Promise<TResult>> {
             if (!property.extensions) {
                 return null;
             }
@@ -77,7 +88,7 @@ module BABYLON.GLTF2 {
                 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 {
@@ -89,6 +100,34 @@ module BABYLON.GLTF2 {
             }
         }
 
+        /**
+         * Helper method called by the loader to allow extensions to override loading scenes.
+         * @hidden
+         */
+        protected _loadExtrasValueAsync<TProperty, TResult = void>(context: string, property: IProperty, actionAsync: (extensionContext: string, value: TProperty) => Nullable<Promise<TResult>>): Nullable<Promise<TResult>> {
+            if (!property.extras) {
+                return null;
+            }
+
+            const extras = property.extras;
+
+            const value = extras[this.name] as TProperty;
+            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
@@ -117,8 +156,8 @@ module BABYLON.GLTF2 {
          * Helper method called by the loader to allow extensions to override loading materials. 
          * @hidden
          */
-        public static _LoadMaterialAsync(loader: GLTFLoader, context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
-            return loader._applyExtensions(extension => extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign));
+        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));
         }
 
         /** 

+ 7 - 2
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -3,6 +3,11 @@
 
 module BABYLON.GLTF2 {
     /** @hidden */
+    export interface _IArrayItem {
+        _index: number;
+    }
+
+    /** @hidden */
     export interface _ILoaderAccessor extends IAccessor, _IArrayItem {
         _data?: Promise<ArrayBufferView>;
         _babylonVertexBuffer?: Promise<VertexBuffer>;
@@ -21,7 +26,7 @@ module BABYLON.GLTF2 {
 
     /** @hidden */
     export interface _ILoaderAnimationSampler extends IAnimationSampler, _IArrayItem {
-        _data: Promise<_ILoaderAnimationSamplerData>;
+        _data?: Promise<_ILoaderAnimationSamplerData>;
     }
 
     /** @hidden */
@@ -74,7 +79,7 @@ module BABYLON.GLTF2 {
 
     /** @hidden */
     export interface _ILoaderNode extends INode, _IArrayItem {
-        _parent: _ILoaderNode;
+        _parent?: _ILoaderNode;
         _babylonMesh?: Mesh;
         _primitiveBabylonMeshes?: Mesh[];
         _babylonBones?: Bone[];

+ 0 - 20
loaders/src/glTF/2.0/babylon.glTFLoaderUtilities.ts

@@ -1,20 +0,0 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GLTF2 {
-    /** @hidden */
-    export interface _IArrayItem {
-        _index: number;
-    }
-
-    /** @hidden */
-    export class _ArrayItem {
-        /** @hidden */
-        public static Assign(values?: _IArrayItem[]): void {
-            if (values) {
-                for (let index = 0; index < values.length; index++) {
-                    values[index]._index = index;
-                }
-            }
-        }
-    }
-}

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

@@ -190,13 +190,15 @@ module BABYLON {
     export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
         /**
          * Factory function that creates a glTF 1.0 loader
+         * @hidden
          */
-        public static CreateGLTFLoaderV1: () => IGLTFLoader;
+        public static _CreateGLTFLoaderV1: () => IGLTFLoader;
 
         /**
          * Factory function that creates a glTF 2.0 loader
+         * @hidden
          */
-        public static CreateGLTFLoaderV2: () => IGLTFLoader;
+        public static _CreateGLTFLoaderV2: () => IGLTFLoader;
 
         // #region Common options
 
@@ -577,8 +579,8 @@ module BABYLON {
             }
 
             const createLoaders: { [key: number]: () => IGLTFLoader } = {
-                1: GLTFFileLoader.CreateGLTFLoaderV1,
-                2: GLTFFileLoader.CreateGLTFLoaderV2
+                1: GLTFFileLoader._CreateGLTFLoaderV1,
+                2: GLTFFileLoader._CreateGLTFLoaderV2
             };
 
             const createLoader = createLoaders[version.major];

+ 1 - 1
package.json

@@ -9,7 +9,7 @@
     ],
     "name": "babylonjs",
     "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-    "version": "3.3.0-alpha.2",
+    "version": "3.3.0-alpha.3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 3 - 3
sandbox/index-local.html

@@ -33,9 +33,9 @@
             </div>
         </div>
         <div class="footerRight">
-            <a href="#" id="btnFullscreen" class="hidden"><img src="./Assets/Icon_Fullscreen.svg" alt="Switch the scene to full screen" title="Switch the scene to full screen" /></a> 
-            <a href="#" id="btnInspector" class="hidden"><img src="./Assets/Icon_EditModel.svg" alt="Display inspector" title="Display inspector" /></a> 
-            <a href="#">
+            <a href="javascript:void(null);" id="btnFullscreen" class="hidden"><img src="./Assets/Icon_Fullscreen.svg" alt="Switch the scene to full screen" title="Switch the scene to full screen" /></a> 
+            <a href="javascript:void(null);" id="btnInspector" class="hidden"><img src="./Assets/Icon_EditModel.svg" alt="Display inspector" title="Display inspector" /></a> 
+            <a href="javascript:void(null);">
                 <div class="custom-upload" title="Open your scene from your hard drive (.babylon, .gltf, .glb, .obj)">
                     <input type="file" id="files" multiple />
                 </div>

+ 4 - 3
sandbox/index.html

@@ -35,6 +35,7 @@
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
 
     <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
+    <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
 </head>
 <body>
@@ -62,9 +63,9 @@
             </div>
         </div>               
         <div class="footerRight">
-            <a href="#" id="btnFullscreen" class="hidden"><img src="./Assets/Icon_Fullscreen.svg" alt="Switch the scene to full screen" title="Switch the scene to full screen" /></a> 
-            <a href="#" id="btnInspector" class="hidden"><img src="./Assets/Icon_EditModel.svg" alt="Display inspector" title="Display inspector" /></a> 
-            <a href="#">
+            <a href="javascript:void(null);" id="btnFullscreen" class="hidden"><img src="./Assets/Icon_Fullscreen.svg" alt="Switch the scene to full screen" title="Switch the scene to full screen" /></a> 
+            <a href="javascript:void(null);" id="btnInspector" class="hidden"><img src="./Assets/Icon_EditModel.svg" alt="Display inspector" title="Display inspector" /></a> 
+            <a href="javascript:void(null);">
                 <div class="custom-upload" title="Open your scene from your hard drive (.babylon, .gltf, .glb, .obj)">
                     <input type="file" id="files" multiple />
                 </div>

+ 23 - 10
sandbox/index.js

@@ -209,12 +209,16 @@ if (BABYLON.Engine.isSupported()) {
         });
     };
 
-    if (assetUrl) {
+    var loadFromAssetUrl = function () {
         var rootUrl = BABYLON.Tools.GetFolderPath(assetUrl);
         var fileName = BABYLON.Tools.GetFilename(assetUrl);
         BABYLON.SceneLoader.LoadAsync(rootUrl, fileName, engine).then(function (scene) {
+            if (currentScene) {
+                currentScene.dispose();
+            }
+
             sceneLoaded({ name: fileName }, scene);
-            currentScene = scene;
+
             scene.whenReadyAsync().then(function () {
                 engine.runRenderLoop(function () {
                     scene.render();
@@ -223,6 +227,10 @@ if (BABYLON.Engine.isSupported()) {
         }).catch(function (reason) {
             sceneError({ name: fileName }, null, reason.message || reason);
         });
+    };
+
+    if (assetUrl) {
+        loadFromAssetUrl();
     }
     else {
         filesInput = new BABYLON.FilesInput(engine, null, sceneLoaded, null, null, null, function () { BABYLON.Tools.ClearLogCache() }, null, sceneError);
@@ -236,14 +244,6 @@ if (BABYLON.Engine.isSupported()) {
         }).bind(this);
         filesInput.monitorElementForDragNDrop(canvas);
 
-        window.addEventListener("keydown", function (event) {
-            // Press R to reload
-            if (event.keyCode === 82 && event.target.nodeName !== "INPUT") {
-                debugLayerLastActiveTab = currentScene.debugLayer.getActiveTab();
-                filesInput.reload();
-            }
-        });
-
         htmlInput.addEventListener('change', function (event) {
             var filestoLoad;
             // Handling data transfer via drag'n'drop
@@ -258,6 +258,19 @@ if (BABYLON.Engine.isSupported()) {
         }, false);
     }
 
+    window.addEventListener("keydown", function (event) {
+        // Press R to reload
+        if (event.keyCode === 82 && event.target.nodeName !== "INPUT") {
+            debugLayerLastActiveTab = currentScene.debugLayer.getActiveTab();
+            if (assetUrl) {
+                loadFromAssetUrl();
+            }
+            else {
+                filesInput.reload();
+            }
+        }
+    });
+
     if (kiosk) {
         footer.style.display = "none";
     }

+ 10 - 2
src/Behaviors/Mesh/babylon.pointerDragBehavior.ts

@@ -30,6 +30,11 @@ module BABYLON {
          *  Mesh with the position where the drag plane should be placed
          */
         public _dragPlaneParent:Nullable<Mesh>=null;
+
+        /**
+         *  If the drag behavior will react to drag events
+         */
+        public enabled = true;
         
         /**
          * Creates a pointer drag behavior that can be attached to a mesh
@@ -91,6 +96,9 @@ module BABYLON {
             }
 
             this._pointerObserver = this.options.pointerObservableScene!.onPrePointerObservable.add((pointerInfoPre, 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){
@@ -98,8 +106,8 @@ module BABYLON {
                     if(!pickInfo.ray){
                         pickInfo.ray = this.options.pointerObservableScene!.createPickingRay(this._scene.pointerX, this._scene.pointerY, Matrix.Identity(), this._scene.activeCamera);
                     }
-                    if(pickInfo.hit){
-                        eventState.skipNextObservers = true;
+                    if(pickInfo.hit && pointerInfoPre.type == BABYLON.PointerEventTypes.POINTERDOWN){
+                        pointerInfoPre.skipOnPointerObservable = true;
                     }
                 }
                 

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

@@ -710,7 +710,7 @@
          * Returns the current version of the framework
          */
         public static get Version(): string {
-            return "3.3.0-alpha.2";
+            return "3.3.0-alpha.3";
         }
 
         // Updatable statics so stick with vars here

+ 6 - 0
src/Gizmos/babylon.axisDragGizmo.ts

@@ -39,11 +39,17 @@ module BABYLON {
             this._dragBehavior.moveAttached = false;
             this._rootMesh.addBehavior(this._dragBehavior);
             this._dragBehavior.onDragObservable.add((event)=>{
+                if(!this.interactionsEnabled){
+                    return;
+                }
                 if(this.attachedMesh){
                     this.attachedMesh.position.addInPlace(event.delta);
                 }
             })
         }
+        protected _onInteractionsEnabledChanged(value:boolean){
+            this._dragBehavior.enabled = value;
+        }
         /**
          * Disposes of the gizmo
          */

+ 64 - 0
src/Gizmos/babylon.axisScaleGizmo.ts

@@ -0,0 +1,64 @@
+module BABYLON {
+    /**
+     * Single axis scale gizmo
+     */
+    export class AxisScaleGizmo extends Gizmo {
+        private _dragBehavior:PointerDragBehavior;
+        /**
+         * Creates an AxisScaleGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         * @param dragAxis The axis which the gizmo will be able to scale on
+         * @param color The color of the gizmo
+         */
+        constructor(gizmoLayer:UtilityLayerRenderer, dragAxis:Vector3, color:Color3){
+            super(gizmoLayer);
+
+            // Create Material
+            var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            coloredMaterial.disableLighting = true;
+            coloredMaterial.emissiveColor = color;
+
+            // Build mesh on root node
+            var arrowMesh = BABYLON.MeshBuilder.CreateBox("yPosMesh", {size: 1}, gizmoLayer.utilityLayerScene);
+            var arrowTail = BABYLON.MeshBuilder.CreateCylinder("yPosMesh", {diameter:0.03, height: 0.2, tessellation: 96}, gizmoLayer.utilityLayerScene);
+            this._rootMesh.addChild(arrowMesh);
+            this._rootMesh.addChild(arrowTail);
+
+            // Position arrow pointing in its drag axis
+            arrowMesh.scaling.scaleInPlace(0.1);
+            arrowMesh.material = coloredMaterial;
+            arrowMesh.rotation.x = Math.PI/2;
+            arrowMesh.position.z+=0.3;
+            arrowTail.rotation.x = Math.PI/2;
+            arrowTail.material = coloredMaterial;
+            arrowTail.position.z+=0.2;
+            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.moveAttached = false;
+            this._rootMesh.addBehavior(this._dragBehavior);
+
+            this._dragBehavior.onDragObservable.add((event)=>{
+                if(!this.interactionsEnabled){
+                    return;
+                }
+                if(this.attachedMesh){
+                    this.attachedMesh.scaling.addInPlace(event.delta);
+                }
+            })
+        }
+        
+        protected _onInteractionsEnabledChanged(value:boolean){
+            this._dragBehavior.enabled = value;
+        }
+        
+        /**
+         * Disposes of the gizmo
+         */
+        public dispose(){
+            this._dragBehavior.detach();
+            super.dispose();
+        } 
+    }
+}

+ 18 - 2
src/Gizmos/babylon.gizmo.ts

@@ -10,8 +10,24 @@ module BABYLON {
         /**
          * Mesh that the gizmo will be attached to. (eg. on a drag gizmo the mesh that will be dragged)
          */
-        public attachedMesh:Nullable<Mesh>;
+        public attachedMesh:Nullable<AbstractMesh>;
+        protected _interactionsEnabled = true;
+        protected _onInteractionsEnabledChanged(value:boolean){
+        }
+
+        /**
+         * If interactions are enabled with this gizmo. (eg. dragging/rotation)
+         */
+        public set interactionsEnabled(value:boolean){
+            this._interactionsEnabled = value;
+            this._onInteractionsEnabledChanged(value);
+        }
+        public get interactionsEnabled(){
+            return this._interactionsEnabled;
+        }
+
         private _beforeRenderObserver:Nullable<Observer<Scene>>;
+        
         /**
          * Creates a gizmo
          * @param gizmoLayer The utility layer the gizmo will be added to
@@ -20,7 +36,7 @@ module BABYLON {
             this._rootMesh = new BABYLON.Mesh("gizmoRootNode",gizmoLayer.utilityLayerScene);
             this._beforeRenderObserver = this.gizmoLayer.utilityLayerScene.onBeforeRenderObservable.add(()=>{
                 if(this.gizmoLayer.utilityLayerScene.activeCamera && this.attachedMesh){
-                    var dist = this.attachedMesh.position.subtract(this.gizmoLayer.utilityLayerScene.activeCamera.position).length()/5;
+                    var dist = this.attachedMesh.position.subtract(this.gizmoLayer.utilityLayerScene.activeCamera.position).length()/3;
                     this._rootMesh.scaling.set(dist, dist, dist);
                 }
                 if(this.attachedMesh){

+ 95 - 0
src/Gizmos/babylon.planeRotationGizmo.ts

@@ -0,0 +1,95 @@
+module BABYLON {
+    /**
+     * Single plane rotation gizmo
+     */
+    export class PlaneRotationGizmo extends Gizmo {
+        private _dragBehavior:PointerDragBehavior;
+        /**
+         * Creates a PlaneRotationGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         * @param planeNormal The normal of the plane which the gizmo will be able to rotate on
+         * @param color The color of the gizmo
+         */
+        constructor(gizmoLayer:UtilityLayerRenderer, planeNormal:Vector3, color:Color3){
+            super(gizmoLayer);
+
+            // Create Material
+            var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            coloredMaterial.disableLighting = true;
+            coloredMaterial.emissiveColor = color;
+
+            // Build mesh on root node
+            var rotationMesh = BABYLON.Mesh.CreateTorus("torus", 3, 0.3, 20, gizmoLayer.utilityLayerScene, false);
+            this._rootMesh.addChild(rotationMesh);
+
+            // Position arrow pointing in its drag axis
+            rotationMesh.scaling.scaleInPlace(0.1);
+            rotationMesh.material = coloredMaterial;
+            rotationMesh.rotation.x = Math.PI/2;
+            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.moveAttached = false;
+            this._rootMesh.addBehavior(this._dragBehavior);
+
+            var lastDragPosition:Nullable<Vector3> = null;
+
+            this._dragBehavior.onDragStartObservable.add((e)=>{
+                if(!this.interactionsEnabled){
+                    return;
+                }
+                lastDragPosition = e.dragPlanePoint;
+            })
+
+            this._dragBehavior.onDragObservable.add((event)=>{
+                if(!this.interactionsEnabled){
+                    return;
+                }
+                if(this.attachedMesh && lastDragPosition){
+                    if(!this.attachedMesh.rotationQuaternion){
+                        this.attachedMesh.rotationQuaternion = new BABYLON.Quaternion();
+                    }
+                    // Calc angle over full 360 degree (https://stackoverflow.com/questions/43493711/the-angle-between-two-3d-vectors-with-a-result-range-0-360)
+                    var newVector = event.dragPlanePoint.subtract(this.attachedMesh.position).normalize();
+                    var originalVector = lastDragPosition.subtract(this.attachedMesh.position).normalize();
+                    var cross = Vector3.Cross(newVector,originalVector);
+                    var dot = Vector3.Dot(newVector,originalVector);
+                    var angle = Math.atan2(cross.length(), dot);
+                    var up = planeNormal.clone();
+                    // Flip up vector depending on which side the camera is on
+                    if(gizmoLayer.utilityLayerScene.activeCamera){
+                        var camVec = gizmoLayer.utilityLayerScene.activeCamera.position.subtract(this.attachedMesh.position);
+                        if(Vector3.Dot(camVec, up) > 0){
+                            up.scaleInPlace(-1);
+                        }
+                    }
+                    var halfCircleSide = Vector3.Dot(up, cross) > 0.0;
+                    if (halfCircleSide) angle = -angle;
+                    
+
+                    // Convert angle and axis to quaternion (http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm)
+                    var quaternionCoefficient = Math.sin(angle/2)
+                    var amountToRotate = new BABYLON.Quaternion(up.x*quaternionCoefficient,up.y*quaternionCoefficient,up.z*quaternionCoefficient,Math.cos(angle/2));
+
+                    // Rotate selected mesh quaternion over fixed axis
+                    amountToRotate.multiplyToRef(this.attachedMesh.rotationQuaternion,this.attachedMesh.rotationQuaternion);
+
+                    lastDragPosition = event.dragPlanePoint;
+                }
+            })
+        }
+
+        protected _onInteractionsEnabledChanged(value:boolean){
+            this._dragBehavior.enabled = value;
+        }
+
+        /**
+         * Disposes of the gizmo
+         */
+        public dispose(){
+            this._dragBehavior.detach();
+            super.dispose();
+        } 
+    }
+}

+ 7 - 1
src/Gizmos/babylon.positionGizmo.ts

@@ -7,7 +7,7 @@ module BABYLON {
         private _yDrag:AxisDragGizmo;
         private _zDrag:AxisDragGizmo;
 
-        public set attachedMesh(mesh:Nullable<Mesh>){
+        public set attachedMesh(mesh:Nullable<AbstractMesh>){
             this._xDrag.attachedMesh = mesh;
             this._yDrag.attachedMesh = mesh;
             this._zDrag.attachedMesh = mesh;
@@ -23,6 +23,12 @@ module BABYLON {
             this._zDrag = new AxisDragGizmo(gizmoLayer, new Vector3(0,0,1), BABYLON.Color3.FromHexString("#0984e3"));
         }
 
+        protected _onInteractionsEnabledChanged(value:boolean){
+            this._xDrag.interactionsEnabled = value
+            this._yDrag.interactionsEnabled = value
+            this._zDrag.interactionsEnabled = value
+        }
+        
         /**
          * Disposes of the gizmo
          */

+ 41 - 0
src/Gizmos/babylon.rotationGizmo.ts

@@ -0,0 +1,41 @@
+module BABYLON {
+    /**
+     * Gizmo that enables rotating a mesh along 3 axis
+     */
+    export class RotationGizmo extends Gizmo {
+        private _xDrag:PlaneRotationGizmo;
+        private _yDrag:PlaneRotationGizmo;
+        private _zDrag:PlaneRotationGizmo;
+
+        public set attachedMesh(mesh:Nullable<AbstractMesh>){
+            this._xDrag.attachedMesh = mesh;
+            this._yDrag.attachedMesh = mesh;
+            this._zDrag.attachedMesh = mesh;
+        }
+        /**
+         * Creates a RotationGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         */
+        constructor(gizmoLayer:UtilityLayerRenderer){
+            super(gizmoLayer);
+            this._xDrag = new PlaneRotationGizmo(gizmoLayer, new Vector3(1,0,0), BABYLON.Color3.FromHexString("#00b894"));
+            this._yDrag = new PlaneRotationGizmo(gizmoLayer, new Vector3(0,1,0), BABYLON.Color3.FromHexString("#d63031"));
+            this._zDrag = new PlaneRotationGizmo(gizmoLayer, new Vector3(0,0,1), BABYLON.Color3.FromHexString("#0984e3"));
+        }
+
+        protected _onInteractionsEnabledChanged(value:boolean){
+            this._xDrag.interactionsEnabled = value
+            this._yDrag.interactionsEnabled = value
+            this._zDrag.interactionsEnabled = value
+        }
+
+        /**
+         * Disposes of the gizmo
+         */
+        public dispose(){
+            this._xDrag.dispose();
+            this._yDrag.dispose();
+            this._zDrag.dispose();
+        }
+    }
+}

+ 41 - 0
src/Gizmos/babylon.scaleGizmo.ts

@@ -0,0 +1,41 @@
+module BABYLON {
+    /**
+     * Gizmo that enables scaling a mesh along 3 axis
+     */
+    export class ScaleGizmo extends Gizmo {
+        private _xDrag:AxisScaleGizmo;
+        private _yDrag:AxisScaleGizmo;
+        private _zDrag:AxisScaleGizmo;
+
+        public set attachedMesh(mesh:Nullable<AbstractMesh>){
+            this._xDrag.attachedMesh = mesh;
+            this._yDrag.attachedMesh = mesh;
+            this._zDrag.attachedMesh = mesh;
+        }
+        /**
+         * Creates a ScaleGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         */
+        constructor(gizmoLayer:UtilityLayerRenderer){
+            super(gizmoLayer);
+            this._xDrag = new AxisScaleGizmo(gizmoLayer, new Vector3(1,0,0), BABYLON.Color3.FromHexString("#00b894"));
+            this._yDrag = new AxisScaleGizmo(gizmoLayer, new Vector3(0,1,0), BABYLON.Color3.FromHexString("#d63031"));
+            this._zDrag = new AxisScaleGizmo(gizmoLayer, new Vector3(0,0,1), BABYLON.Color3.FromHexString("#0984e3"));
+        }
+
+        protected _onInteractionsEnabledChanged(value:boolean){
+            this._xDrag.interactionsEnabled = value
+            this._yDrag.interactionsEnabled = value
+            this._zDrag.interactionsEnabled = value
+        }
+
+        /**
+         * Disposes of the gizmo
+         */
+        public dispose(){
+            this._xDrag.dispose();
+            this._yDrag.dispose();
+            this._zDrag.dispose();
+        }
+    }
+}

+ 16 - 7
src/Mesh/babylon.transformNode.ts

@@ -34,6 +34,13 @@ module BABYLON {
         @serialize()
         public infiniteDistance = false;
 
+        /**
+         * Gets or sets a boolean indicating that non uniform scaling (when at least one component is different from others) should be ignored.
+         * By default the system will update normals to compensate
+         */
+        @serialize()
+        public ignoreNonUniformScaling = false;        
+
         @serializeAsVector3()
         public position = Vector3.Zero();
 
@@ -585,7 +592,7 @@ module BABYLON {
                 return false;
             }
 
-            this._nonUniformScaling = true;
+            this._nonUniformScaling = value;
             return true;
         }
 
@@ -872,12 +879,14 @@ module BABYLON {
             }
 
             // Normal matrix
-            if (this.scaling.isNonUniform) {
-                this._updateNonUniformScalingState(true);
-            } else if (this.parent && (<TransformNode>this.parent)._nonUniformScaling) {
-                this._updateNonUniformScalingState((<TransformNode>this.parent)._nonUniformScaling);
-            } else {
-                this._updateNonUniformScalingState(false);
+            if (!this.ignoreNonUniformScaling) {
+                if (this.scaling.isNonUniform) {
+                    this._updateNonUniformScalingState(true);
+                } else if (this.parent && (<TransformNode>this.parent)._nonUniformScaling) {
+                    this._updateNonUniformScalingState((<TransformNode>this.parent)._nonUniformScaling);
+                } else {
+                    this._updateNonUniformScalingState(false);
+                }
             }
 
             this._afterComputeWorldMatrix();

+ 2 - 0
src/Rendering/babylon.utilityLayerRenderer.ts

@@ -36,6 +36,8 @@ module BABYLON {
             this._sceneDisposeObserver = this.originalScene.onDisposeObservable.add(()=>{
                 this.dispose();
             })
+            
+            this._updateCamera();
         }
 
         /**