瀏覽代碼

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

Jaskar 7 年之前
父節點
當前提交
49df0ee63d
共有 43 個文件被更改,包括 83389 次插入81278 次删除
  1. 15091 14983
      Playground/babylon.d.txt
  2. 39 13
      Tools/Gulp/config.json
  3. 20071 20030
      dist/preview release/babylon.d.ts
  4. 55 54
      dist/preview release/babylon.js
  5. 11811 11509
      dist/preview release/babylon.max.js
  6. 11811 11509
      dist/preview release/babylon.no-module.max.js
  7. 44 43
      dist/preview release/babylon.worker.js
  8. 11813 11511
      dist/preview release/es6.js
  9. 18 0
      dist/preview release/gui/babylon.gui.d.ts
  10. 79 1
      dist/preview release/gui/babylon.gui.js
  11. 2 2
      dist/preview release/gui/babylon.gui.min.js
  12. 18 0
      dist/preview release/gui/babylon.gui.module.d.ts
  13. 5 5
      dist/preview release/inspector/babylon.inspector.bundle.js
  14. 13 0
      dist/preview release/proceduralTexturesLibrary/babylon.brickProceduralTexture.d.ts
  15. 38 0
      dist/preview release/proceduralTexturesLibrary/babylon.brickProceduralTexture.js
  16. 1 1
      dist/preview release/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js
  17. 13 0
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.d.ts
  18. 33 0
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.js
  19. 1 1
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js
  20. 13 0
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.module.d.ts
  21. 53 52
      dist/preview release/viewer/babylon.viewer.js
  22. 11801 11499
      dist/preview release/viewer/babylon.viewer.max.js
  23. 6 5
      dist/preview release/what's new.md
  24. 9 0
      gui/src/2D/controls/grid.ts
  25. 66 0
      gui/src/3D/controls/cylinderPanel.ts
  26. 1 1
      gui/src/3D/controls/spherePanel.ts
  27. 97 0
      localDev/indexMini.html
  28. 28 0
      proceduralTexturesLibrary/src/brick/babylon.brickProceduralTexture.ts
  29. 44 20
      src/Behaviors/Mesh/babylon.pointerDragBehavior.ts
  30. 1 1
      src/Gizmos/babylon.axisDragGizmo.ts
  31. 1 1
      src/Gizmos/babylon.axisScaleGizmo.ts
  32. 224 0
      src/Gizmos/babylon.boundingBoxGizmo.ts
  33. 5 1
      src/Gizmos/babylon.gizmo.ts
  34. 11 7
      src/Materials/Background/babylon.backgroundMaterial.ts
  35. 11 7
      src/Materials/PBR/babylon.pbrBaseMaterial.ts
  36. 10 0
      src/Materials/Textures/Procedurals/babylon.proceduralTexture.ts
  37. 11 7
      src/Materials/babylon.standardMaterial.ts
  38. 5 1
      src/Mesh/babylon.mesh.ts
  39. 13 7
      src/PostProcess/babylon.imageProcessingPostProcess.ts
  40. 5 1
      src/Rendering/babylon.utilityLayerRenderer.ts
  41. 4 0
      src/Sprites/babylon.sprite.ts
  42. 1 1
      src/Sprites/babylon.spriteManager.ts
  43. 13 5
      src/babylon.scene.ts

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


+ 39 - 13
Tools/Gulp/config.json

@@ -116,7 +116,9 @@
             "environmentHelper",
             "particleHelper",
             "videoDome",
-            "photoDome"
+            "photoDome",
+            "behaviors",
+            "imageProcessing"            
         ],
         "minimal": [
             "freeCamera",
@@ -126,7 +128,13 @@
             "meshBuilder",
             "freeCamera",
             "hemisphericLight"
-        ]
+        ],
+        "360Viewer": [
+            "freeCamera",
+            "hemisphericLight",
+            "meshBuilder",
+            "picking"
+        ]      
     },
     "workloads": {
         "core": {
@@ -174,12 +182,7 @@
                 "../../src/Materials/babylon.uniformBuffer.js",
                 "../../src/Mesh/babylon.mesh.vertexData.js",
                 "../../src/Mesh/babylon.geometry.js",
-                "../../src/PostProcess/babylon.postProcessManager.js",
                 "../../src/Tools/babylon.performanceMonitor.js",
-                "../../src/Materials/babylon.imageProcessingConfiguration.js",
-                "../../src/Materials/Textures/babylon.colorGradingTexture.js",
-                "../../src/Materials/babylon.colorCurves.js",
-                "../../src/Behaviors/babylon.behavior.js",
                 "../../src/Materials/babylon.materialHelper.js",
                 "../../src/Materials/babylon.pushMaterial.js",
                 "../../src/Materials/babylon.standardMaterial.js"
@@ -219,7 +222,7 @@
                 "fresnelFunction",
                 "reflectionFunction",
                 "imageProcessingDeclaration",
-                "imageProcessingFunctions",
+                "imageProcessingFunctions",                
                 "bumpFragmentFunctions",
                 "clipPlaneFragmentDeclaration",
                 "fogFragmentDeclaration",
@@ -230,6 +233,24 @@
                 "fogFragment"
             ]
         },
+        "behaviors": {
+            "files": [
+                "../../src/Behaviors/babylon.behavior.js"
+            ],
+            "dependUpon": [
+                "core"
+            ]
+        },   
+        "imageProcessing": {
+            "files": [
+                "../../src/Materials/babylon.imageProcessingConfiguration.js",
+                "../../src/Materials/Textures/babylon.colorGradingTexture.js",
+                "../../src/Materials/babylon.colorCurves.js"
+            ],
+            "dependUpon": [
+                "core"
+            ]
+        },        
         "particles": {
             "files": [
                 "../../src/Particles/babylon.particle.js",
@@ -290,7 +311,7 @@
                 "../../src/Behaviors/Cameras/babylon.autoRotationBehavior.js"
             ],
             "dependUpon": [
-                "core"
+                "behaviors"
             ]
         },
         "meshBehaviors": {
@@ -298,7 +319,7 @@
                 "../../src/Behaviors/Mesh/babylon.pointerDragBehavior.js"
             ],
             "dependUpon": [
-                "core"
+                "behaviors"
             ]
         },
         "textureTools": {
@@ -680,6 +701,7 @@
         },
         "postProcesses": {
             "files": [
+                "../../src/PostProcess/babylon.postProcessManager.js",
                 "../../src/PostProcess/babylon.postProcess.js",
                 "../../src/PostProcess/babylon.passPostProcess.js"
             ],
@@ -853,7 +875,8 @@
                 "../../src/PostProcess/babylon.imageProcessingPostProcess.js"
             ],
             "dependUpon": [
-                "postProcesses"
+                "postProcesses",
+                "imageProcessing"
             ],
             "shaders": [
                 "imageProcessing.fragment"
@@ -879,7 +902,8 @@
                 "../../src/PostProcess/babylon.imageProcessingPostProcess.js"
             ],
             "dependUpon": [
-                "postProcesses"
+                "postProcesses",
+                "imageProcessing"
             ],
             "shaders": [
                 "refraction.fragment",
@@ -1054,6 +1078,7 @@
                 "../../src/Gizmos/babylon.positionGizmo.js",
                 "../../src/Gizmos/babylon.rotationGizmo.js",
                 "../../src/Gizmos/babylon.scaleGizmo.js",
+                "../../src/Gizmos/babylon.boundingBoxGizmo.js",
                 "../../src/Gizmos/babylon.gizmoManager.js"
             ],
             "dependUpon": [
@@ -1731,7 +1756,8 @@
                     "../../gui/src/3D/controls/holographicButton.ts",
                     "../../gui/src/3D/controls/stackPanel3D.ts",
                     "../../gui/src/3D/controls/volumeBasedPanel.ts",
-                    "../../gui/src/3D/controls/spherePanel.ts"
+                    "../../gui/src/3D/controls/spherePanel.ts",
+                    "../../gui/src/3D/controls/cylinderPanel.ts"
                 ],
                 "shaderFiles": [
                     "../../gui/src/3D/materials/shaders/fluent.vertex.fx",

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


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


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


File diff suppressed because it is too large
+ 11811 - 11509
dist/preview release/babylon.no-module.max.js


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


File diff suppressed because it is too large
+ 11813 - 11511
dist/preview release/es6.js


+ 18 - 0
dist/preview release/gui/babylon.gui.d.ts

@@ -1944,6 +1944,8 @@ declare module BABYLON.GUI {
         constructor(name?: string | undefined);
         protected _getTypeName(): string;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        /** Releases associated resources */
+        dispose(): void;
     }
 }
 
@@ -2539,3 +2541,19 @@ declare module BABYLON.GUI {
         private _sphericalMapping(source);
     }
 }
+
+
+declare module BABYLON.GUI {
+    /**
+     * Class used to create a container panel deployed on the surface of a cylinder
+     */
+    class CylinderPanel extends VolumeBasedPanel {
+        private _radius;
+        /**
+         * Gets or sets the radius of the cylinder where to project controls (5 by default)
+         */
+        radius: float;
+        protected _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+        private _cylindricalMapping(source);
+    }
+}

+ 79 - 1
dist/preview release/gui/babylon.gui.js

@@ -6778,6 +6778,14 @@ var BABYLON;
                 }
                 _super.prototype._additionalProcessing.call(this, parentMeasure, context);
             };
+            /** Releases associated resources */
+            Grid.prototype.dispose = function () {
+                _super.prototype.dispose.call(this);
+                for (var _i = 0, _a = this._childControls; _i < _a.length; _i++) {
+                    var control = _a[_i];
+                    control.dispose();
+                }
+            };
             return Grid;
         }(GUI.Container));
         GUI.Grid = Grid;
@@ -8505,7 +8513,7 @@ var BABYLON;
             __extends(SpherePanel, _super);
             function SpherePanel() {
                 var _this = _super !== null && _super.apply(this, arguments) || this;
-                _this._radius = 4.0;
+                _this._radius = 5.0;
                 return _this;
             }
             Object.defineProperty(SpherePanel.prototype, "radius", {
@@ -8563,6 +8571,76 @@ var BABYLON;
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
 })(BABYLON || (BABYLON = {}));
 
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
+        /**
+         * Class used to create a container panel deployed on the surface of a cylinder
+         */
+        var CylinderPanel = /** @class */ (function (_super) {
+            __extends(CylinderPanel, _super);
+            function CylinderPanel() {
+                var _this = _super !== null && _super.apply(this, arguments) || this;
+                _this._radius = 5.0;
+                return _this;
+            }
+            Object.defineProperty(CylinderPanel.prototype, "radius", {
+                /**
+                 * Gets or sets the radius of the cylinder where to project controls (5 by default)
+                 */
+                get: function () {
+                    return this._radius;
+                },
+                set: function (value) {
+                    var _this = this;
+                    if (this._radius === value) {
+                        return;
+                    }
+                    this._radius = value;
+                    BABYLON.Tools.SetImmediate(function () {
+                        _this._arrangeChildren();
+                    });
+                },
+                enumerable: true,
+                configurable: true
+            });
+            CylinderPanel.prototype._mapGridNode = function (control, nodePosition) {
+                var newPos = this._cylindricalMapping(nodePosition);
+                var mesh = control.mesh;
+                if (!mesh) {
+                    return;
+                }
+                switch (this.orientation) {
+                    case GUI.Container3D.FACEORIGIN_ORIENTATION:
+                        mesh.lookAt(new BABYLON.Vector3(-newPos.x, 0, -newPos.z));
+                        break;
+                    case GUI.Container3D.FACEORIGINREVERSED_ORIENTATION:
+                        mesh.lookAt(new BABYLON.Vector3(newPos.x, 0, newPos.z));
+                        break;
+                    case GUI.Container3D.FACEFORWARD_ORIENTATION:
+                        mesh.lookAt(new BABYLON.Vector3(0, 0, 1));
+                        break;
+                    case GUI.Container3D.FACEFORWARDREVERSED_ORIENTATION:
+                        mesh.lookAt(new BABYLON.Vector3(0, 0, -1));
+                        break;
+                }
+                control.position = newPos;
+            };
+            CylinderPanel.prototype._cylindricalMapping = function (source) {
+                var newPos = new BABYLON.Vector3(0, source.y, this._radius);
+                var yAngle = (source.x / this._radius);
+                BABYLON.Matrix.RotationYawPitchRollToRef(yAngle, 0, 0, BABYLON.Tmp.Matrix[0]);
+                return BABYLON.Vector3.TransformNormal(newPos, BABYLON.Tmp.Matrix[0]);
+            };
+            return CylinderPanel;
+        }(GUI.VolumeBasedPanel));
+        GUI.CylinderPanel = CylinderPanel;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));
+
     
 
     return BABYLON.GUI;

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


+ 18 - 0
dist/preview release/gui/babylon.gui.module.d.ts

@@ -1949,6 +1949,8 @@ declare module BABYLON.GUI {
         constructor(name?: string | undefined);
         protected _getTypeName(): string;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        /** Releases associated resources */
+        dispose(): void;
     }
 }
 
@@ -2544,3 +2546,19 @@ declare module BABYLON.GUI {
         private _sphericalMapping(source);
     }
 }
+
+
+declare module BABYLON.GUI {
+    /**
+     * Class used to create a container panel deployed on the surface of a cylinder
+     */
+    class CylinderPanel extends VolumeBasedPanel {
+        private _radius;
+        /**
+         * Gets or sets the radius of the cylinder where to project controls (5 by default)
+         */
+        radius: float;
+        protected _mapGridNode(control: Control3D, nodePosition: Vector3): void;
+        private _cylindricalMapping(source);
+    }
+}

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


+ 13 - 0
dist/preview release/proceduralTexturesLibrary/babylon.brickProceduralTexture.d.ts

@@ -11,5 +11,18 @@ declare module BABYLON {
         numberOfBricksWidth: number;
         jointColor: Color3;
         brickColor: Color3;
+        /**
+         * Serializes this brick procedural texture
+         * @returns a serialized brick procedural texture object
+         */
+        serialize(): any;
+        /**
+         * Creates a Brick Procedural Texture from parsed brick procedural texture data
+         * @param parsedTexture defines parsed texture data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing brick procedural texture information
+         * @returns a parsed Brick Procedural Texture
+         */
+        static Parse(parsedTexture: any, scene: Scene, rootUrl: string): BrickProceduralTexture;
     }
 }

+ 38 - 0
dist/preview release/proceduralTexturesLibrary/babylon.brickProceduralTexture.js

@@ -9,6 +9,12 @@ var __extends = (this && this.__extends) || (function () {
         d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
     };
 })();
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
 var BABYLON;
 (function (BABYLON) {
     var BrickProceduralTexture = /** @class */ (function (_super) {
@@ -72,6 +78,38 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        /**
+         * Serializes this brick procedural texture
+         * @returns a serialized brick procedural texture object
+         */
+        BrickProceduralTexture.prototype.serialize = function () {
+            var serializationObject = BABYLON.SerializationHelper.Serialize(this, _super.prototype.serialize.call(this));
+            serializationObject.customType = "BABYLON.BrickProceduralTexture";
+            return serializationObject;
+        };
+        /**
+         * Creates a Brick Procedural Texture from parsed brick procedural texture data
+         * @param parsedTexture defines parsed texture data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing brick procedural texture information
+         * @returns a parsed Brick Procedural Texture
+         */
+        BrickProceduralTexture.Parse = function (parsedTexture, scene, rootUrl) {
+            var texture = BABYLON.SerializationHelper.Parse(function () { return new BrickProceduralTexture(parsedTexture.name, parsedTexture._size, scene, undefined, parsedTexture._generateMipMaps); }, parsedTexture, scene, rootUrl);
+            return texture;
+        };
+        __decorate([
+            BABYLON.serialize()
+        ], BrickProceduralTexture.prototype, "numberOfBricksHeight", null);
+        __decorate([
+            BABYLON.serialize()
+        ], BrickProceduralTexture.prototype, "numberOfBricksWidth", null);
+        __decorate([
+            BABYLON.serializeAsColor3()
+        ], BrickProceduralTexture.prototype, "jointColor", null);
+        __decorate([
+            BABYLON.serializeAsColor3()
+        ], BrickProceduralTexture.prototype, "brickColor", null);
         return BrickProceduralTexture;
     }(BABYLON.ProceduralTexture));
     BABYLON.BrickProceduralTexture = BrickProceduralTexture;

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


+ 13 - 0
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.d.ts

@@ -79,6 +79,19 @@ declare module BABYLON {
         numberOfBricksWidth: number;
         jointColor: Color3;
         brickColor: Color3;
+        /**
+         * Serializes this brick procedural texture
+         * @returns a serialized brick procedural texture object
+         */
+        serialize(): any;
+        /**
+         * Creates a Brick Procedural Texture from parsed brick procedural texture data
+         * @param parsedTexture defines parsed texture data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing brick procedural texture information
+         * @returns a parsed Brick Procedural Texture
+         */
+        static Parse(parsedTexture: any, scene: Scene, rootUrl: string): BrickProceduralTexture;
     }
 }
 

+ 33 - 0
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.js

@@ -354,6 +354,7 @@ BABYLON.Effect.ShadersStore['roadProceduralTexturePixelShader'] = "precision hig
 
 
 
+
 var BABYLON;
 (function (BABYLON) {
     var BrickProceduralTexture = /** @class */ (function (_super) {
@@ -417,6 +418,38 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        /**
+         * Serializes this brick procedural texture
+         * @returns a serialized brick procedural texture object
+         */
+        BrickProceduralTexture.prototype.serialize = function () {
+            var serializationObject = BABYLON.SerializationHelper.Serialize(this, _super.prototype.serialize.call(this));
+            serializationObject.customType = "BABYLON.BrickProceduralTexture";
+            return serializationObject;
+        };
+        /**
+         * Creates a Brick Procedural Texture from parsed brick procedural texture data
+         * @param parsedTexture defines parsed texture data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing brick procedural texture information
+         * @returns a parsed Brick Procedural Texture
+         */
+        BrickProceduralTexture.Parse = function (parsedTexture, scene, rootUrl) {
+            var texture = BABYLON.SerializationHelper.Parse(function () { return new BrickProceduralTexture(parsedTexture.name, parsedTexture._size, scene, undefined, parsedTexture._generateMipMaps); }, parsedTexture, scene, rootUrl);
+            return texture;
+        };
+        __decorate([
+            BABYLON.serialize()
+        ], BrickProceduralTexture.prototype, "numberOfBricksHeight", null);
+        __decorate([
+            BABYLON.serialize()
+        ], BrickProceduralTexture.prototype, "numberOfBricksWidth", null);
+        __decorate([
+            BABYLON.serializeAsColor3()
+        ], BrickProceduralTexture.prototype, "jointColor", null);
+        __decorate([
+            BABYLON.serializeAsColor3()
+        ], BrickProceduralTexture.prototype, "brickColor", null);
         return BrickProceduralTexture;
     }(BABYLON.ProceduralTexture));
     BABYLON.BrickProceduralTexture = BrickProceduralTexture;

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


+ 13 - 0
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.module.d.ts

@@ -84,6 +84,19 @@ declare module BABYLON {
         numberOfBricksWidth: number;
         jointColor: Color3;
         brickColor: Color3;
+        /**
+         * Serializes this brick procedural texture
+         * @returns a serialized brick procedural texture object
+         */
+        serialize(): any;
+        /**
+         * Creates a Brick Procedural Texture from parsed brick procedural texture data
+         * @param parsedTexture defines parsed texture data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing brick procedural texture information
+         * @returns a parsed Brick Procedural Texture
+         */
+        static Parse(parsedTexture: any, scene: Scene, rootUrl: string): BrickProceduralTexture;
     }
 }
 

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


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


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

@@ -6,7 +6,7 @@
 - Added new `MixMaterial` to the Materials Library allowing to mix up to 8 textures ([julien-moreau](https://github.com/julien-moreau))
 - Added new `PhotoDome` object to display 360 photos. [Demo](https://www.babylonjs-playground.com/#14KRGG#0) ([SzeyinLee](https://github.com/SzeyinLee))
 - New GUI 3D controls toolset. [Complete doc + demos](http://doc.babylonjs.com/how_to/gui3d) ([Deltakosh](https://github.com/deltakosh))
-- Added [Environmnent Texture Tools](https://doc.babylonjs.com/how_to/physically_based_rendering#creating-a-compressed-environment-texture) to reduce the size of the usual .DDS file ([sebavan](http://www.github.com/sebavan))
+- Added [Environment Texture Tools](https://doc.babylonjs.com/how_to/physically_based_rendering#creating-a-compressed-environment-texture) to reduce the size of the usual .DDS file ([sebavan](http://www.github.com/sebavan))
 - New GUI control: the [Grid](http://doc.babylonjs.com/how_to/gui#grid) ([Deltakosh](https://github.com/deltakosh))
 
 ## Updates
@@ -17,7 +17,7 @@
 ### Core Engine
 
 - Added new `Animatable.waitAsync` function to use Promises with animations. Demo [Here](https://www.babylonjs-playground.com/#HZBCXR) ([Deltakosh](https://github.com/deltakosh))
-- Added the choice of [forming a closed loop](http://doc.babylonjs.com/how_to/how_to_use_curve3#catmull-rom-spline) to the catamull-rom-spline curve3 ([johnk](https://github.com/babylonjsguide))
+- Added the choice of [forming a closed loop](http://doc.babylonjs.com/how_to/how_to_use_curve3#catmull-rom-spline) to the catmull-rom-spline curve3 ([johnk](https://github.com/babylonjsguide))
 - Added support for specifying the center of rotation to textures ([bghgary](http://www.github.com/bghgary))
 - Added webVR support for Oculus Go ([TrevorDev](https://github.com/TrevorDev))
 - Added ability to not generate polynomials harmonics upon prefiltered texture creation ([sebavan](http://www.github.com/sebavan))
@@ -27,9 +27,10 @@
 - 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 and gizmoManager class used to manipulate meshes in a scene, position, rotation, scale gizmos ([TrevorDev](https://github.com/TrevorDev))
+- Gizmo and GizmoManager classes used to manipulate meshes in a scene. Position, rotation, scale, and bounding box gizmos ([TrevorDev](https://github.com/TrevorDev))
 - Added a new `mesh.ignoreNonUniformScaling` to turn off non uniform scaling compensation ([Deltakosh](https://github.com/deltakosh))
 - AssetsManager tasks will only run when their state is INIT. It is now possible to remove a task from the assets manager ([RaananW](https://github.com/RaananW))
+- Sprite isVisible field ([TrevorDev](https://github.com/TrevorDev))
 - Added support for `minScaleX`, `minScaleY`, `maxScaleX`, `maxScaleY` for particles ([Deltakosh](https://github.com/deltakosh))
 
 ### glTF Loader
@@ -41,7 +42,7 @@
 ### Viewer
 
 - No fullscreen button on small devices ([RaananW](https://github.com/RaananW))
-- Nav-Bar is now disaplayed on fullscreen per default ([RaananW](https://github.com/RaananW))
+- Nav-Bar is now displayed on fullscreen per default ([RaananW](https://github.com/RaananW))
 - Viewer configuration supports deprecated values using the new configurationCompatibility processor  ([RaananW](https://github.com/RaananW))
 - Shadows will only render while models are entering the scene or animating ([RaananW](https://github.com/RaananW))
 - Support for model drag and drop onto the canvas ([RaananW](https://github.com/RaananW))
@@ -61,7 +62,7 @@
 
 ### Core Engine
 
-- Fixed ```shadowEnabled``` property on lights. Shadows are not visble anymore when disabled ([sebavan](http://www.github.com/sebavan))
+- Fixed ```shadowEnabled``` property on lights. Shadows are not visible anymore when disabled ([sebavan](http://www.github.com/sebavan))
 - Physics `unregisterOnPhysicsCollide` didn't remove callback correctly [#4291](https://github.com/BabylonJS/Babylon.js/issues/4291) ([RaananW](https://github.com/RaananW))
 - Added missing getter and setter for global exposure in ColorCurves ([RaananW](https://github.com/RaananW))
 - Fixed an issue with view matrix when `ArcRotateCamera` was used with collisions ([Deltakosh](https://github.com/deltakosh))

+ 9 - 0
gui/src/2D/controls/grid.ts

@@ -337,5 +337,14 @@ module BABYLON.GUI {
 
             super._additionalProcessing(parentMeasure, context);
         }
+
+        /** Releases associated resources */
+        public dispose() {
+            super.dispose();
+
+            for (var control of this._childControls) {
+                control.dispose();
+            }
+        }
     }
 }

+ 66 - 0
gui/src/3D/controls/cylinderPanel.ts

@@ -0,0 +1,66 @@
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+    /**
+     * Class used to create a container panel deployed on the surface of a cylinder
+     */
+    export class CylinderPanel extends VolumeBasedPanel {
+        private _radius = 5.0;
+
+        /**
+         * Gets or sets the radius of the cylinder where to project controls (5 by default)
+         */
+        public get radius(): float {
+            return this._radius;
+        }
+
+        public set radius(value: float) {
+            if (this._radius === value) {
+                return;
+            }
+
+            this._radius = value;
+
+            Tools.SetImmediate(() => {
+                this._arrangeChildren();               
+            });
+        }              
+
+        protected _mapGridNode(control: Control3D, nodePosition: Vector3) {            
+            let newPos = this._cylindricalMapping(nodePosition);
+            let mesh = control.mesh;
+
+            if (!mesh) {
+                return;
+            }
+
+            switch (this.orientation) {
+                case Container3D.FACEORIGIN_ORIENTATION:
+                    mesh.lookAt(new BABYLON.Vector3(-newPos.x, 0, -newPos.z));
+                    break;
+                case Container3D.FACEORIGINREVERSED_ORIENTATION:
+                    mesh.lookAt(new BABYLON.Vector3(newPos.x, 0, newPos.z));
+                    break;
+                case Container3D.FACEFORWARD_ORIENTATION:
+                    mesh.lookAt(new BABYLON.Vector3(0, 0, 1));
+                    break;
+                case Container3D.FACEFORWARDREVERSED_ORIENTATION:
+                    mesh.lookAt(new BABYLON.Vector3(0, 0, -1));
+                    break;
+            }
+            
+            control.position = newPos;
+        }
+
+        private _cylindricalMapping(source: Vector3)
+        {
+            let newPos = new Vector3(0, source.y, this._radius);
+
+            let yAngle = (source.x / this._radius);
+
+            Matrix.RotationYawPitchRollToRef(yAngle, 0, 0, Tmp.Matrix[0]);
+
+            return Vector3.TransformNormal(newPos, Tmp.Matrix[0]);
+        }
+    }
+}

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

@@ -5,7 +5,7 @@ module BABYLON.GUI {
      * Class used to create a container panel deployed on the surface of a sphere
      */
     export class SpherePanel extends VolumeBasedPanel {
-        private _radius = 4.0;
+        private _radius = 5.0;
 
         /**
          * Gets or sets the radius of the sphere where to project controls (5 by default)

+ 97 - 0
localDev/indexMini.html

@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+    <title>Local Development</title>
+
+    <script src="../dist/preview%20release/babylon.max.js"></script>
+
+    <style>
+        html,
+        body {
+            width: 100%;
+            height: 100%;
+            padding: 0;
+            margin: 0;
+            overflow: hidden;
+        }
+
+        #renderCanvas {
+            width: 100%;
+            height: 100%;
+        }
+
+        #fps {
+            position: absolute;
+            background-color: black;
+            border: 2px solid red;
+            text-align: center;
+            font-size: 16px;
+            color: white;
+            top: 15px;
+            right: 10px;
+            width: 60px;
+            height: 20px;
+        }
+    </style>
+</head>
+
+<body>
+    <div id="fps">0</div>
+    <canvas id="renderCanvas" touch-action="none"></canvas>
+
+    <script>
+        var canvas = document.getElementById("renderCanvas");
+        var divFps = document.getElementById("fps");
+
+        // Global to simulate PG.
+        var engine = new BABYLON.Engine(canvas, true, { stencil: true, disableWebGL2Support: false, preserveDrawingBuffer: true });
+
+        if (BABYLON.Engine.isSupported()) {
+
+            // This creates a basic Babylon Scene object (non-mesh)
+            var scene = new BABYLON.Scene(engine);
+
+            // This creates and positions a free camera (non-mesh)
+            var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
+
+            camera.attachControl(canvas, true);
+
+            // This targets the camera to scene origin
+            camera.setTarget(BABYLON.Vector3.Zero());
+
+            // This attaches the camera to the canvas
+            camera.attachControl(canvas, true);
+
+            // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
+            var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
+
+            // Default intensity is 1. Let's dim the light a small amount
+            light.intensity = 0.7;
+
+            // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
+            var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
+
+            // Move the sphere upward 1/2 its height
+            sphere.position.y = 1;
+
+            // Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
+            var ground = BABYLON.Mesh.CreateGround("ground1", 6, 6, 2, scene);            
+
+
+            engine.runRenderLoop(function () {
+                if (scene.activeCamera) {
+                    scene.render();
+                }
+                divFps.innerHTML = engine.getFps().toFixed() + " fps";
+            });
+        }
+
+        // Resize
+        window.addEventListener("resize", function () {
+            engine.resize();
+        });
+    </script>
+</body>
+
+</html>

+ 28 - 0
proceduralTexturesLibrary/src/brick/babylon.brickProceduralTexture.ts

@@ -19,6 +19,7 @@ module BABYLON {
             this.setColor3("jointColor", this._jointColor);
         }
 
+        @serialize()
         public get numberOfBricksHeight(): number {
             return this._numberOfBricksHeight;
         }
@@ -28,6 +29,7 @@ module BABYLON {
             this.updateShaderUniforms();
         }
 
+        @serialize()
         public get numberOfBricksWidth(): number {
             return this._numberOfBricksWidth;
         }
@@ -37,6 +39,7 @@ module BABYLON {
             this.updateShaderUniforms();
         }
 
+        @serializeAsColor3()
         public get jointColor(): Color3 {
             return this._jointColor;
         }
@@ -46,6 +49,7 @@ module BABYLON {
             this.updateShaderUniforms();
         }
 
+        @serializeAsColor3()
         public get brickColor(): Color3 {
             return this._brickColor;
         }
@@ -54,5 +58,29 @@ module BABYLON {
             this._brickColor = value;
             this.updateShaderUniforms();
         }
+
+        /**
+         * Serializes this brick procedural texture
+         * @returns a serialized brick procedural texture object
+         */
+        public serialize(): any {
+            var serializationObject = SerializationHelper.Serialize(this, super.serialize());
+            serializationObject.customType = "BABYLON.BrickProceduralTexture";
+
+            return serializationObject;
+        }
+
+        /**
+         * Creates a Brick Procedural Texture from parsed brick procedural texture data
+         * @param parsedTexture defines parsed texture data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing brick procedural texture information
+         * @returns a parsed Brick Procedural Texture
+         */
+        public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): BrickProceduralTexture {
+            var texture = SerializationHelper.Parse(() => new BrickProceduralTexture(parsedTexture.name, parsedTexture._size, scene, undefined, parsedTexture._generateMipMaps), parsedTexture, scene, rootUrl);
+
+            return texture;
+        }
     }	
 }

+ 44 - 20
src/Behaviors/Mesh/babylon.pointerDragBehavior.ts

@@ -9,11 +9,18 @@ module BABYLON {
         private _pointerObserver:Nullable<Observer<PointerInfo>>;
         private static _planeScene:Scene;
         private _draggingID = -1;
+        // Debug mode will display drag planes to help visualize behavior
+        private _debugMode = false;
+        private _maxDragAngle = Math.PI/5;
         
         /**
          *  Fires each time the attached mesh is dragged with the pointer
+         *  * delta between last drag position and current drag position in world space
+         *  * dragDistance along the drag axis
+         *  * dragPlaneNormal normal of the current drag plane used during the drag
+         *  * dragPlanePoint in world space where the drag intersects the drag plane
          */
-        public onDragObservable = new Observable<{delta:Vector3, dragPlanePoint:Vector3}>()
+        public onDragObservable = new Observable<{delta:Vector3, dragPlanePoint:Vector3, dragPlaneNormal:Vector3, dragDistance:number}>()
         /**
          *  Fires each time a drag begins (eg. mouse down on mesh)
          */
@@ -38,10 +45,13 @@ module BABYLON {
         
         /**
          * Creates a pointer drag behavior that can be attached to a mesh
-         * @param options The drag axis or normal of the plane that will be dragged across.
+         * @param options The drag axis or normal of the plane that will be dragged across. If no options are specified the drag plane will always face the ray's origin (eg. camera)
          */
         constructor(private options:{dragAxis?:Vector3, dragPlaneNormal?:Vector3}){
             var optionCount = 0;
+            if(options === undefined){
+                options = {}
+            }
             if(options.dragAxis){
                 optionCount++;
             }
@@ -51,9 +61,6 @@ module BABYLON {
             if(optionCount > 1){
                 throw "Multiple drag modes specified in dragBehavior options. Only one expected";
             }
-            if(optionCount < 1){
-                throw "At least one drag mode option must be specified";
-            }
         }
 
         /**
@@ -78,15 +85,20 @@ module BABYLON {
 
             // Initialize drag plane to not interfere with existing scene
             if(!PointerDragBehavior._planeScene){
-                PointerDragBehavior._planeScene = new BABYLON.Scene(this._scene.getEngine())
-                this._scene.getEngine().scenes.pop();
+                if(this._debugMode){
+                    PointerDragBehavior._planeScene = this._scene;
+                }else{
+                    PointerDragBehavior._planeScene = new BABYLON.Scene(this._scene.getEngine());
+                    this._scene.getEngine().scenes.pop();
+                }
             }
-            this._dragPlane = BABYLON.Mesh.CreatePlane("pointerDragPlane", 1000, PointerDragBehavior._planeScene, false, BABYLON.Mesh.DOUBLESIDE);
+            this._dragPlane = BABYLON.Mesh.CreatePlane("pointerDragPlane", this._debugMode ? 1 : 10000, PointerDragBehavior._planeScene, false, BABYLON.Mesh.DOUBLESIDE);
 
             // State of the drag
             var dragging = false;
             var lastPosition = new BABYLON.Vector3(0,0,0);
             var delta = new BABYLON.Vector3(0,0,0);
+            var dragLength = 0;
 
             var pickPredicate = (m:AbstractMesh)=>{
                 return this._attachedNode == m || m.isDescendantOf(this._attachedNode)
@@ -117,21 +129,30 @@ module BABYLON {
                 }else if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERMOVE){
                     if(this._draggingID == (<PointerEvent>pointerInfo.event).pointerId && dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.ray){
                         var pickedPoint = this._pickWithRayOnDragPlane(pointerInfo.pickInfo.ray);
-                        this._updateDragPlanePosition(pointerInfo.pickInfo.ray);
+                        
+                         // Get angle between drag plane and ray. Only update the drag plane at non steep angles to avoid jumps in delta position
+                        var angle = Math.acos(Vector3.Dot(this._dragPlane.forward, pointerInfo.pickInfo.ray.direction));
+                        if(angle < this._maxDragAngle){
+                            this._updateDragPlanePosition(pointerInfo.pickInfo.ray);
+                        }
+                        
                         if (pickedPoint) {
                             // depending on the drag mode option drag accordingly
                             if(this.options.dragAxis){
-                                //get the closest point on the dragaxis from the selected mesh to the picked point location
-                                // https://www.opengl.org/discussion_boards/showthread.php/159717-Closest-point-on-a-Vector-to-a-point
-                                this.options.dragAxis.scaleToRef(BABYLON.Vector3.Dot(pickedPoint.subtract(lastPosition), this.options.dragAxis), delta);
+                                // Convert local drag axis to world
+                                var worldDragAxis = Vector3.TransformCoordinates(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix());
+
+                                // Project delta drag from the drag plane onto the drag axis
+                                dragLength = BABYLON.Vector3.Dot(pickedPoint.subtract(lastPosition), worldDragAxis)
+                                worldDragAxis.scaleToRef(dragLength, delta);
                             }else{
+                                dragLength = delta.length();
                                 pickedPoint.subtractToRef(lastPosition, delta);
                             }
                             if(this.moveAttached){
                                 (<Mesh>this._attachedNode).position.addInPlace(delta);
-                                
                             }
-                            this.onDragObservable.notifyObservers({delta: delta, dragPlanePoint: pickedPoint});
+                            this.onDragObservable.notifyObservers({dragDistance: dragLength, delta: delta, dragPlanePoint: pickedPoint, dragPlaneNormal: this._dragPlane.forward});
                             lastPosition.copyFrom(pickedPoint);
                         }
                     }
@@ -153,13 +174,13 @@ module BABYLON {
 
         // Position the drag plane based on the attached mesh position, for single axis rotate the plane along the axis to face the camera
         private _updateDragPlanePosition(ray:Ray){
-            var pointA = this._dragPlaneParent ? this._dragPlaneParent.position : (<Mesh>this._attachedNode).position // center
+            var pointA = this._dragPlaneParent ? this._dragPlaneParent.absolutePosition : (<Mesh>this._attachedNode).absolutePosition;
             if(this.options.dragAxis){
-                var camPos = ray.origin;
+                var localAxis = Vector3.TransformCoordinates(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix());
 
                 // Calculate plane normal in direction of camera but perpendicular to drag axis
-                var pointB = pointA.add(this.options.dragAxis); // towards drag axis
-                var pointC = pointA.add(camPos.subtract(pointA).normalize()); // towards camera
+                var pointB = pointA.add(localAxis); // towards drag axis
+                var pointC = pointA.add(ray.origin.subtract(pointA).normalize()); // towards camera
                 // Get perpendicular line from direction to camera and drag axis
                 var lineA = pointB.subtract(pointA);
                 var lineB = pointC.subtract(pointA);
@@ -168,10 +189,13 @@ module BABYLON {
                 var norm = BABYLON.Vector3.Cross(lineA, perpLine).normalize();
 
                 this._dragPlane.position.copyFrom(pointA);
-                this._dragPlane.lookAt(pointA.add(norm));
+                this._dragPlane.lookAt(pointA.subtract(norm));
             }else if(this.options.dragPlaneNormal){
                 this._dragPlane.position.copyFrom(pointA);
-                this._dragPlane.lookAt(pointA.add(this.options.dragPlaneNormal));
+                this._dragPlane.lookAt(pointA.subtract(this.options.dragPlaneNormal));
+            }else{
+                this._dragPlane.position.copyFrom(pointA);
+                this._dragPlane.lookAt(ray.origin);
             }
             this._dragPlane.computeWorldMatrix(true);
         }

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

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

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

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

+ 224 - 0
src/Gizmos/babylon.boundingBoxGizmo.ts

@@ -0,0 +1,224 @@
+module BABYLON {
+    /**
+     * Bounding box gizmo
+     */
+    export class BoundingBoxGizmo extends Gizmo {
+        private _lineBoundingBox:AbstractMesh;
+        private _rotateSpheresParent:AbstractMesh;
+        private _scaleBoxesParent:AbstractMesh;
+        private _boundingDimensions = new BABYLON.Vector3(1,1,1);
+        private _renderObserver:Nullable<Observer<Scene>> = null;
+
+        /**
+         * Creates an BoundingBoxGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         * @param color The color of the gizmo
+         */
+        constructor(gizmoLayer:UtilityLayerRenderer, color:Color3){
+            super(gizmoLayer);
+
+            // Do not update the gizmo's scale so it has a fixed size to the object its attached to
+            this._updateScale = false;
+
+            // Create Material
+            var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
+            coloredMaterial.disableLighting = true;
+            coloredMaterial.emissiveColor = color;
+
+            // Build bounding box out of lines
+            this._lineBoundingBox = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
+            this._lineBoundingBox.rotationQuaternion = new BABYLON.Quaternion();
+            var lines = []
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(0,0,0), new BABYLON.Vector3(this._boundingDimensions.x,0,0)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(0,0,0), new BABYLON.Vector3(0,this._boundingDimensions.y,0)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(0,0,0), new BABYLON.Vector3(0,0,this._boundingDimensions.z)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(this._boundingDimensions.x,0,0), new BABYLON.Vector3(this._boundingDimensions.x,this._boundingDimensions.y,0)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(this._boundingDimensions.x,0,0), new BABYLON.Vector3(this._boundingDimensions.x,0,this._boundingDimensions.z)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(0,this._boundingDimensions.y,0), new BABYLON.Vector3(this._boundingDimensions.x,this._boundingDimensions.y,0)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(0,this._boundingDimensions.y,0), new BABYLON.Vector3(0,this._boundingDimensions.y,this._boundingDimensions.z)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(0,0,this._boundingDimensions.z), new BABYLON.Vector3(this._boundingDimensions.x,0,this._boundingDimensions.z)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(0,0,this._boundingDimensions.z), new BABYLON.Vector3(0,this._boundingDimensions.y,this._boundingDimensions.z)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(this._boundingDimensions.x,this._boundingDimensions.y,this._boundingDimensions.z), new BABYLON.Vector3(0,this._boundingDimensions.y,this._boundingDimensions.z)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(this._boundingDimensions.x,this._boundingDimensions.y,this._boundingDimensions.z), new BABYLON.Vector3(this._boundingDimensions.x,0,this._boundingDimensions.z)]}, gizmoLayer.utilityLayerScene));
+            lines.push(BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(this._boundingDimensions.x,this._boundingDimensions.y,this._boundingDimensions.z), new BABYLON.Vector3(this._boundingDimensions.x,this._boundingDimensions.y,0)]}, gizmoLayer.utilityLayerScene));
+            lines.forEach((l)=>{
+                l.color = color
+                l.position.addInPlace(new BABYLON.Vector3(-this._boundingDimensions.x/2,-this._boundingDimensions.y/2,-this._boundingDimensions.z/2))
+                l.isPickable=false;
+                this._lineBoundingBox.addChild(l)
+            })
+            this._rootMesh.addChild(this._lineBoundingBox);
+
+            // Create rotation spheres
+            this._rotateSpheresParent = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
+            this._rotateSpheresParent.rotationQuaternion = new Quaternion();
+            for(let i=0;i<12;i++){
+                let sphere = BABYLON.MeshBuilder.CreateSphere("", {diameter: 0.1}, gizmoLayer.utilityLayerScene);
+                sphere.rotationQuaternion = new Quaternion();
+                sphere.material = coloredMaterial;
+
+                // Drag behavior
+                var _dragBehavior = new PointerDragBehavior({});
+                _dragBehavior.moveAttached = false;
+                sphere.addBehavior(_dragBehavior);
+                _dragBehavior.onDragObservable.add((event)=>{
+                    if(this.attachedMesh){
+                        var worldDragDirection = sphere.forward;
+
+                        // Project the world right on to the drag plane
+                        var toSub = event.dragPlaneNormal.scale(Vector3.Dot(event.dragPlaneNormal, worldDragDirection));
+                        var dragAxis = worldDragDirection.subtract(toSub).normalizeToNew();
+
+                        // project drag delta on to the resulting drag axis and rotate based on that
+                        var projectDist = Vector3.Dot(dragAxis, event.delta);
+
+                        // Rotate based on axis
+                        if(i>=8){
+                            this.attachedMesh.rotation.z -= projectDist;
+                        }else if(i>=4){
+                            this.attachedMesh.rotation.y -= projectDist;
+                        }else{
+                            this.attachedMesh.rotation.x -= projectDist;
+                        }
+                    }
+                });
+
+                // Selection/deselection
+                _dragBehavior.onDragStartObservable.add(()=>{
+                    this._selectNode(sphere)
+                })
+                _dragBehavior.onDragEndObservable.add(()=>{
+                    this._selectNode(null)
+                })
+
+                this._rotateSpheresParent.addChild(sphere);
+            }
+            this._rootMesh.addChild(this._rotateSpheresParent);
+
+            // Create scale cubes
+            this._scaleBoxesParent = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
+            this._scaleBoxesParent.rotationQuaternion = new Quaternion();
+            for(var i=0;i<2;i++){
+                for(var j=0;j<2;j++){
+                    for(var k=0;k<2;k++){
+                        let box = BABYLON.MeshBuilder.CreateBox("", {size: 0.1}, gizmoLayer.utilityLayerScene);
+                        box.material = coloredMaterial;
+
+                        // Dragging logic
+                        let dragAxis = new BABYLON.Vector3(i==0?-1:1,j==0?-1:1,k==0?-1:1);
+                        var _dragBehavior = new PointerDragBehavior({dragAxis: dragAxis});
+                        _dragBehavior.moveAttached = false;
+                        box.addBehavior(_dragBehavior);
+                        _dragBehavior.onDragObservable.add((event)=>{
+                            if(this.attachedMesh){
+                                // Current boudning box dimensions
+                                var boundingInfo = this.attachedMesh.getBoundingInfo().boundingBox;
+                                var boundBoxDimensions = boundingInfo.maximum.subtract(boundingInfo.minimum).multiplyInPlace(this.attachedMesh.scaling);
+                                
+                                // Get the change in bounding box size/2 and add this to the mesh's position to offset from scaling with center pivot point
+                                var deltaScale = new Vector3(event.dragDistance,event.dragDistance,event.dragDistance);
+                                var scaleRatio = deltaScale.divide(this.attachedMesh.scaling).scaleInPlace(0.5);
+                                var moveDirection = boundBoxDimensions.multiply(scaleRatio).multiplyInPlace(dragAxis);
+                                var worldMoveDirection = Vector3.TransformCoordinates(moveDirection, this.attachedMesh.getWorldMatrix().getRotationMatrix());
+                                
+                                // Update scale and position
+                                this.attachedMesh.scaling.addInPlace(deltaScale);
+                                this.attachedMesh.position.addInPlace(worldMoveDirection);
+                            }
+                        })
+
+                        // Selection/deselection
+                        _dragBehavior.onDragStartObservable.add(()=>{
+                            this._selectNode(box)
+                        })
+                        _dragBehavior.onDragEndObservable.add(()=>{
+                            this._selectNode(null)
+                        })
+
+                        this._scaleBoxesParent.addChild(box);
+                    }
+                }
+            }
+            this._rootMesh.addChild(this._scaleBoxesParent);
+
+            // Update bounding box positions
+            this._renderObserver = this.gizmoLayer.originalScene.onBeforeRenderObservable.add(()=>{
+                this._updateBoundingBox();
+            })
+            this._updateBoundingBox();
+        }
+
+        private _selectNode(selectedMesh:Nullable<Mesh>){
+            this._rotateSpheresParent.getChildMeshes()
+            .concat(this._scaleBoxesParent.getChildMeshes()).forEach((m,i)=>{
+                m.isVisible = (!selectedMesh || m == selectedMesh);
+            })
+        }
+
+        private _updateBoundingBox(){   
+            if(this.attachedMesh){
+                // Update bounding dimensions/positions
+                var boundingInfo = this.attachedMesh.getBoundingInfo().boundingBox;
+                var boundBoxDimensions = boundingInfo.maximum.subtract(boundingInfo.minimum).multiplyInPlace(this.attachedMesh.scaling);
+                this._boundingDimensions.copyFrom(boundBoxDimensions);
+                this._lineBoundingBox.scaling.copyFrom(this._boundingDimensions);
+                if(!this.attachedMesh.rotationQuaternion){
+                    this.attachedMesh.rotationQuaternion = new BABYLON.Quaternion();
+                }
+                this._lineBoundingBox.rotationQuaternion!.copyFrom(this.attachedMesh.rotationQuaternion);
+                this._rotateSpheresParent.rotationQuaternion!.copyFrom(this.attachedMesh.rotationQuaternion);
+                this._scaleBoxesParent.rotationQuaternion!.copyFrom(this.attachedMesh.rotationQuaternion);
+            }
+
+            // Update rotation sphere locations
+            var rotateSpheres = this._rotateSpheresParent.getChildMeshes();
+            for(var i=0;i<3;i++){
+                for(var j=0;j<2;j++){
+                    for(var k=0;k<2;k++){
+                        var index= ((i*4)+(j*2))+k
+                        if(i==0){
+                            rotateSpheres[index].position.set(this._boundingDimensions.x/2,this._boundingDimensions.y*j,this._boundingDimensions.z*k);
+                            rotateSpheres[index].position.addInPlace(new BABYLON.Vector3(-this._boundingDimensions.x/2,-this._boundingDimensions.y/2,-this._boundingDimensions.z/2));
+                            rotateSpheres[index].lookAt(Vector3.Cross(Vector3.Right(), rotateSpheres[index].position.normalizeToNew()).normalizeToNew().add(rotateSpheres[index].position));
+                        }
+                        if(i==1){
+                            rotateSpheres[index].position.set(this._boundingDimensions.x*j,this._boundingDimensions.y/2,this._boundingDimensions.z*k);
+                            rotateSpheres[index].position.addInPlace(new BABYLON.Vector3(-this._boundingDimensions.x/2,-this._boundingDimensions.y/2,-this._boundingDimensions.z/2));
+                            rotateSpheres[index].lookAt(Vector3.Cross(Vector3.Up(), rotateSpheres[index].position.normalizeToNew()).normalizeToNew().add(rotateSpheres[index].position));
+                        }
+                        if(i==2){
+                            rotateSpheres[index].position.set(this._boundingDimensions.x*j,this._boundingDimensions.y*k,this._boundingDimensions.z/2);
+                            rotateSpheres[index].position.addInPlace(new BABYLON.Vector3(-this._boundingDimensions.x/2,-this._boundingDimensions.y/2,-this._boundingDimensions.z/2));
+                            rotateSpheres[index].lookAt(Vector3.Cross(Vector3.Forward(), rotateSpheres[index].position.normalizeToNew()).normalizeToNew().add(rotateSpheres[index].position));
+                        }
+                    }
+                }
+            }
+
+            // Update scale box locations
+            var scaleBoxes = this._scaleBoxesParent.getChildMeshes();
+            for(var i=0;i<2;i++){
+                for(var j=0;j<2;j++){
+                    for(var k=0;k<2;k++){
+                        var index= ((i*4)+(j*2))+k;
+                        if(scaleBoxes[index]){
+                            scaleBoxes[index].position.set(this._boundingDimensions.x*i,this._boundingDimensions.y*j,this._boundingDimensions.z*k);
+                            scaleBoxes[index].position.addInPlace(new BABYLON.Vector3(-this._boundingDimensions.x/2,-this._boundingDimensions.y/2,-this._boundingDimensions.z/2));
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Disposes of the gizmo
+         */
+        public dispose(){
+            this.gizmoLayer.originalScene.onBeforeRenderObservable.remove(this._renderObserver);
+            this._lineBoundingBox.dispose();
+            this._rotateSpheresParent.dispose();
+            this._scaleBoxesParent.dispose();
+            super.dispose();
+        } 
+    }
+}

+ 5 - 1
src/Gizmos/babylon.gizmo.ts

@@ -11,6 +11,10 @@ module BABYLON {
          * Mesh that the gizmo will be attached to. (eg. on a drag gizmo the mesh that will be dragged)
          */
         public attachedMesh:Nullable<AbstractMesh>;
+        /**
+         * When set, the gizmo will always appear the same size no matter where the camera is (default: false)
+         */
+        protected _updateScale = true;
         protected _interactionsEnabled = true;
         protected _onInteractionsEnabledChanged(value:boolean){
         }
@@ -35,7 +39,7 @@ module BABYLON {
         constructor(/** The utility layer the gizmo will be added to */ public gizmoLayer:UtilityLayerRenderer){
             this._rootMesh = new BABYLON.Mesh("gizmoRootNode",gizmoLayer.utilityLayerScene);
             this._beforeRenderObserver = this.gizmoLayer.utilityLayerScene.onBeforeRenderObservable.add(()=>{
-                if(this.gizmoLayer.utilityLayerScene.activeCamera && this.attachedMesh){
+                if(this._updateScale && this.gizmoLayer.utilityLayerScene.activeCamera && this.attachedMesh){
                     var dist = this.attachedMesh.position.subtract(this.gizmoLayer.utilityLayerScene.activeCamera.position).length()/3;
                     this._rootMesh.scaling.set(dist, dist, dist);
                 }

+ 11 - 7
src/Materials/Background/babylon.backgroundMaterial.ts

@@ -410,10 +410,12 @@
             }
 
             // Attaches observer.
-            this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
-                this._computePrimaryColorFromPerceptualColor();
-                this._markAllSubMeshesAsImageProcessingDirty();
-            });
+            if (this._imageProcessingConfiguration) {
+                this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
+                    this._computePrimaryColorFromPerceptualColor();
+                    this._markAllSubMeshesAsImageProcessingDirty();
+                });
+            }
         }
 
         /**
@@ -745,7 +747,7 @@
                 defines.USEHIGHLIGHTANDSHADOWCOLORS = !this._useRGBColor && (this._primaryColorShadowLevel !== 0 || this._primaryColorHighlightLevel !== 0);
             }
 
-            if (defines._areImageProcessingDirty) {
+            if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) {
                 if (!this._imageProcessingConfiguration.isReady()) {
                     return false;
                 }
@@ -825,8 +827,10 @@
                 var samplers = ["diffuseSampler", "reflectionSampler", "reflectionSamplerLow", "reflectionSamplerHigh"];
                 var uniformBuffers = ["Material", "Scene"];
 
-                ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
-                ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
+                if (ImageProcessingConfiguration) {
+                    ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
+                    ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
+                }
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
                     uniformsNames: uniforms,

+ 11 - 7
src/Materials/PBR/babylon.pbrBaseMaterial.ts

@@ -525,9 +525,11 @@
             }
 
             // Attaches observer.
-            this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
-                this._markAllSubMeshesAsImageProcessingDirty();
-            });
+            if (this._imageProcessingConfiguration) {
+                this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
+                    this._markAllSubMeshesAsImageProcessingDirty();
+                });
+            }
         }
 
         /**
@@ -807,7 +809,7 @@
                 }
             }
 
-            if (defines._areImageProcessingDirty) {
+            if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) {
                 if (!this._imageProcessingConfiguration.isReady()) {
                     return false;
                 }
@@ -983,8 +985,10 @@
                 "microSurfaceSampler", "environmentBrdfSampler"];
             var uniformBuffers = ["Material", "Scene"];
 
-            ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
-            ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
+            if (ImageProcessingConfiguration) {
+                ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
+                ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
+            }
 
             MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
                 uniformsNames: uniforms,
@@ -1231,7 +1235,7 @@
                 defines.SPECULARAA = scene.getEngine().getCaps().standardDerivatives && this._enableSpecularAntiAliasing;
             }
 
-            if (defines._areImageProcessingDirty) {
+            if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) {
                 this._imageProcessingConfiguration.prepareDefines(defines);
             }
 

+ 10 - 0
src/Materials/Textures/Procedurals/babylon.proceduralTexture.ts

@@ -1,7 +1,12 @@
 module BABYLON {
     export class ProceduralTexture extends Texture {
+        @serialize()
         private _size: number;
+
+        @serialize()
         public _generateMipMaps: boolean;
+
+        @serialize()
         public isEnabled = true;
         private _currentRefreshId = -1;
         private _refreshRate = 1;
@@ -154,6 +159,7 @@
             this._fragment = fragment;
         }
 
+        @serialize()
         public get refreshRate(): number {
             return this._refreshRate;
         }
@@ -198,6 +204,10 @@
 
             this.releaseInternalTexture();
             this._texture = this._engine.createRenderTargetTexture(size, generateMipMaps);
+
+            // Update properties
+            this._size = size;
+            this._generateMipMaps = generateMipMaps;
         }
 
         private _checkUniform(uniformName: string): void {

+ 11 - 7
src/Materials/babylon.standardMaterial.ts

@@ -370,9 +370,11 @@ module BABYLON {
             }
 
             // Attaches observer.
-            this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
-                this._markAllSubMeshesAsImageProcessingDirty();
-            });
+            if (this._imageProcessingConfiguration) {
+                this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
+                    this._markAllSubMeshesAsImageProcessingDirty();
+                });
+            }
         }
 
         /**
@@ -735,7 +737,7 @@ module BABYLON {
                 defines.PREMULTIPLYALPHA = (this.alphaMode === Engine.ALPHA_PREMULTIPLIED || this.alphaMode === Engine.ALPHA_PREMULTIPLIED_PORTERDUFF);
             }
 
-            if (defines._areImageProcessingDirty) {
+            if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) {
                 if (!this._imageProcessingConfiguration.isReady()) {
                     return false;
                 }
@@ -890,8 +892,10 @@ module BABYLON {
 
                 var uniformBuffers = ["Material", "Scene"];
 
-                ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
-                ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
+                if (ImageProcessingConfiguration) {
+                    ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
+                    ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
+                }
 
                 MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
                     uniformsNames: uniforms,
@@ -1223,7 +1227,7 @@ module BABYLON {
                 MaterialHelper.BindLogDepth(defines, effect, scene);
 
                 // image processing
-                if (!this._imageProcessingConfiguration.applyByPostProcess) {
+                if (this._imageProcessingConfiguration && !this._imageProcessingConfiguration.applyByPostProcess) {
                     this._imageProcessingConfiguration.bind(this._activeEffect);
                 }
             }

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

@@ -2621,7 +2621,11 @@
                             instance.animations.push(Animation.Parse(parsedAnimation));
                         }
                         Node.ParseAnimationRanges(instance, parsedMesh, scene);
-                    }
+
+                        if (parsedMesh.autoAnimate) {
+                            scene.beginAnimation(instance, parsedMesh.autoAnimateFrom, parsedMesh.autoAnimateTo, parsedMesh.autoAnimateLoop, parsedMesh.autoAnimateSpeed || 1.0);
+                        }                            
+                }
                 }
             }
 

+ 13 - 7
src/PostProcess/babylon.imageProcessingPostProcess.ts

@@ -65,9 +65,11 @@
             }
 
             // Attaches observer.
-            this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
-                this._updateParameters();
-            });
+            if (this._imageProcessingConfiguration) {
+                this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
+                    this._updateParameters();
+                });
+            }
 
             // Ensure the effect will be rebuilt.
             if (!doNotBuild) {
@@ -350,10 +352,12 @@
             }
 
             var samplers = ["textureSampler"];
-            ImageProcessingConfiguration.PrepareSamplers(samplers, this._defines);
-
             var uniforms = ["scale"];
-            ImageProcessingConfiguration.PrepareUniforms(uniforms, this._defines);
+
+            if (ImageProcessingConfiguration) {
+                ImageProcessingConfiguration.PrepareSamplers(samplers, this._defines);
+                ImageProcessingConfiguration.PrepareUniforms(uniforms, this._defines);
+            }
 
             this.updateEffect(defines, uniforms, samplers);
         }
@@ -365,7 +369,9 @@
                 this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
             }
 
-            this.imageProcessingConfiguration.applyByPostProcess = false;
+            if (this._imageProcessingConfiguration) {
+                this.imageProcessingConfiguration.applyByPostProcess = false;
+            }
         }
     }
 }

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

@@ -67,6 +67,10 @@ module BABYLON {
                     if(!prePointerInfo.skipOnPointerObservable){
                         this.utilityLayerScene.onPointerObservable.notifyObservers(new PointerInfo(prePointerInfo.type, prePointerInfo.event, utilityScenePick))
                     }
+                    let pointerEvent = <PointerEvent>(prePointerInfo.event);
+                    if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && this._pointerCaptures[pointerEvent.pointerId]) {
+                        this._pointerCaptures[pointerEvent.pointerId] = false;
+                    }
                     return;
                 }
 
@@ -104,7 +108,7 @@ module BABYLON {
                                 delete this._lastPointerEvents[pointerEvent.pointerId];
                             }
                         }
-
+                        
                         if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && this._pointerCaptures[pointerEvent.pointerId]) {
                             this._pointerCaptures[pointerEvent.pointerId] = false;
                         }

+ 4 - 0
src/Sprites/babylon.sprite.ts

@@ -22,6 +22,10 @@
         private _manager: SpriteManager;
         private _time = 0;
         private _onAnimationEnd: () => void;
+        /**
+         * Gets or sets a boolean indicating if the sprite is visible (renderable). Default is true
+         */
+        public isVisible = true;
 
         public get size(): number {
             return this.width;

+ 1 - 1
src/Sprites/babylon.spriteManager.ts

@@ -207,7 +207,7 @@
             var offset = 0;
             for (var index = 0; index < max; index++) {
                 var sprite = this.sprites[index];
-                if (!sprite) {
+                if (!sprite || !sprite.isVisible) {
                     continue;
                 }
 

+ 13 - 5
src/babylon.scene.ts

@@ -1245,7 +1245,9 @@
 
             this._renderingManager = new RenderingManager(this);
 
-            this.postProcessManager = new PostProcessManager(this);
+            if (PostProcessManager) {
+                this.postProcessManager = new PostProcessManager(this);
+            }
 
             if (OutlineRenderer) {
                 this._outlineRenderer = new OutlineRenderer(this);
@@ -1266,8 +1268,10 @@
             // Uniform Buffer
             this._createUbo();
 
-            // Default Image processing definition.
-            this._imageProcessingConfiguration = new ImageProcessingConfiguration();
+            // Default Image processing definition
+            if (ImageProcessingConfiguration) {
+                this._imageProcessingConfiguration = new ImageProcessingConfiguration();
+            }
         }
 
         /**
@@ -4568,7 +4572,9 @@
             this.onAfterRenderTargetsRenderObservable.notifyObservers(this);
 
             // Prepare Frame
-            this.postProcessManager._prepareFrame();
+            if (this.postProcessManager) {
+                this.postProcessManager._prepareFrame();
+            }
 
             // Backgrounds
             var layerIndex;
@@ -4641,7 +4647,9 @@
             }
             
             // Finalize frame
-            this.postProcessManager._finalizeFrame(camera.isIntermediate);
+            if (this.postProcessManager) {
+                this.postProcessManager._finalizeFrame(camera.isIntermediate);
+            }
 
             // Reset some special arrays
             this._renderTargets.reset();