Bladeren bron

merged with master

Benjamin Guignabert 8 jaren geleden
bovenliggende
commit
f344110abb
37 gewijzigde bestanden met toevoegingen van 16463 en 15984 verwijderingen
  1. 10 1
      .vscode/launch.json
  2. 18 3
      .vscode/tasks.json
  3. 2 0
      canvas2D/src/Engine/babylon.group2d.ts
  4. 33 26
      canvas2D/src/Engine/babylon.prim2dBase.ts
  5. 7305 7299
      dist/preview release/babylon.d.ts
  6. 35 35
      dist/preview release/babylon.js
  7. 40 16
      dist/preview release/babylon.max.js
  8. 7305 7299
      dist/preview release/babylon.module.d.ts
  9. 38 38
      dist/preview release/babylon.worker.js
  10. 30 27
      dist/preview release/canvas2D/babylon.canvas2d.js
  11. 8 8
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  12. 471 460
      dist/preview release/customConfigurations/minimalViewer/babylon.d.ts
  13. 20 20
      dist/preview release/customConfigurations/minimalViewer/babylon.js
  14. 62 38
      dist/preview release/customConfigurations/minimalViewer/babylon.max.js
  15. 471 460
      dist/preview release/customConfigurations/minimalViewer/babylon.module.d.ts
  16. 23 5
      dist/preview release/gui/babylon.gui.d.ts
  17. 254 95
      dist/preview release/gui/babylon.gui.js
  18. 2 2
      dist/preview release/gui/babylon.gui.min.js
  19. 3 1
      dist/preview release/what's new.md
  20. 3 14
      gui/readme.md
  21. 29 17
      gui/src/advancedDynamicTexture.ts
  22. 48 7
      gui/src/controls/button.ts
  23. 30 8
      gui/src/controls/container.ts
  24. 25 6
      gui/src/controls/control.ts
  25. 2 16
      gui/src/controls/ellipse.ts
  26. 82 26
      gui/src/controls/image.ts
  27. 25 15
      gui/src/controls/line.ts
  28. 0 1
      gui/src/controls/rectangle.ts
  29. 31 5
      gui/src/controls/stackPanel.ts
  30. 5 5
      gui/src/controls/textBlock.ts
  31. 2 2
      gui/src/valueAndUnit.ts
  32. 5 2
      src/Cameras/babylon.arcRotateCamera.ts
  33. 25 17
      src/Materials/Textures/babylon.videoTexture.ts
  34. 7 7
      src/Physics/Plugins/babylon.cannonJSPlugin.ts
  35. 2 0
      src/Physics/babylon.physicsImpostor.ts
  36. 9 0
      src/babylon.engine.ts
  37. 3 3
      src/babylon.scene.ts

+ 10 - 1
.vscode/launch.json

@@ -8,6 +8,7 @@
             "url": "http://localhost:1338/sandbox/index-local.html",
             "url": "http://localhost:1338/sandbox/index-local.html",
             "webRoot": "${workspaceRoot}/",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
             "sourceMaps": true,
+            "preLaunchTask": "run",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "runtimeArgs": [
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis" 
                 "--enable-unsafe-es3-apis" 
@@ -19,7 +20,8 @@
             "request": "launch",
             "request": "launch",
             "url": "http://localhost:1338/Playground/index-local.html",
             "url": "http://localhost:1338/Playground/index-local.html",
             "webRoot": "${workspaceRoot}/",
             "webRoot": "${workspaceRoot}/",
-            "sourceMaps": true,
+            "sourceMaps": true,            
+            "preLaunchTask": "run",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "runtimeArgs": [
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis" 
                 "--enable-unsafe-es3-apis" 
@@ -32,6 +34,7 @@
             "url": "http://localhost:1338/Playground/index-local.html",
             "url": "http://localhost:1338/Playground/index-local.html",
             "webRoot": "${workspaceRoot}/",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
             "sourceMaps": true,
+            "preLaunchTask": "run",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "runtimeArgs": [
             "runtimeArgs": [
                 "--disable-es3-apis" 
                 "--disable-es3-apis" 
@@ -44,6 +47,7 @@
             "url": "http://localhost:1338/materialsLibrary/index.html",
             "url": "http://localhost:1338/materialsLibrary/index.html",
             "webRoot": "${workspaceRoot}/",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
             "sourceMaps": true,
+            "preLaunchTask": "run",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "runtimeArgs": [
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis" 
                 "--enable-unsafe-es3-apis" 
@@ -56,6 +60,7 @@
             "url": "http://localhost:1338/postProcessLibrary/index.html",
             "url": "http://localhost:1338/postProcessLibrary/index.html",
             "webRoot": "${workspaceRoot}/",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
             "sourceMaps": true,
+            "preLaunchTask": "run",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "runtimeArgs": [
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis" 
                 "--enable-unsafe-es3-apis" 
@@ -68,6 +73,7 @@
             "url": "http://localhost:1338/proceduralTexturesLibrary/index.html",
             "url": "http://localhost:1338/proceduralTexturesLibrary/index.html",
             "webRoot": "${workspaceRoot}/",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
             "sourceMaps": true,
+            "preLaunchTask": "run",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "runtimeArgs": [
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis" 
                 "--enable-unsafe-es3-apis" 
@@ -80,6 +86,7 @@
             "url": "http://localhost:1338/inspector/index.html",
             "url": "http://localhost:1338/inspector/index.html",
             "webRoot": "${workspaceRoot}/",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
             "sourceMaps": true,
+            "preLaunchTask": "run",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "runtimeArgs": [
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis" 
                 "--enable-unsafe-es3-apis" 
@@ -92,6 +99,7 @@
             "url": "http://localhost:1338/localDev/index.html",
             "url": "http://localhost:1338/localDev/index.html",
             "webRoot": "${workspaceRoot}/",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
             "sourceMaps": true,
+            "preLaunchTask": "run",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "runtimeArgs": [
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis" 
                 "--enable-unsafe-es3-apis" 
@@ -104,6 +112,7 @@
             "url": "http://localhost:1338/tests/validation/index.html",
             "url": "http://localhost:1338/tests/validation/index.html",
             "webRoot": "${workspaceRoot}/",
             "webRoot": "${workspaceRoot}/",
             "sourceMaps": true,
             "sourceMaps": true,
+            "preLaunchTask": "run",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "runtimeArgs": [
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis" 
                 "--enable-unsafe-es3-apis" 

+ 18 - 3
.vscode/tasks.json

@@ -14,9 +14,24 @@
             "taskName": "run",
             "taskName": "run",
             // Hijack Test Command for easy shortcut
             // Hijack Test Command for easy shortcut
             "isTestCommand": true,
             "isTestCommand": true,
-            "problemMatcher": [
-                "$tsc"
-            ]
+            "isBackground": true,
+            "problemMatcher": {
+                "owner": "typescript",
+                "fileLocation": "relative",
+                "pattern": {
+                    "regexp": "^([^\\s].*)\\((\\d+|\\,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$",
+                    "file": 1,
+                    "location": 2,
+                    "severity": 3,
+                    "code": 4,
+                    "message": 5
+                },
+                "watching": {
+                    "activeOnStart": true,
+                    "beginsPattern": "Starting \\'watch\\'",
+                    "endsPattern": "Finished \\'run\\'"
+                }
+            }
         },
         },
         { 
         { 
             "taskName": "typescript-all",
             "taskName": "typescript-all",

+ 2 - 0
canvas2D/src/Engine/babylon.group2d.ts

@@ -558,6 +558,8 @@
                     }
                     }
                 }
                 }
 
 
+                this._renderableData._primDirtyList.length = 0;
+                
                 // Restore saved states
                 // Restore saved states
                 engine.setAlphaTesting(curAlphaTest);
                 engine.setAlphaTesting(curAlphaTest);
                 engine.setDepthWrite(curDepthWrite);
                 engine.setDepthWrite(curDepthWrite);

+ 33 - 26
canvas2D/src/Engine/babylon.prim2dBase.ts

@@ -442,38 +442,45 @@
          */
          */
         fromString(value: string) {
         fromString(value: string) {
             let m = value.trim().split(",");
             let m = value.trim().split(",");
-            if (m.length === 1) {
-                this.setHorizontal(m[0]);
-                this.setVertical(m[0]);
-            } else {
-                for (let v of m) {
-                    v = v.toLocaleLowerCase().trim();
+            
+            var hset = false;
+            var vset = false;
 
 
-                    // Horizontal
-                    let i = v.indexOf("h:");
-                    if (i === -1) {
-                        i = v.indexOf("horizontal:");
-                    }
+            for (let v of m) {
+                v = v.toLocaleLowerCase().trim();
 
 
-                    if (i !== -1) {
-                        v = v.substr(v.indexOf(":") + 1);
-                        this.setHorizontal(v);
-                        continue;
-                    }
+                // Horizontal
+                let i = v.indexOf("h:");
+                if (i === -1) {
+                    i = v.indexOf("horizontal:");
+                }
 
 
-                    // Vertical
-                    i = v.indexOf("v:");
-                    if (i === -1) {
-                        i = v.indexOf("vertical:");
-                    }
+                if (i !== -1) {
+                    v = v.substr(v.indexOf(":") + 1);
+                    this.setHorizontal(v);
+                    hset = true;
+                    continue;
+                }
 
 
-                    if (i !== -1) {
-                        v = v.substr(v.indexOf(":") + 1);
-                        this.setVertical(v);
-                        continue;
-                    }
+                // Vertical
+                i = v.indexOf("v:");
+                if (i === -1) {
+                    i = v.indexOf("vertical:");
+                }
+
+                if (i !== -1) {
+                    v = v.substr(v.indexOf(":") + 1);
+                    this.setVertical(v);
+                    vset = true;
+                    continue;
                 }
                 }
             }
             }
+
+            if (!hset && !vset && m.length === 1) {
+                this.setHorizontal(m[0]);
+                this.setVertical(m[0]);
+            }
+
         }
         }
 
 
         copyFrom(pa: PrimitiveAlignment) {
         copyFrom(pa: PrimitiveAlignment) {

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


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


+ 40 - 16
dist/preview release/babylon.max.js

@@ -7521,6 +7521,13 @@ var BABYLON;
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
         });
         });
+        Object.defineProperty(Engine, "ALPHA_PREMULTIPLIED_PORTERDUFF", {
+            get: function () {
+                return Engine._ALPHA_PREMULTIPLIED_PORTERDUFF;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Engine, "DELAYLOADSTATE_NONE", {
         Object.defineProperty(Engine, "DELAYLOADSTATE_NONE", {
             get: function () {
             get: function () {
                 return Engine._DELAYLOADSTATE_NONE;
                 return Engine._DELAYLOADSTATE_NONE;
@@ -8755,6 +8762,10 @@ var BABYLON;
                     this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
                     this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
                     this._alphaState.alphaBlend = true;
                     this._alphaState.alphaBlend = true;
                     break;
                     break;
+                case Engine.ALPHA_PREMULTIPLIED_PORTERDUFF:
+                    this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA);
+                    this._alphaState.alphaBlend = true;
+                    break;
                 case Engine.ALPHA_COMBINE:
                 case Engine.ALPHA_COMBINE:
                     this._alphaState.setAlphaBlendFunctionParameters(this._gl.SRC_ALPHA, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
                     this._alphaState.setAlphaBlendFunctionParameters(this._gl.SRC_ALPHA, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
                     this._alphaState.alphaBlend = true;
                     this._alphaState.alphaBlend = true;
@@ -10177,6 +10188,7 @@ var BABYLON;
     Engine._ALPHA_MAXIMIZED = 5;
     Engine._ALPHA_MAXIMIZED = 5;
     Engine._ALPHA_ONEONE = 6;
     Engine._ALPHA_ONEONE = 6;
     Engine._ALPHA_PREMULTIPLIED = 7;
     Engine._ALPHA_PREMULTIPLIED = 7;
+    Engine._ALPHA_PREMULTIPLIED_PORTERDUFF = 8;
     Engine._DELAYLOADSTATE_NONE = 0;
     Engine._DELAYLOADSTATE_NONE = 0;
     Engine._DELAYLOADSTATE_LOADED = 1;
     Engine._DELAYLOADSTATE_LOADED = 1;
     Engine._DELAYLOADSTATE_LOADING = 2;
     Engine._DELAYLOADSTATE_LOADING = 2;
@@ -15620,7 +15632,7 @@ var BABYLON;
                 }
                 }
                 var canvas = _this._engine.getRenderingCanvas();
                 var canvas = _this._engine.getRenderingCanvas();
                 if (!_this.pointerMovePredicate) {
                 if (!_this.pointerMovePredicate) {
-                    _this.pointerMovePredicate = function (mesh) { return mesh.isPickable && mesh.isVisible && mesh.isReady() && (_this.constantlyUpdateMeshUnderPointer || (mesh.actionManager !== null && mesh.actionManager !== undefined)); };
+                    _this.pointerMovePredicate = function (mesh) { return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.isEnabled() && (_this.constantlyUpdateMeshUnderPointer || (mesh.actionManager !== null && mesh.actionManager !== undefined)); };
                 }
                 }
                 // Meshes
                 // Meshes
                 var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this.pointerMovePredicate, false, _this.cameraToUseForPointers);
                 var pickResult = _this.pick(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this.pointerMovePredicate, false, _this.cameraToUseForPointers);
@@ -15689,7 +15701,7 @@ var BABYLON;
                 _this._startingPointerTime = new Date().getTime();
                 _this._startingPointerTime = new Date().getTime();
                 if (!_this.pointerDownPredicate) {
                 if (!_this.pointerDownPredicate) {
                     _this.pointerDownPredicate = function (mesh) {
                     _this.pointerDownPredicate = function (mesh) {
-                        return mesh.isPickable && mesh.isVisible && mesh.isReady();
+                        return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.isEnabled();
                     };
                     };
                 }
                 }
                 // Meshes
                 // Meshes
@@ -15805,7 +15817,7 @@ var BABYLON;
                     }
                     }
                     if (!this.pointerUpPredicate) {
                     if (!this.pointerUpPredicate) {
                         this.pointerUpPredicate = function (mesh) {
                         this.pointerUpPredicate = function (mesh) {
-                            return mesh.isPickable && mesh.isVisible && mesh.isReady();
+                            return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.isEnabled();
                         };
                         };
                     }
                     }
                     // Meshes
                     // Meshes
@@ -31482,6 +31494,7 @@ var BABYLON;
             _this.upperRadiusLimit = null;
             _this.upperRadiusLimit = null;
             _this.inertialPanningX = 0;
             _this.inertialPanningX = 0;
             _this.inertialPanningY = 0;
             _this.inertialPanningY = 0;
+            _this.panningInertia = 0.9;
             //-- end properties for backward compatibility for inputs
             //-- end properties for backward compatibility for inputs
             _this.zoomOnFactor = 1;
             _this.zoomOnFactor = 1;
             _this.targetScreenOffset = BABYLON.Vector2.Zero();
             _this.targetScreenOffset = BABYLON.Vector2.Zero();
@@ -31786,8 +31799,8 @@ var BABYLON;
                 if (!this._targetHost) {
                 if (!this._targetHost) {
                     this._target.addInPlace(this._transformedDirection);
                     this._target.addInPlace(this._transformedDirection);
                 }
                 }
-                this.inertialPanningX *= this.inertia;
-                this.inertialPanningY *= this.inertia;
+                this.inertialPanningX *= this.panningInertia;
+                this.inertialPanningY *= this.panningInertia;
                 if (Math.abs(this.inertialPanningX) < this.speed * BABYLON.Epsilon)
                 if (Math.abs(this.inertialPanningX) < this.speed * BABYLON.Epsilon)
                     this.inertialPanningX = 0;
                     this.inertialPanningX = 0;
                 if (Math.abs(this.inertialPanningY) < this.speed * BABYLON.Epsilon)
                 if (Math.abs(this.inertialPanningY) < this.speed * BABYLON.Epsilon)
@@ -32040,6 +32053,9 @@ var BABYLON;
     ], ArcRotateCamera.prototype, "inertialPanningY", void 0);
     ], ArcRotateCamera.prototype, "inertialPanningY", void 0);
     __decorate([
     __decorate([
         BABYLON.serialize()
         BABYLON.serialize()
+    ], ArcRotateCamera.prototype, "panningInertia", void 0);
+    __decorate([
+        BABYLON.serialize()
     ], ArcRotateCamera.prototype, "zoomOnFactor", void 0);
     ], ArcRotateCamera.prototype, "zoomOnFactor", void 0);
     __decorate([
     __decorate([
         BABYLON.serialize()
         BABYLON.serialize()
@@ -42179,16 +42195,17 @@ var BABYLON;
             _this._lastUpdate = BABYLON.Tools.Now;
             _this._lastUpdate = BABYLON.Tools.Now;
             return _this;
             return _this;
         }
         }
+        VideoTexture.prototype.__setTextureReady = function () {
+            this._texture.isReady = true;
+        };
         VideoTexture.prototype._createTexture = function () {
         VideoTexture.prototype._createTexture = function () {
-            var _this = this;
             this._texture = this.getScene().getEngine().createDynamicTexture(this.video.videoWidth, this.video.videoHeight, this._generateMipMaps, this._samplingMode);
             this._texture = this.getScene().getEngine().createDynamicTexture(this.video.videoWidth, this.video.videoHeight, this._generateMipMaps, this._samplingMode);
             if (this._autoLaunch) {
             if (this._autoLaunch) {
                 this._autoLaunch = false;
                 this._autoLaunch = false;
                 this.video.play();
                 this.video.play();
             }
             }
-            this.video.addEventListener("playing", function () {
-                _this._texture.isReady = true;
-            });
+            this._setTextureReady = this.__setTextureReady.bind(this);
+            this.video.addEventListener("playing", this._setTextureReady);
         };
         };
         VideoTexture.prototype.update = function () {
         VideoTexture.prototype.update = function () {
             var now = BABYLON.Tools.Now;
             var now = BABYLON.Tools.Now;
@@ -42199,6 +42216,10 @@ var BABYLON;
             this.getScene().getEngine().updateVideoTexture(this._texture, this.video, this._invertY);
             this.getScene().getEngine().updateVideoTexture(this._texture, this.video, this._invertY);
             return true;
             return true;
         };
         };
+        VideoTexture.prototype.dispose = function () {
+            _super.prototype.dispose.call(this);
+            this.video.removeEventListener("playing", this._setTextureReady);
+        };
         VideoTexture.CreateFromWebCam = function (scene, onReady, constraints) {
         VideoTexture.CreateFromWebCam = function (scene, onReady, constraints) {
             var video = document.createElement("video");
             var video = document.createElement("video");
             var constraintsDeviceId;
             var constraintsDeviceId;
@@ -55944,6 +55965,9 @@ var BABYLON;
                 if (!this.object.parent) {
                 if (!this.object.parent) {
                     this._init();
                     this._init();
                 }
                 }
+                else if (this.object.parent.physicsImpostor) {
+                    BABYLON.Tools.Warn("You must affect impostors to children before affecting impostor to parent.");
+                }
             }
             }
         }
         }
         /**
         /**
@@ -56625,9 +56649,9 @@ var BABYLON;
             //For now pointDepth will not be used and will be automatically calculated.
             //For now pointDepth will not be used and will be automatically calculated.
             //Future reference - try and find the best place to add a reference to the pointDepth variable.
             //Future reference - try and find the best place to add a reference to the pointDepth variable.
             var arraySize = pointDepth || ~~(Math.sqrt(pos.length / 3) - 1);
             var arraySize = pointDepth || ~~(Math.sqrt(pos.length / 3) - 1);
-            var dim = Math.min(object.getBoundingInfo().boundingBox.extendSize.x, object.getBoundingInfo().boundingBox.extendSize.z);
+            var dim = Math.min(object.getBoundingInfo().boundingBox.extendSizeWorld.x, object.getBoundingInfo().boundingBox.extendSizeWorld.z);
             var elementSize = dim * 2 / arraySize;
             var elementSize = dim * 2 / arraySize;
-            var minY = object.getBoundingInfo().boundingBox.extendSize.y;
+            var minY = object.getBoundingInfo().boundingBox.extendSizeWorld.y;
             for (var i = 0; i < pos.length; i = i + 3) {
             for (var i = 0; i < pos.length; i = i + 3) {
                 var x = Math.round((pos[i + 0]) / elementSize + arraySize / 2);
                 var x = Math.round((pos[i + 0]) / elementSize + arraySize / 2);
                 var z = Math.round(((pos[i + 2]) / elementSize - arraySize / 2) * -1);
                 var z = Math.round(((pos[i + 2]) / elementSize - arraySize / 2) * -1);
@@ -56697,15 +56721,15 @@ var BABYLON;
                 //rotation is back
                 //rotation is back
                 mesh.rotationQuaternion = rotationQuaternion;
                 mesh.rotationQuaternion = rotationQuaternion;
                 //calculate the new center using a pivot (since Cannon.js doesn't center height maps)
                 //calculate the new center using a pivot (since Cannon.js doesn't center height maps)
-                var p = BABYLON.Matrix.Translation(mesh.getBoundingInfo().boundingBox.extendSize.x, 0, -mesh.getBoundingInfo().boundingBox.extendSize.z);
+                var p = BABYLON.Matrix.Translation(mesh.getBoundingInfo().boundingBox.extendSizeWorld.x, 0, -mesh.getBoundingInfo().boundingBox.extendSizeWorld.z);
                 mesh.setPivotMatrix(p);
                 mesh.setPivotMatrix(p);
                 mesh.computeWorldMatrix(true);
                 mesh.computeWorldMatrix(true);
                 //calculate the translation
                 //calculate the translation
-                var translation = mesh.getBoundingInfo().boundingBox.center.subtract(center).subtract(mesh.position).negate();
-                this._tmpPosition.copyFromFloats(translation.x, translation.y - mesh.getBoundingInfo().boundingBox.extendSize.y, translation.z);
+                var translation = mesh.getBoundingInfo().boundingBox.centerWorld.subtract(center).subtract(mesh.position).negate();
+                this._tmpPosition.copyFromFloats(translation.x, translation.y - mesh.getBoundingInfo().boundingBox.extendSizeWorld.y, translation.z);
                 //add it inverted to the delta 
                 //add it inverted to the delta 
-                this._tmpDeltaPosition.copyFrom(mesh.getBoundingInfo().boundingBox.center.subtract(c));
-                this._tmpDeltaPosition.y += mesh.getBoundingInfo().boundingBox.extendSize.y;
+                this._tmpDeltaPosition.copyFrom(mesh.getBoundingInfo().boundingBox.centerWorld.subtract(c));
+                this._tmpDeltaPosition.y += mesh.getBoundingInfo().boundingBox.extendSizeWorld.y;
                 mesh.setPivotMatrix(oldPivot);
                 mesh.setPivotMatrix(oldPivot);
                 mesh.computeWorldMatrix(true);
                 mesh.computeWorldMatrix(true);
             }
             }

File diff suppressed because it is too large
+ 7305 - 7299
dist/preview release/babylon.module.d.ts


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


+ 30 - 27
dist/preview release/canvas2D/babylon.canvas2d.js

@@ -6140,36 +6140,38 @@ var BABYLON;
          */
          */
         PrimitiveAlignment.prototype.fromString = function (value) {
         PrimitiveAlignment.prototype.fromString = function (value) {
             var m = value.trim().split(",");
             var m = value.trim().split(",");
-            if (m.length === 1) {
+            var hset = false;
+            var vset = false;
+            for (var _i = 0, m_1 = m; _i < m_1.length; _i++) {
+                var v = m_1[_i];
+                v = v.toLocaleLowerCase().trim();
+                // Horizontal
+                var i = v.indexOf("h:");
+                if (i === -1) {
+                    i = v.indexOf("horizontal:");
+                }
+                if (i !== -1) {
+                    v = v.substr(v.indexOf(":") + 1);
+                    this.setHorizontal(v);
+                    hset = true;
+                    continue;
+                }
+                // Vertical
+                i = v.indexOf("v:");
+                if (i === -1) {
+                    i = v.indexOf("vertical:");
+                }
+                if (i !== -1) {
+                    v = v.substr(v.indexOf(":") + 1);
+                    this.setVertical(v);
+                    vset = true;
+                    continue;
+                }
+            }
+            if (!hset && !vset && m.length === 1) {
                 this.setHorizontal(m[0]);
                 this.setHorizontal(m[0]);
                 this.setVertical(m[0]);
                 this.setVertical(m[0]);
             }
             }
-            else {
-                for (var _i = 0, m_1 = m; _i < m_1.length; _i++) {
-                    var v = m_1[_i];
-                    v = v.toLocaleLowerCase().trim();
-                    // Horizontal
-                    var i = v.indexOf("h:");
-                    if (i === -1) {
-                        i = v.indexOf("horizontal:");
-                    }
-                    if (i !== -1) {
-                        v = v.substr(v.indexOf(":") + 1);
-                        this.setHorizontal(v);
-                        continue;
-                    }
-                    // Vertical
-                    i = v.indexOf("v:");
-                    if (i === -1) {
-                        i = v.indexOf("vertical:");
-                    }
-                    if (i !== -1) {
-                        v = v.substr(v.indexOf(":") + 1);
-                        this.setVertical(v);
-                        continue;
-                    }
-                }
-            }
         };
         };
         PrimitiveAlignment.prototype.copyFrom = function (pa) {
         PrimitiveAlignment.prototype.copyFrom = function (pa) {
             this._horizontal = pa._horizontal;
             this._horizontal = pa._horizontal;
@@ -12093,6 +12095,7 @@ var BABYLON;
                         engine.setViewport(curVP);
                         engine.setViewport(curVP);
                     }
                     }
                 }
                 }
+                this._renderableData._primDirtyList.length = 0;
                 // Restore saved states
                 // Restore saved states
                 engine.setAlphaTesting(curAlphaTest);
                 engine.setAlphaTesting(curAlphaTest);
                 engine.setDepthWrite(curDepthWrite);
                 engine.setDepthWrite(curDepthWrite);

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


File diff suppressed because it is too large
+ 471 - 460
dist/preview release/customConfigurations/minimalViewer/babylon.d.ts


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


File diff suppressed because it is too large
+ 62 - 38
dist/preview release/customConfigurations/minimalViewer/babylon.max.js


File diff suppressed because it is too large
+ 471 - 460
dist/preview release/customConfigurations/minimalViewer/babylon.module.d.ts


+ 23 - 5
dist/preview release/gui/babylon.gui.d.ts

@@ -5,14 +5,16 @@ declare module BABYLON.GUI {
         private _renderObserver;
         private _renderObserver;
         private _resizeObserver;
         private _resizeObserver;
         private _pointerMoveObserver;
         private _pointerMoveObserver;
+        private _pointerObserver;
         private _background;
         private _background;
         _rootContainer: Container;
         _rootContainer: Container;
         _lastControlOver: Control;
         _lastControlOver: Control;
         _lastControlDown: Control;
         _lastControlDown: Control;
         _shouldBlockPointer: boolean;
         _shouldBlockPointer: boolean;
-        _toDispose: IDisposable;
+        _layerToDispose: Layer;
         _linkedControls: Control[];
         _linkedControls: Control[];
         private _isFullscreen;
         private _isFullscreen;
+        private _fullscreenViewport;
         background: string;
         background: string;
         constructor(name: string, width: number, height: number, scene: Scene, generateMipMaps?: boolean, samplingMode?: number);
         constructor(name: string, width: number, height: number, scene: Scene, generateMipMaps?: boolean, samplingMode?: number);
         markAsDirty(): void;
         markAsDirty(): void;
@@ -24,6 +26,7 @@ declare module BABYLON.GUI {
         private _render();
         private _render();
         private _doPicking(x, y, type);
         private _doPicking(x, y, type);
         attach(): void;
         attach(): void;
+        attachToMesh(mesh: AbstractMesh): void;
         static CreateForMesh(mesh: AbstractMesh, width?: number, height?: number): AdvancedDynamicTexture;
         static CreateForMesh(mesh: AbstractMesh, width?: number, height?: number): AdvancedDynamicTexture;
         static CreateFullscreenUI(name: string, foreground: boolean, scene: Scene): AdvancedDynamicTexture;
         static CreateFullscreenUI(name: string, foreground: boolean, scene: Scene): AdvancedDynamicTexture;
     }
     }
@@ -195,7 +198,7 @@ declare module BABYLON.GUI {
         _link(root: Container, host: AdvancedDynamicTexture): void;
         _link(root: Container, host: AdvancedDynamicTexture): void;
         protected _transform(context: CanvasRenderingContext2D): void;
         protected _transform(context: CanvasRenderingContext2D): void;
         protected _applyStates(context: CanvasRenderingContext2D): void;
         protected _applyStates(context: CanvasRenderingContext2D): void;
-        protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D): boolean;
         protected _clip(context: CanvasRenderingContext2D): void;
         protected _clip(context: CanvasRenderingContext2D): void;
         _measure(): void;
         _measure(): void;
         protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -237,6 +240,9 @@ declare module BABYLON.GUI {
         name: string;
         name: string;
         protected _children: Control[];
         protected _children: Control[];
         protected _measureForChildren: Measure;
         protected _measureForChildren: Measure;
+        protected _background: string;
+        background: string;
+        readonly children: Control[];
         constructor(name: string);
         constructor(name: string);
         containsControl(control: Control): boolean;
         containsControl(control: Control): boolean;
         addControl(control: Control): Container;
         addControl(control: Control): Container;
@@ -256,6 +262,8 @@ declare module BABYLON.GUI {
 declare module BABYLON.GUI {
 declare module BABYLON.GUI {
     class StackPanel extends Container {
     class StackPanel extends Container {
         name: string;
         name: string;
+        private _isVertical;
+        isVertical: boolean;
         constructor(name: string);
         constructor(name: string);
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
     }
     }
@@ -266,7 +274,6 @@ declare module BABYLON.GUI {
     class Rectangle extends Container {
     class Rectangle extends Container {
         name: string;
         name: string;
         private _thickness;
         private _thickness;
-        private _background;
         private _cornerRadius;
         private _cornerRadius;
         thickness: number;
         thickness: number;
         cornerRadius: number;
         cornerRadius: number;
@@ -284,9 +291,7 @@ declare module BABYLON.GUI {
     class Ellipse extends Container {
     class Ellipse extends Container {
         name: string;
         name: string;
         private _thickness;
         private _thickness;
-        private _background;
         thickness: number;
         thickness: number;
-        background: string;
         constructor(name: string);
         constructor(name: string);
         protected _localDraw(context: CanvasRenderingContext2D): void;
         protected _localDraw(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -307,6 +312,7 @@ declare module BABYLON.GUI {
         private _y2;
         private _y2;
         private _dash;
         private _dash;
         private _connectedControl;
         private _connectedControl;
+        private _connectedControlDirtyObserver;
         dash: Array<number>;
         dash: Array<number>;
         connectedControl: Control;
         connectedControl: Control;
         x1: number;
         x1: number;
@@ -357,15 +363,22 @@ declare module BABYLON.GUI {
         private _imageHeight;
         private _imageHeight;
         private _loaded;
         private _loaded;
         private _stretch;
         private _stretch;
+        private _source;
+        private _autoScale;
+        autoScale: boolean;
         stretch: number;
         stretch: number;
+        source: string;
         constructor(name: string, url: string);
         constructor(name: string, url: string);
+        synchronizeSizeWithContent(): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         private static _STRETCH_NONE;
         private static _STRETCH_NONE;
         private static _STRETCH_FILL;
         private static _STRETCH_FILL;
         private static _STRETCH_UNIFORM;
         private static _STRETCH_UNIFORM;
+        private static _STRETCH_EXTEND;
         static readonly STRETCH_NONE: number;
         static readonly STRETCH_NONE: number;
         static readonly STRETCH_FILL: number;
         static readonly STRETCH_FILL: number;
         static readonly STRETCH_UNIFORM: number;
         static readonly STRETCH_UNIFORM: number;
+        static readonly STRETCH_EXTEND: number;
     }
     }
 }
 }
 
 
@@ -373,6 +386,10 @@ declare module BABYLON.GUI {
 declare module BABYLON.GUI {
 declare module BABYLON.GUI {
     class Button extends Rectangle {
     class Button extends Rectangle {
         name: string;
         name: string;
+        pointerEnterAnimation: () => void;
+        pointerOutAnimation: () => void;
+        pointerDownAnimation: () => void;
+        pointerUpAnimation: () => void;
         constructor(name: string);
         constructor(name: string);
         _processPicking(x: number, y: number, type: number): boolean;
         _processPicking(x: number, y: number, type: number): boolean;
         protected _onPointerEnter(): void;
         protected _onPointerEnter(): void;
@@ -380,6 +397,7 @@ declare module BABYLON.GUI {
         protected _onPointerDown(): void;
         protected _onPointerDown(): void;
         protected _onPointerUp(): void;
         protected _onPointerUp(): void;
         static CreateImageButton(name: string, text: string, imageUrl: string): Button;
         static CreateImageButton(name: string, text: string, imageUrl: string): Button;
+        static CreateImageOnlyButton(name: string, imageUrl: string): Button;
         static CreateSimpleButton(name: string, text: string): Button;
         static CreateSimpleButton(name: string, text: string): Button;
     }
     }
 }
 }

+ 254 - 95
dist/preview release/gui/babylon.gui.js

@@ -25,6 +25,7 @@ var BABYLON;
                 _this._rootContainer = new GUI.Container("root");
                 _this._rootContainer = new GUI.Container("root");
                 _this._linkedControls = new Array();
                 _this._linkedControls = new Array();
                 _this._isFullscreen = false;
                 _this._isFullscreen = false;
+                _this._fullscreenViewport = new BABYLON.Viewport(0, 0, 1, 1);
                 _this._renderObserver = _this.getScene().onBeforeCameraRenderObservable.add(function (camera) { return _this._checkUpdate(camera); });
                 _this._renderObserver = _this.getScene().onBeforeCameraRenderObservable.add(function (camera) { return _this._checkUpdate(camera); });
                 _this._rootContainer._link(null, _this);
                 _this._rootContainer._link(null, _this);
                 _this.hasAlpha = true;
                 _this.hasAlpha = true;
@@ -67,9 +68,13 @@ var BABYLON;
                 if (this._pointerMoveObserver) {
                 if (this._pointerMoveObserver) {
                     this.getScene().onPrePointerObservable.remove(this._pointerMoveObserver);
                     this.getScene().onPrePointerObservable.remove(this._pointerMoveObserver);
                 }
                 }
-                if (this._toDispose) {
-                    this._toDispose.dispose();
-                    this._toDispose = null;
+                if (this._pointerObserver) {
+                    this.getScene().onPointerObservable.remove(this._pointerObserver);
+                }
+                if (this._layerToDispose) {
+                    this._layerToDispose.texture = null;
+                    this._layerToDispose.dispose();
+                    this._layerToDispose = null;
                 }
                 }
                 _super.prototype.dispose.call(this);
                 _super.prototype.dispose.call(this);
             };
             };
@@ -88,8 +93,7 @@ var BABYLON;
                 if (this._isFullscreen && this._linkedControls.length) {
                 if (this._isFullscreen && this._linkedControls.length) {
                     var scene = this.getScene();
                     var scene = this.getScene();
                     var engine = scene.getEngine();
                     var engine = scene.getEngine();
-                    var viewport = camera.viewport;
-                    var globalViewport = viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
+                    var globalViewport = this._fullscreenViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
                     for (var _i = 0, _a = this._linkedControls; _i < _a.length; _i++) {
                     for (var _i = 0, _a = this._linkedControls; _i < _a.length; _i++) {
                         var control = _a[_i];
                         var control = _a[_i];
                         var mesh = control._linkedMesh;
                         var mesh = control._linkedMesh;
@@ -147,6 +151,20 @@ var BABYLON;
                     pi.skipOnPointerObservable = _this._shouldBlockPointer && pi.type !== BABYLON.PointerEventTypes.POINTERUP;
                     pi.skipOnPointerObservable = _this._shouldBlockPointer && pi.type !== BABYLON.PointerEventTypes.POINTERUP;
                 });
                 });
             };
             };
+            AdvancedDynamicTexture.prototype.attachToMesh = function (mesh) {
+                var _this = this;
+                var scene = this.getScene();
+                this._pointerObserver = scene.onPointerObservable.add(function (pi, state) {
+                    if (pi.type !== BABYLON.PointerEventTypes.POINTERUP && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
+                        return;
+                    }
+                    if (pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
+                        var uv = pi.pickInfo.getTextureCoordinates();
+                        var size = _this.getSize();
+                        _this._doPicking(uv.x * size.width, (1.0 - uv.y) * size.height, pi.type);
+                    }
+                });
+            };
             // Statics
             // Statics
             AdvancedDynamicTexture.CreateForMesh = function (mesh, width, height) {
             AdvancedDynamicTexture.CreateForMesh = function (mesh, width, height) {
                 if (width === void 0) { width = 1024; }
                 if (width === void 0) { width = 1024; }
@@ -159,15 +177,7 @@ var BABYLON;
                 material.emissiveTexture = result;
                 material.emissiveTexture = result;
                 material.opacityTexture = result;
                 material.opacityTexture = result;
                 mesh.material = material;
                 mesh.material = material;
-                mesh.getScene().onPointerObservable.add(function (pi, state) {
-                    if (pi.type !== BABYLON.PointerEventTypes.POINTERUP && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
-                        return;
-                    }
-                    if (pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
-                        var uv = pi.pickInfo.getTextureCoordinates();
-                        result._doPicking(uv.x * width, (1.0 - uv.y) * height, pi.type);
-                    }
-                });
+                result.attachToMesh(mesh);
                 return result;
                 return result;
             };
             };
             AdvancedDynamicTexture.CreateFullscreenUI = function (name, foreground, scene) {
             AdvancedDynamicTexture.CreateFullscreenUI = function (name, foreground, scene) {
@@ -176,7 +186,7 @@ var BABYLON;
                 // Display
                 // Display
                 var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
                 var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
                 layer.texture = result;
                 layer.texture = result;
-                result._toDispose = layer;
+                result._layerToDispose = layer;
                 result._isFullscreen = true;
                 result._isFullscreen = true;
                 // Attach
                 // Attach
                 result.attach();
                 result.attach();
@@ -380,9 +390,9 @@ var BABYLON;
             ValueAndUnit.prototype.toString = function () {
             ValueAndUnit.prototype.toString = function () {
                 switch (this.unit) {
                 switch (this.unit) {
                     case ValueAndUnit.UNITMODE_PERCENTAGE:
                     case ValueAndUnit.UNITMODE_PERCENTAGE:
-                        return this.unit + "%";
+                        return this.value + "%";
                     case ValueAndUnit.UNITMODE_PIXEL:
                     case ValueAndUnit.UNITMODE_PIXEL:
-                        return this.unit + "px";
+                        return this.value + "px";
                 }
                 }
                 return this.unit.toString();
                 return this.unit.toString();
             };
             };
@@ -829,6 +839,7 @@ var BABYLON;
             };
             };
             Control.prototype._markMatrixAsDirty = function () {
             Control.prototype._markMatrixAsDirty = function () {
                 this._isMatrixDirty = true;
                 this._isMatrixDirty = true;
+                this._markAsDirty();
             };
             };
             Control.prototype._markAsDirty = function () {
             Control.prototype._markAsDirty = function () {
                 this._isDirty = true;
                 this._isDirty = true;
@@ -845,15 +856,15 @@ var BABYLON;
                 if (!this._isMatrixDirty && this._scaleX === 1 && this._scaleY === 1 && this._rotation === 0) {
                 if (!this._isMatrixDirty && this._scaleX === 1 && this._scaleY === 1 && this._rotation === 0) {
                     return;
                     return;
                 }
                 }
-                // preTranslate
+                // postTranslate
                 var offsetX = this._currentMeasure.width * this._transformCenterX + this._currentMeasure.left;
                 var offsetX = this._currentMeasure.width * this._transformCenterX + this._currentMeasure.left;
                 var offsetY = this._currentMeasure.height * this._transformCenterY + this._currentMeasure.top;
                 var offsetY = this._currentMeasure.height * this._transformCenterY + this._currentMeasure.top;
                 context.translate(offsetX, offsetY);
                 context.translate(offsetX, offsetY);
-                // scale
-                context.scale(this._scaleX, this._scaleY);
                 // rotate
                 // rotate
                 context.rotate(this._rotation);
                 context.rotate(this._rotation);
-                // postTranslate
+                // scale
+                context.scale(this._scaleX, this._scaleY);
+                // preTranslate
                 context.translate(-offsetX, -offsetY);
                 context.translate(-offsetX, -offsetY);
                 // Need to update matrices?
                 // Need to update matrices?
                 if (this._isMatrixDirty || this._cachedOffsetX !== offsetX || this._cachedOffsetY !== offsetY) {
                 if (this._isMatrixDirty || this._cachedOffsetX !== offsetX || this._cachedOffsetY !== offsetY) {
@@ -891,11 +902,24 @@ var BABYLON;
                         this.onDirtyObservable.notifyObservers(this);
                         this.onDirtyObservable.notifyObservers(this);
                     }
                     }
                 }
                 }
+                if (this._currentMeasure.left > parentMeasure.left + parentMeasure.width) {
+                    return false;
+                }
+                if (this._currentMeasure.left + this._currentMeasure.width < parentMeasure.left) {
+                    return false;
+                }
+                if (this._currentMeasure.top > parentMeasure.top + parentMeasure.height) {
+                    return false;
+                }
+                if (this._currentMeasure.top + this._currentMeasure.height < parentMeasure.top) {
+                    return false;
+                }
                 // Transform
                 // Transform
                 this._transform(context);
                 this._transform(context);
                 // Clip
                 // Clip
                 this._clip(context);
                 this._clip(context);
                 context.clip();
                 context.clip();
+                return true;
             };
             };
             Control.prototype._clip = function (context) {
             Control.prototype._clip = function (context) {
                 context.beginPath();
                 context.beginPath();
@@ -1201,6 +1225,27 @@ var BABYLON;
                 _this._measureForChildren = GUI.Measure.Empty();
                 _this._measureForChildren = GUI.Measure.Empty();
                 return _this;
                 return _this;
             }
             }
+            Object.defineProperty(Container.prototype, "background", {
+                get: function () {
+                    return this._background;
+                },
+                set: function (value) {
+                    if (this._background === value) {
+                        return;
+                    }
+                    this._background = value;
+                    this._markAsDirty();
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(Container.prototype, "children", {
+                get: function () {
+                    return this._children;
+                },
+                enumerable: true,
+                configurable: true
+            });
             Container.prototype.containsControl = function (control) {
             Container.prototype.containsControl = function (control) {
                 return this._children.indexOf(control) !== -1;
                 return this._children.indexOf(control) !== -1;
             };
             };
@@ -1240,7 +1285,10 @@ var BABYLON;
                 }
                 }
             };
             };
             Container.prototype._localDraw = function (context) {
             Container.prototype._localDraw = function (context) {
-                // Implemented by child to be injected inside main draw
+                if (this._background) {
+                    context.fillStyle = this._background;
+                    context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+                }
             };
             };
             Container.prototype._link = function (root, host) {
             Container.prototype._link = function (root, host) {
                 _super.prototype._link.call(this, root, host);
                 _super.prototype._link.call(this, root, host);
@@ -1251,13 +1299,14 @@ var BABYLON;
             };
             };
             Container.prototype._draw = function (parentMeasure, context) {
             Container.prototype._draw = function (parentMeasure, context) {
                 context.save();
                 context.save();
-                _super.prototype._processMeasures.call(this, parentMeasure, context);
                 this._applyStates(context);
                 this._applyStates(context);
-                this._localDraw(context);
-                this._clipForChildren(context);
-                for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
-                    var child = _a[_i];
-                    child._draw(this._measureForChildren, context);
+                if (this._processMeasures(parentMeasure, context)) {
+                    this._localDraw(context);
+                    this._clipForChildren(context);
+                    for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
+                        var child = _a[_i];
+                        child._draw(this._measureForChildren, context);
+                    }
                 }
                 }
                 context.restore();
                 context.restore();
             };
             };
@@ -1309,19 +1358,46 @@ var BABYLON;
             function StackPanel(name) {
             function StackPanel(name) {
                 var _this = _super.call(this, name) || this;
                 var _this = _super.call(this, name) || this;
                 _this.name = name;
                 _this.name = name;
+                _this._isVertical = true;
                 return _this;
                 return _this;
             }
             }
+            Object.defineProperty(StackPanel.prototype, "isVertical", {
+                get: function () {
+                    return this._isVertical;
+                },
+                set: function (value) {
+                    if (this._isVertical === value) {
+                        return;
+                    }
+                    this._isVertical = value;
+                    this._markAsDirty();
+                },
+                enumerable: true,
+                configurable: true
+            });
             StackPanel.prototype._additionalProcessing = function (parentMeasure, context) {
             StackPanel.prototype._additionalProcessing = function (parentMeasure, context) {
-                var top = 0;
+                var stack = 0;
                 for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
                 for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
                     var child = _a[_i];
                     var child = _a[_i];
                     child._currentMeasure.copyFrom(parentMeasure);
                     child._currentMeasure.copyFrom(parentMeasure);
                     child._measure();
                     child._measure();
-                    child.top = top + "px";
-                    top += child._currentMeasure.height;
-                    child.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+                    if (this._isVertical) {
+                        child.top = stack + "px";
+                        stack += child._currentMeasure.height;
+                        child.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+                    }
+                    else {
+                        child.left = stack + "px";
+                        stack += child._currentMeasure.width;
+                        child.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+                    }
+                }
+                if (this._isVertical) {
+                    this.height = stack + "px";
+                }
+                else {
+                    this.width = stack + "px";
                 }
                 }
-                this.height = top + "px";
                 _super.prototype._additionalProcessing.call(this, parentMeasure, context);
                 _super.prototype._additionalProcessing.call(this, parentMeasure, context);
             };
             };
             return StackPanel;
             return StackPanel;
@@ -1505,20 +1581,6 @@ var BABYLON;
                 enumerable: true,
                 enumerable: true,
                 configurable: true
                 configurable: true
             });
             });
-            Object.defineProperty(Ellipse.prototype, "background", {
-                get: function () {
-                    return this._background;
-                },
-                set: function (value) {
-                    if (this._background === value) {
-                        return;
-                    }
-                    this._background = value;
-                    this._markAsDirty();
-                },
-                enumerable: true,
-                configurable: true
-            });
             Ellipse.prototype._localDraw = function (context) {
             Ellipse.prototype._localDraw = function (context) {
                 context.save();
                 context.save();
                 context.beginPath();
                 context.beginPath();
@@ -1608,9 +1670,17 @@ var BABYLON;
                     return this._connectedControl;
                     return this._connectedControl;
                 },
                 },
                 set: function (value) {
                 set: function (value) {
+                    var _this = this;
                     if (this._connectedControl === value) {
                     if (this._connectedControl === value) {
                         return;
                         return;
                     }
                     }
+                    if (this._connectedControlDirtyObserver && this._connectedControl) {
+                        this._connectedControl.onDirtyObservable.remove(this._connectedControlDirtyObserver);
+                        this._connectedControlDirtyObserver = null;
+                    }
+                    if (value) {
+                        this._connectedControlDirtyObserver = value.onDirtyObservable.add(function () { return _this._markAsDirty(); });
+                    }
                     this._connectedControl = value;
                     this._connectedControl = value;
                     this._markAsDirty();
                     this._markAsDirty();
                 },
                 },
@@ -1648,7 +1718,7 @@ var BABYLON;
             Object.defineProperty(Line.prototype, "x2", {
             Object.defineProperty(Line.prototype, "x2", {
                 get: function () {
                 get: function () {
                     if (this._connectedControl) {
                     if (this._connectedControl) {
-                        return this._connectedControl.centerX;
+                        return this._connectedControl.centerX + this._x2;
                     }
                     }
                     return this._x2;
                     return this._x2;
                 },
                 },
@@ -1665,7 +1735,7 @@ var BABYLON;
             Object.defineProperty(Line.prototype, "y2", {
             Object.defineProperty(Line.prototype, "y2", {
                 get: function () {
                 get: function () {
                     if (this._connectedControl) {
                     if (this._connectedControl) {
-                        return this._connectedControl.centerY;
+                        return this._connectedControl.centerY + this._y2;
                     }
                     }
                     return this._y2;
                     return this._y2;
                 },
                 },
@@ -1710,24 +1780,25 @@ var BABYLON;
             Line.prototype._draw = function (parentMeasure, context) {
             Line.prototype._draw = function (parentMeasure, context) {
                 context.save();
                 context.save();
                 this._applyStates(context);
                 this._applyStates(context);
-                _super.prototype._processMeasures.call(this, parentMeasure, context);
-                context.strokeStyle = this.color;
-                context.lineWidth = this._lineWidth;
-                context.setLineDash(this._dash);
-                context.beginPath();
-                context.moveTo(this._x1, this._y1);
-                context.lineTo(this.x2, this.y2);
-                context.stroke();
+                if (this._processMeasures(parentMeasure, context)) {
+                    context.strokeStyle = this.color;
+                    context.lineWidth = this._lineWidth;
+                    context.setLineDash(this._dash);
+                    context.beginPath();
+                    context.moveTo(this._x1, this._y1);
+                    context.lineTo(this.x2, this.y2);
+                    context.stroke();
+                }
                 context.restore();
                 context.restore();
             };
             };
             Line.prototype._measure = function () {
             Line.prototype._measure = function () {
                 // Width / Height
                 // Width / Height
-                this._currentMeasure.width = Math.abs(this._x1 - this.x2);
-                this._currentMeasure.height = Math.abs(this._y1 - this.y2);
+                this._currentMeasure.width = Math.abs(this._x1 - this.x2) + this._lineWidth;
+                this._currentMeasure.height = Math.abs(this._y1 - this.y2) + this._lineWidth;
             };
             };
             Line.prototype._computeAlignment = function (parentMeasure, context) {
             Line.prototype._computeAlignment = function (parentMeasure, context) {
-                this._currentMeasure.left = Math.min(this._x1, this.x2);
-                this._currentMeasure.top = Math.min(this._y1, this.y2);
+                this._currentMeasure.left = Math.min(this._x1, this.x2) - this._lineWidth / 2;
+                this._currentMeasure.top = Math.min(this._y1, this.y2) - this._lineWidth / 2;
             };
             };
             Line.prototype._moveToProjectedPosition = function (projectedPosition) {
             Line.prototype._moveToProjectedPosition = function (projectedPosition) {
                 this.x1 = projectedPosition.x + this.linkOffsetX;
                 this.x1 = projectedPosition.x + this.linkOffsetX;
@@ -1761,6 +1832,7 @@ var BABYLON;
             function TextBlock(name, text) {
             function TextBlock(name, text) {
                 var _this = _super.call(this, name) || this;
                 var _this = _super.call(this, name) || this;
                 _this.name = name;
                 _this.name = name;
+                _this._text = "";
                 _this._textWrapping = false;
                 _this._textWrapping = false;
                 _this._textHorizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
                 _this._textHorizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
                 _this._textVerticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_CENTER;
                 _this._textVerticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_CENTER;
@@ -1842,9 +1914,10 @@ var BABYLON;
             TextBlock.prototype._draw = function (parentMeasure, context) {
             TextBlock.prototype._draw = function (parentMeasure, context) {
                 context.save();
                 context.save();
                 this._applyStates(context);
                 this._applyStates(context);
-                _super.prototype._processMeasures.call(this, parentMeasure, context);
-                // Render lines
-                this._renderLines(context);
+                if (this._processMeasures(parentMeasure, context)) {
+                    // Render lines
+                    this._renderLines(context);
+                }
                 context.restore();
                 context.restore();
             };
             };
             TextBlock.prototype._additionalProcessing = function (parentMeasure, context) {
             TextBlock.prototype._additionalProcessing = function (parentMeasure, context) {
@@ -1930,16 +2003,26 @@ var BABYLON;
                 _this.name = name;
                 _this.name = name;
                 _this._loaded = false;
                 _this._loaded = false;
                 _this._stretch = Image.STRETCH_FILL;
                 _this._stretch = Image.STRETCH_FILL;
-                _this._domImage = new DOMImage();
-                _this._domImage.onload = function () {
-                    _this._imageWidth = _this._domImage.width;
-                    _this._imageHeight = _this._domImage.height;
-                    _this._loaded = true;
-                    _this._markAsDirty();
-                };
-                _this._domImage.src = url;
+                _this._autoScale = false;
+                _this.source = url;
                 return _this;
                 return _this;
             }
             }
+            Object.defineProperty(Image.prototype, "autoScale", {
+                get: function () {
+                    return this._autoScale;
+                },
+                set: function (value) {
+                    if (this._autoScale === value) {
+                        return;
+                    }
+                    this._autoScale = value;
+                    if (value && this._loaded) {
+                        this.synchronizeSizeWithContent();
+                    }
+                },
+                enumerable: true,
+                configurable: true
+            });
             Object.defineProperty(Image.prototype, "stretch", {
             Object.defineProperty(Image.prototype, "stretch", {
                 get: function () {
                 get: function () {
                     return this._stretch;
                     return this._stretch;
@@ -1954,26 +2037,65 @@ var BABYLON;
                 enumerable: true,
                 enumerable: true,
                 configurable: true
                 configurable: true
             });
             });
+            Object.defineProperty(Image.prototype, "source", {
+                set: function (value) {
+                    var _this = this;
+                    if (this._source === value) {
+                        return;
+                    }
+                    this._loaded = false;
+                    this._source = value;
+                    this._domImage = new DOMImage();
+                    this._domImage.onload = function () {
+                        _this._imageWidth = _this._domImage.width;
+                        _this._imageHeight = _this._domImage.height;
+                        _this._loaded = true;
+                        if (_this._autoScale) {
+                            _this.synchronizeSizeWithContent();
+                        }
+                        _this._markAsDirty();
+                    };
+                    this._domImage.src = value;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Image.prototype.synchronizeSizeWithContent = function () {
+                if (!this._loaded) {
+                    return;
+                }
+                this.width = this._domImage.width + "px";
+                this.height = this._domImage.height + "px";
+            };
             Image.prototype._draw = function (parentMeasure, context) {
             Image.prototype._draw = function (parentMeasure, context) {
                 context.save();
                 context.save();
                 this._applyStates(context);
                 this._applyStates(context);
-                _super.prototype._processMeasures.call(this, parentMeasure, context);
-                if (this._loaded) {
-                    switch (this._stretch) {
-                        case Image.STRETCH_NONE:
-                            context.drawImage(this._domImage, this._currentMeasure.left, this._currentMeasure.top);
-                            break;
-                        case Image.STRETCH_FILL:
-                            context.drawImage(this._domImage, 0, 0, this._imageWidth, this._imageHeight, this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
-                            break;
-                        case Image.STRETCH_UNIFORM:
-                            var hRatio = this._currentMeasure.width / this._imageWidth;
-                            var vRatio = this._currentMeasure.height / this._imageHeight;
-                            var ratio = Math.min(hRatio, vRatio);
-                            var centerX = (this._currentMeasure.width - this._imageWidth * ratio) / 2;
-                            var centerY = (this._currentMeasure.height - this._imageHeight * ratio) / 2;
-                            context.drawImage(this._domImage, 0, 0, this._imageWidth, this._imageHeight, this._currentMeasure.left + centerX, this._currentMeasure.top + centerY, this._imageWidth * ratio, this._imageHeight * ratio);
-                            break;
+                if (this._processMeasures(parentMeasure, context)) {
+                    if (this._loaded) {
+                        switch (this._stretch) {
+                            case Image.STRETCH_NONE:
+                                context.drawImage(this._domImage, this._currentMeasure.left, this._currentMeasure.top);
+                                break;
+                            case Image.STRETCH_FILL:
+                                context.drawImage(this._domImage, 0, 0, this._imageWidth, this._imageHeight, this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+                                break;
+                            case Image.STRETCH_UNIFORM:
+                                var hRatio = this._currentMeasure.width / this._imageWidth;
+                                var vRatio = this._currentMeasure.height / this._imageHeight;
+                                var ratio = Math.min(hRatio, vRatio);
+                                var centerX = (this._currentMeasure.width - this._imageWidth * ratio) / 2;
+                                var centerY = (this._currentMeasure.height - this._imageHeight * ratio) / 2;
+                                context.drawImage(this._domImage, 0, 0, this._imageWidth, this._imageHeight, this._currentMeasure.left + centerX, this._currentMeasure.top + centerY, this._imageWidth * ratio, this._imageHeight * ratio);
+                                break;
+                            case Image.STRETCH_EXTEND:
+                                context.drawImage(this._domImage, this._currentMeasure.left, this._currentMeasure.top);
+                                if (this._autoScale) {
+                                    this.synchronizeSizeWithContent();
+                                }
+                                this._root.width = this.width;
+                                this._root.height = this.height;
+                                break;
+                        }
                     }
                     }
                 }
                 }
                 context.restore();
                 context.restore();
@@ -1999,12 +2121,20 @@ var BABYLON;
                 enumerable: true,
                 enumerable: true,
                 configurable: true
                 configurable: true
             });
             });
+            Object.defineProperty(Image, "STRETCH_EXTEND", {
+                get: function () {
+                    return Image._STRETCH_EXTEND;
+                },
+                enumerable: true,
+                configurable: true
+            });
             return Image;
             return Image;
         }(GUI.Control));
         }(GUI.Control));
         // Static
         // Static
         Image._STRETCH_NONE = 0;
         Image._STRETCH_NONE = 0;
         Image._STRETCH_FILL = 1;
         Image._STRETCH_FILL = 1;
         Image._STRETCH_UNIFORM = 2;
         Image._STRETCH_UNIFORM = 2;
+        Image._STRETCH_EXTEND = 3;
         GUI.Image = Image;
         GUI.Image = Image;
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
@@ -2033,6 +2163,20 @@ var BABYLON;
                 _this.name = name;
                 _this.name = name;
                 _this.thickness = 1;
                 _this.thickness = 1;
                 _this.isPointerBlocker = true;
                 _this.isPointerBlocker = true;
+                _this.pointerEnterAnimation = function () {
+                    _this.alpha -= 0.1;
+                };
+                _this.pointerOutAnimation = function () {
+                    _this.alpha += 0.1;
+                };
+                _this.pointerDownAnimation = function () {
+                    _this.scaleX -= 0.05;
+                    _this.scaleY -= 0.05;
+                };
+                _this.pointerUpAnimation = function () {
+                    _this.scaleX += 0.05;
+                    _this.scaleY += 0.05;
+                };
                 return _this;
                 return _this;
             }
             }
             // While being a container, the button behaves like a control.
             // While being a container, the button behaves like a control.
@@ -2044,21 +2188,27 @@ var BABYLON;
                 return true;
                 return true;
             };
             };
             Button.prototype._onPointerEnter = function () {
             Button.prototype._onPointerEnter = function () {
-                this.alpha -= 0.2;
+                if (this.pointerEnterAnimation) {
+                    this.pointerEnterAnimation();
+                }
                 _super.prototype._onPointerEnter.call(this);
                 _super.prototype._onPointerEnter.call(this);
             };
             };
             Button.prototype._onPointerOut = function () {
             Button.prototype._onPointerOut = function () {
-                this.alpha += 0.2;
+                if (this.pointerOutAnimation) {
+                    this.pointerOutAnimation();
+                }
                 _super.prototype._onPointerOut.call(this);
                 _super.prototype._onPointerOut.call(this);
             };
             };
             Button.prototype._onPointerDown = function () {
             Button.prototype._onPointerDown = function () {
-                this.scaleX -= 0.05;
-                this.scaleY -= 0.05;
+                if (this.pointerDownAnimation) {
+                    this.pointerDownAnimation();
+                }
                 _super.prototype._onPointerDown.call(this);
                 _super.prototype._onPointerDown.call(this);
             };
             };
             Button.prototype._onPointerUp = function () {
             Button.prototype._onPointerUp = function () {
-                this.scaleX += 0.05;
-                this.scaleY += 0.05;
+                if (this.pointerUpAnimation) {
+                    this.pointerUpAnimation();
+                }
                 _super.prototype._onPointerUp.call(this);
                 _super.prototype._onPointerUp.call(this);
             };
             };
             // Statics
             // Statics
@@ -2078,6 +2228,15 @@ var BABYLON;
                 result.addControl(iconImage);
                 result.addControl(iconImage);
                 return result;
                 return result;
             };
             };
+            Button.CreateImageOnlyButton = function (name, imageUrl) {
+                var result = new Button(name);
+                // Adding image
+                var iconImage = new BABYLON.GUI.Image(name + "_icon", imageUrl);
+                iconImage.stretch = BABYLON.GUI.Image.STRETCH_FILL;
+                iconImage.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+                result.addControl(iconImage);
+                return result;
+            };
             Button.CreateSimpleButton = function (name, text) {
             Button.CreateSimpleButton = function (name, text) {
                 var result = new Button(name);
                 var result = new Button(name);
                 // Adding text
                 // Adding text

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


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

@@ -6,6 +6,7 @@
  - WebGL2 context support. WebGL2 is now used instead of WebGL 1 when available. [More info here](http://doc.babylonjs.com/overviews/webgl2) ([deltakosh](https://github.com/deltakosh))
  - WebGL2 context support. WebGL2 is now used instead of WebGL 1 when available. [More info here](http://doc.babylonjs.com/overviews/webgl2) ([deltakosh](https://github.com/deltakosh))
  - Complete WebVR 1.1 support including controllers for HTC Vive and Occulus. [More info here](http://doc.babylonjs.com/overviews/webvr_camera) ([raanan](https://github.com/raananw))
  - Complete WebVR 1.1 support including controllers for HTC Vive and Occulus. [More info here](http://doc.babylonjs.com/overviews/webvr_camera) ([raanan](https://github.com/raananw))
  - Support for Morph Targets. [More info here](http://doc.babylonjs.com/tutorials/how_to_use_morphtargets) ([deltakosh](https://github.com/deltakosh))
  - Support for Morph Targets. [More info here](http://doc.babylonjs.com/tutorials/how_to_use_morphtargets) ([deltakosh](https://github.com/deltakosh))
+ - New Babylon.GUI to create user interface (comaptible with WebVR). [More info here](http://doc.babylonjs.com/overviews/Gui) ([deltakosh](https://github.com/deltakosh))
  - Added support for Exponential Shadow maps to replace Variance Shadow maps. [more info here](http://www.babylonjs-playground.com/debug.html#1CXNXC#3) - [Demo](http://www.babylonjs.com/Demos/AdvancedShadows/) - [Demo](http://www.babylonjs-playground.com/#1CXNXC#4) ([deltakosh](https://github.com/deltakosh))
  - Added support for Exponential Shadow maps to replace Variance Shadow maps. [more info here](http://www.babylonjs-playground.com/debug.html#1CXNXC#3) - [Demo](http://www.babylonjs.com/Demos/AdvancedShadows/) - [Demo](http://www.babylonjs-playground.com/#1CXNXC#4) ([deltakosh](https://github.com/deltakosh))
  - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
  - Support for [Vertex Array Objects](https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt) ([deltakosh](https://github.com/deltakosh))
  - Support for [Uniform Buffer Objects](https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.16) ([CraigFeldspar](https://github.com/CraigFeldspar))
  - Support for [Uniform Buffer Objects](https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.16) ([CraigFeldspar](https://github.com/CraigFeldspar))
@@ -19,8 +20,9 @@
  - All deprecated functions and properties were removed ([deltakosh](https://github.com/deltakosh))
  - All deprecated functions and properties were removed ([deltakosh](https://github.com/deltakosh))
  - New build system based on workloads. [More info here](http://doc.babylonjs.com/generals/how_to_start#custom-builds) ([deltakosh](https://github.com/deltakosh))
  - New build system based on workloads. [More info here](http://doc.babylonjs.com/generals/how_to_start#custom-builds) ([deltakosh](https://github.com/deltakosh))
  - New `Cell Shading` material added into `Materials Library` [Demo](http://www.babylonjs.com/Demos/CellShading/) - ([Julien Moreau-Mathis](https://github.com/julien-moreau))
  - New `Cell Shading` material added into `Materials Library` [Demo](http://www.babylonjs.com/Demos/CellShading/) - ([Julien Moreau-Mathis](https://github.com/julien-moreau))
-
+ 
 ### Updates
 ### Updates
+- Added `ArcRotateCamera.panningInertia` to decouple inertia from panning inertia ([deltakosh](https://github.com/deltakosh))
 - Added `FIXED_EQUIRECTANGULAR_MIRRORED_MODE` mode for reflection texture. [Demo here](http://www.babylonjs-playground.com/#11GAIH#22) ([deltakosh](https://github.com/deltakosh))
 - Added `FIXED_EQUIRECTANGULAR_MIRRORED_MODE` mode for reflection texture. [Demo here](http://www.babylonjs-playground.com/#11GAIH#22) ([deltakosh](https://github.com/deltakosh))
 - Introduced `boundingBox.centerWorld` and `boundingBox.extendSizeWorld` ([deltakosh](https://github.com/deltakosh))
 - Introduced `boundingBox.centerWorld` and `boundingBox.extendSizeWorld` ([deltakosh](https://github.com/deltakosh))
 - Improved FXAA post-process ([deltakosh](https://github.com/deltakosh))
 - Improved FXAA post-process ([deltakosh](https://github.com/deltakosh))

+ 3 - 14
gui/readme.md

@@ -1,16 +1,5 @@
 # Babylon.js GUI library
 # Babylon.js GUI library
+The Babylon.js GUI library is an extension you can use to generate interactive user interface.
+It is build on top of the DynamicTexture.
 
 
-The Babylon.js GUI library is an extension you can use to generate interactive user interface on top of the DynamicTexture.
-
-## How to use it
-
-- unit mode (Default to percentage)
-
-## Features
-* Flixible containers and controls
-* Horizontal and vertical alignment
-* Proportional or pixel constant size modes
-* Text wrapping
-
-==> ideas
-* pick on mesh
+Documentation: http://doc.babylonjs.com/overviews/gui

+ 29 - 17
gui/src/advancedDynamicTexture.ts

@@ -6,14 +6,16 @@ module BABYLON.GUI {
         private _renderObserver: Observer<Camera>;
         private _renderObserver: Observer<Camera>;
         private _resizeObserver: Observer<Engine>;
         private _resizeObserver: Observer<Engine>;
         private _pointerMoveObserver: Observer<PointerInfoPre>;
         private _pointerMoveObserver: Observer<PointerInfoPre>;
+        private _pointerObserver: Observer<PointerInfo>;
         private _background: string;
         private _background: string;
         public _rootContainer = new Container("root");
         public _rootContainer = new Container("root");
         public _lastControlOver: Control;
         public _lastControlOver: Control;
         public _lastControlDown: Control;
         public _lastControlDown: Control;
         public _shouldBlockPointer: boolean;
         public _shouldBlockPointer: boolean;
-        public _toDispose: IDisposable;
+        public _layerToDispose: Layer;
         public _linkedControls = new Array<Control>();
         public _linkedControls = new Array<Control>();
         private _isFullscreen = false;
         private _isFullscreen = false;
+        private _fullscreenViewport = new Viewport(0, 0, 1, 1);
 
 
         public get background(): string {
         public get background(): string {
             return this._background;
             return this._background;
@@ -69,9 +71,14 @@ module BABYLON.GUI {
                 this.getScene().onPrePointerObservable.remove(this._pointerMoveObserver);
                 this.getScene().onPrePointerObservable.remove(this._pointerMoveObserver);
             }
             }
 
 
-            if (this._toDispose) {
-                this._toDispose.dispose();
-                this._toDispose = null;
+            if (this._pointerObserver) {
+                this.getScene().onPointerObservable.remove(this._pointerObserver);
+            }
+
+            if (this._layerToDispose) {
+                this._layerToDispose.texture = null;
+                this._layerToDispose.dispose();
+                this._layerToDispose = null;
             }
             }
 
 
             super.dispose();
             super.dispose();
@@ -94,8 +101,7 @@ module BABYLON.GUI {
             if (this._isFullscreen && this._linkedControls.length) {
             if (this._isFullscreen && this._linkedControls.length) {
                 var scene = this.getScene();
                 var scene = this.getScene();
                 var engine = scene.getEngine();
                 var engine = scene.getEngine();
-                var viewport = camera.viewport;
-                var globalViewport = viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
+                var globalViewport = this._fullscreenViewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
 
 
                 for (var control of this._linkedControls) {
                 for (var control of this._linkedControls) {
                     var mesh = control._linkedMesh;
                     var mesh = control._linkedMesh;
@@ -166,6 +172,21 @@ module BABYLON.GUI {
             });
             });
         }
         }
 
 
+        public attachToMesh(mesh: AbstractMesh): void {
+            var scene = this.getScene();
+            this._pointerObserver = scene.onPointerObservable.add((pi, state) => {
+                if (pi.type !== BABYLON.PointerEventTypes.POINTERUP && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
+                    return;
+                }
+
+                if (pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
+                    var uv = pi.pickInfo.getTextureCoordinates();
+                    var size = this.getSize();
+                    this._doPicking(uv.x * size.width, (1.0 - uv.y) * size.height, pi.type);
+                }
+            });
+        }
+
         // Statics
         // Statics
         public static CreateForMesh(mesh: AbstractMesh, width = 1024, height = 1024): AdvancedDynamicTexture {
         public static CreateForMesh(mesh: AbstractMesh, width = 1024, height = 1024): AdvancedDynamicTexture {
             var result = new AdvancedDynamicTexture(mesh.name + " AdvancedDynamicTexture", width, height, mesh.getScene(), true, Texture.TRILINEAR_SAMPLINGMODE);
             var result = new AdvancedDynamicTexture(mesh.name + " AdvancedDynamicTexture", width, height, mesh.getScene(), true, Texture.TRILINEAR_SAMPLINGMODE);
@@ -179,16 +200,7 @@ module BABYLON.GUI {
 
 
             mesh.material = material;
             mesh.material = material;
 
 
-            mesh.getScene().onPointerObservable.add(function(pi, state) {
-                if (pi.type !== BABYLON.PointerEventTypes.POINTERUP && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
-                    return;
-                }
-
-                if (pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
-                    var uv = pi.pickInfo.getTextureCoordinates();
-                    result._doPicking(uv.x * width, (1.0 - uv.y) * height, pi.type);
-                }
-            });
+            result.attachToMesh(mesh);
 
 
             return result;
             return result;
         }
         }
@@ -200,7 +212,7 @@ module BABYLON.GUI {
             var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
             var layer = new BABYLON.Layer(name + "_layer", null, scene, !foreground);
             layer.texture = result;
             layer.texture = result;
 
 
-            result._toDispose = layer;
+            result._layerToDispose = layer;
             result._isFullscreen = true;
             result._isFullscreen = true;
 
 
             // Attach
             // Attach

+ 48 - 7
gui/src/controls/button.ts

@@ -1,11 +1,34 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 
 module BABYLON.GUI {
 module BABYLON.GUI {
-    export class Button extends Rectangle {      
+    export class Button extends Rectangle {    
+        public pointerEnterAnimation: () => void;
+        public pointerOutAnimation: () => void;
+        public pointerDownAnimation: () => void;
+        public pointerUpAnimation: () => void;
+
         constructor(public name: string) {
         constructor(public name: string) {
             super(name);
             super(name);
             this.thickness = 1;
             this.thickness = 1;
             this.isPointerBlocker = true;
             this.isPointerBlocker = true;
+
+            this.pointerEnterAnimation = () => {
+                this.alpha -= 0.1;
+            }
+
+            this.pointerOutAnimation = () => {
+                this.alpha += 0.1;
+            }    
+
+            this.pointerDownAnimation = () => {
+                this.scaleX -= 0.05;
+                this.scaleY -= 0.05;
+            }
+
+            this.pointerUpAnimation = () => {
+                this.scaleX += 0.05;
+                this.scaleY += 0.05;
+            }                      
         }
         }
 
 
         // While being a container, the button behaves like a control.
         // While being a container, the button behaves like a control.
@@ -20,25 +43,31 @@ module BABYLON.GUI {
         }
         }
 
 
         protected _onPointerEnter(): void {
         protected _onPointerEnter(): void {
-            this.alpha -= 0.2;
+            if (this.pointerEnterAnimation) {
+                this.pointerEnterAnimation();
+            }
             super._onPointerEnter();
             super._onPointerEnter();
         }
         }
 
 
         protected _onPointerOut(): void {
         protected _onPointerOut(): void {
-            this.alpha += 0.2;
+            if (this.pointerOutAnimation) {
+                this.pointerOutAnimation();
+            }
             super._onPointerOut();
             super._onPointerOut();
         }
         }
 
 
         protected _onPointerDown(): void {
         protected _onPointerDown(): void {
-            this.scaleX -= 0.05;
-            this.scaleY -= 0.05;
+            if (this.pointerDownAnimation) {
+                this.pointerDownAnimation();
+            }
 
 
             super._onPointerDown();
             super._onPointerDown();
         }
         }
 
 
         protected _onPointerUp (): void {
         protected _onPointerUp (): void {
-            this.scaleX += 0.05;
-            this.scaleY += 0.05;
+            if (this.pointerUpAnimation) {
+                this.pointerUpAnimation();
+            }
 
 
             super._onPointerUp();
             super._onPointerUp();
         }        
         }        
@@ -64,6 +93,18 @@ module BABYLON.GUI {
             return result;
             return result;
         }
         }
 
 
+        public static CreateImageOnlyButton(name: string, imageUrl: string): Button {
+            var result = new Button(name);
+
+            // Adding image
+            var iconImage = new BABYLON.GUI.Image(name + "_icon", imageUrl);
+            iconImage.stretch = BABYLON.GUI.Image.STRETCH_FILL;
+            iconImage.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+            result.addControl(iconImage);            
+
+            return result;
+        }
+
         public static CreateSimpleButton(name: string, text: string): Button {
         public static CreateSimpleButton(name: string, text: string): Button {
             var result = new Button(name);
             var result = new Button(name);
 
 

+ 30 - 8
gui/src/controls/container.ts

@@ -3,7 +3,25 @@
 module BABYLON.GUI {
 module BABYLON.GUI {
     export class Container extends Control {
     export class Container extends Control {
         protected _children = new Array<Control>();
         protected _children = new Array<Control>();
-        protected _measureForChildren = Measure.Empty();     
+        protected _measureForChildren = Measure.Empty();  
+        protected _background: string;   
+
+        public get background(): string {
+            return this._background;
+        }
+
+        public set background(value: string) {
+            if (this._background === value) {
+                return;
+            }
+
+            this._background = value;
+            this._markAsDirty();
+        }  
+
+        public get children(): Control[] {
+            return this._children;
+        }        
 
 
         constructor(public name: string) {
         constructor(public name: string) {
             super(name);
             super(name);
@@ -62,7 +80,10 @@ module BABYLON.GUI {
         }
         }
 
 
         protected _localDraw(context: CanvasRenderingContext2D): void {
         protected _localDraw(context: CanvasRenderingContext2D): void {
-            // Implemented by child to be injected inside main draw
+            if (this._background) {
+                context.fillStyle = this._background;
+                context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+            }
         }
         }
 
 
         public _link(root: Container, host: AdvancedDynamicTexture): void {
         public _link(root: Container, host: AdvancedDynamicTexture): void {
@@ -73,17 +94,18 @@ module BABYLON.GUI {
             }
             }
         }
         }
 
 
-        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {      
             context.save();
             context.save();
-            super._processMeasures(parentMeasure, context);
            
            
             this._applyStates(context);
             this._applyStates(context);
 
 
-            this._localDraw(context);
+            if (this._processMeasures(parentMeasure, context)) {
+                this._localDraw(context);
 
 
-            this._clipForChildren(context);
-            for (var child of this._children) {
-                child._draw(this._measureForChildren, context);
+                this._clipForChildren(context);
+                for (var child of this._children) {
+                    child._draw(this._measureForChildren, context);
+                }
             }
             }
             context.restore();
             context.restore();
         }
         }

+ 25 - 6
gui/src/controls/control.ts

@@ -374,6 +374,7 @@ module BABYLON.GUI {
 
 
         public _markMatrixAsDirty(): void {
         public _markMatrixAsDirty(): void {
             this._isMatrixDirty = true;
             this._isMatrixDirty = true;
+            this._markAsDirty();
         }
         }
 
 
         protected _markAsDirty(): void {            
         protected _markAsDirty(): void {            
@@ -395,18 +396,18 @@ module BABYLON.GUI {
                 return;
                 return;
             }
             }
 
 
-            // preTranslate
+            // postTranslate
             var offsetX = this._currentMeasure.width * this._transformCenterX + this._currentMeasure.left;
             var offsetX = this._currentMeasure.width * this._transformCenterX + this._currentMeasure.left;
             var offsetY = this._currentMeasure.height * this._transformCenterY + this._currentMeasure.top;
             var offsetY = this._currentMeasure.height * this._transformCenterY + this._currentMeasure.top;
             context.translate(offsetX, offsetY);
             context.translate(offsetX, offsetY);
 
 
-            // scale
-            context.scale(this._scaleX, this._scaleY);
-
             // rotate
             // rotate
             context.rotate(this._rotation);
             context.rotate(this._rotation);
 
 
-            // postTranslate
+            // scale
+            context.scale(this._scaleX, this._scaleY);
+
+            // preTranslate
             context.translate(-offsetX, -offsetY);    
             context.translate(-offsetX, -offsetY);    
 
 
             // Need to update matrices?
             // Need to update matrices?
@@ -433,7 +434,7 @@ module BABYLON.GUI {
             context.globalAlpha = this._alpha;
             context.globalAlpha = this._alpha;
         }
         }
 
 
-        protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D) {     
+        protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D): boolean {     
             if (this._isDirty || !this._cachedParentMeasure.isEqualsTo(parentMeasure)) {
             if (this._isDirty || !this._cachedParentMeasure.isEqualsTo(parentMeasure)) {
                 this._isDirty = false;
                 this._isDirty = false;
                 this._currentMeasure.copyFrom(parentMeasure);
                 this._currentMeasure.copyFrom(parentMeasure);
@@ -457,12 +458,30 @@ module BABYLON.GUI {
                 }                
                 }                
             }     
             }     
 
 
+            if (this._currentMeasure.left > parentMeasure.left + parentMeasure.width) {
+                return false;
+            }
+
+            if (this._currentMeasure.left + this._currentMeasure.width < parentMeasure.left) {
+                return false;
+            }
+
+            if (this._currentMeasure.top > parentMeasure.top + parentMeasure.height) {
+                return false;
+            }
+
+            if (this._currentMeasure.top + this._currentMeasure.height < parentMeasure.top) {
+                return false;
+            }
+
             // Transform
             // Transform
             this._transform(context); 
             this._transform(context); 
                         
                         
             // Clip
             // Clip
             this._clip(context);
             this._clip(context);
             context.clip();
             context.clip();
+
+            return true;
         }
         }
 
 
         protected _clip( context: CanvasRenderingContext2D) {
         protected _clip( context: CanvasRenderingContext2D) {

+ 2 - 16
gui/src/controls/ellipse.ts

@@ -2,8 +2,7 @@
 
 
 module BABYLON.GUI {
 module BABYLON.GUI {
     export class Ellipse extends Container {
     export class Ellipse extends Container {
-        private _thickness = 1;
-        private _background: string;          
+        private _thickness = 1;       
         
         
         public get thickness(): number {
         public get thickness(): number {
             return this._thickness;
             return this._thickness;
@@ -16,20 +15,7 @@ module BABYLON.GUI {
 
 
             this._thickness = value;
             this._thickness = value;
             this._markAsDirty();
             this._markAsDirty();
-        }   
-       
-        public get background(): string {
-            return this._background;
-        }
-
-        public set background(value: string) {
-            if (this._background === value) {
-                return;
-            }
-
-            this._background = value;
-            this._markAsDirty();
-        }           
+        }                
      
      
         constructor(public name: string) {
         constructor(public name: string) {
             super(name);
             super(name);

+ 82 - 26
gui/src/controls/image.ts

@@ -9,6 +9,24 @@ module BABYLON.GUI {
         private _imageHeight: number;
         private _imageHeight: number;
         private _loaded = false;
         private _loaded = false;
         private _stretch = Image.STRETCH_FILL;
         private _stretch = Image.STRETCH_FILL;
+        private _source: string;
+        private _autoScale = false;
+
+        public get autoScale(): boolean {
+            return this._autoScale;
+        }
+
+        public set autoScale(value: boolean) {
+            if (this._autoScale === value) {
+                return;
+            }
+
+            this._autoScale = value;
+
+            if (value && this._loaded) {
+                this.synchronizeSizeWithContent();
+            }
+        }
 
 
         public get stretch(): number {
         public get stretch(): number {
             return this._stretch;
             return this._stretch;
@@ -24,46 +42,79 @@ module BABYLON.GUI {
             this._markAsDirty();
             this._markAsDirty();
         }
         }
 
 
-        constructor(public name: string, url: string) {
-            super(name);
+        public set source(value: string) {
+            if (this._source === value) {
+                return;
+            }
 
 
+            this._loaded = false;
+            this._source = value;
+            
             this._domImage = new DOMImage();
             this._domImage = new DOMImage();
             
             
             this._domImage.onload = () => {
             this._domImage.onload = () => {
                 this._imageWidth = this._domImage.width;
                 this._imageWidth = this._domImage.width;
                 this._imageHeight = this._domImage.height;
                 this._imageHeight = this._domImage.height;
                 this._loaded = true;
                 this._loaded = true;
+
+                if (this._autoScale) {
+                    this.synchronizeSizeWithContent();
+                }
+
                 this._markAsDirty();
                 this._markAsDirty();
             }
             }
             
             
-            this._domImage.src = url;
+            this._domImage.src = value;
+        }
+
+        constructor(public name: string, url: string) {
+            super(name);
+
+            this.source = url;
+        }
+
+        public synchronizeSizeWithContent() {
+            if (!this._loaded) {
+                return;
+            }
+
+            this.width = this._domImage.width + "px";
+            this.height = this._domImage.height + "px";
         }
         }
 
 
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
             context.save();
 
 
             this._applyStates(context);
             this._applyStates(context);
-            super._processMeasures(parentMeasure, context);
-
-            if (this._loaded) {
-                switch (this._stretch) {
-                    case Image.STRETCH_NONE:
-                        context.drawImage(this._domImage, this._currentMeasure.left, this._currentMeasure.top);
-                        break;
-                    case Image.STRETCH_FILL:
-                        context.drawImage(this._domImage, 0, 0, this._imageWidth, this._imageHeight, 
-                                                          this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
-                        break;
-                    case Image.STRETCH_UNIFORM:
-                        var hRatio = this._currentMeasure.width  / this._imageWidth;
-                        var vRatio =  this._currentMeasure.height / this._imageHeight;
-                        var ratio = Math.min(hRatio, vRatio);
-                        var centerX = (this._currentMeasure.width - this._imageWidth * ratio) / 2;
-                        var centerY = (this._currentMeasure.height - this._imageHeight * ratio) / 2; 
-
-                        context.drawImage(this._domImage, 0, 0, this._imageWidth, this._imageHeight,
-                                                          this._currentMeasure.left + centerX, this._currentMeasure.top + centerY, this._imageWidth * ratio, this._imageHeight * ratio);
-                        break;
+            if (this._processMeasures(parentMeasure, context)) {
+                if (this._loaded) {
+                    switch (this._stretch) {
+                        case Image.STRETCH_NONE:
+                            context.drawImage(this._domImage, this._currentMeasure.left, this._currentMeasure.top);
+                            break;
+                        case Image.STRETCH_FILL:
+                            context.drawImage(this._domImage, 0, 0, this._imageWidth, this._imageHeight, 
+                                                            this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
+                            break;
+                        case Image.STRETCH_UNIFORM:
+                            var hRatio = this._currentMeasure.width  / this._imageWidth;
+                            var vRatio =  this._currentMeasure.height / this._imageHeight;
+                            var ratio = Math.min(hRatio, vRatio);
+                            var centerX = (this._currentMeasure.width - this._imageWidth * ratio) / 2;
+                            var centerY = (this._currentMeasure.height - this._imageHeight * ratio) / 2; 
+
+                            context.drawImage(this._domImage, 0, 0, this._imageWidth, this._imageHeight,
+                                                            this._currentMeasure.left + centerX, this._currentMeasure.top + centerY, this._imageWidth * ratio, this._imageHeight * ratio);
+                            break;
+                        case Image.STRETCH_EXTEND:
+                            context.drawImage(this._domImage, this._currentMeasure.left, this._currentMeasure.top);
+                            if (this._autoScale) {
+                                this.synchronizeSizeWithContent();
+                            } 
+                            this._root.width = this.width;
+                            this._root.height = this.height;
+                            break;
+                    }
                 }
                 }
             }
             }
             context.restore();
             context.restore();
@@ -73,6 +124,7 @@ module BABYLON.GUI {
         private static _STRETCH_NONE = 0;
         private static _STRETCH_NONE = 0;
         private static _STRETCH_FILL = 1;
         private static _STRETCH_FILL = 1;
         private static _STRETCH_UNIFORM = 2;
         private static _STRETCH_UNIFORM = 2;
+        private static _STRETCH_EXTEND = 3;
 
 
         public static get STRETCH_NONE(): number {
         public static get STRETCH_NONE(): number {
             return Image._STRETCH_NONE;
             return Image._STRETCH_NONE;
@@ -84,6 +136,10 @@ module BABYLON.GUI {
 
 
         public static get STRETCH_UNIFORM(): number {
         public static get STRETCH_UNIFORM(): number {
             return Image._STRETCH_UNIFORM;
             return Image._STRETCH_UNIFORM;
-        }              
+        }      
+
+        public static get STRETCH_EXTEND(): number {
+            return Image._STRETCH_EXTEND;
+        }                 
     }    
     }    
-}
+}

+ 25 - 15
gui/src/controls/line.ts

@@ -12,6 +12,7 @@ module BABYLON.GUI {
         private _y2 = 0;
         private _y2 = 0;
         private _dash = new Array<number>();
         private _dash = new Array<number>();
         private _connectedControl: Control;
         private _connectedControl: Control;
+        private _connectedControlDirtyObserver: Observer<Control>;
 
 
         public get dash(): Array<number> {
         public get dash(): Array<number> {
             return this._dash;
             return this._dash;
@@ -35,6 +36,15 @@ module BABYLON.GUI {
                 return;
                 return;
             }
             }
 
 
+            if (this._connectedControlDirtyObserver && this._connectedControl) {
+                this._connectedControl.onDirtyObservable.remove(this._connectedControlDirtyObserver);
+                this._connectedControlDirtyObserver = null;
+            }
+
+            if (value) {
+                this._connectedControlDirtyObserver = value.onDirtyObservable.add(() => this._markAsDirty());
+            }            
+
             this._connectedControl = value;
             this._connectedControl = value;
             this._markAsDirty();
             this._markAsDirty();
         }              
         }              
@@ -67,7 +77,7 @@ module BABYLON.GUI {
 
 
         public get x2(): number {
         public get x2(): number {
             if (this._connectedControl) {
             if (this._connectedControl) {
-                return this._connectedControl.centerX;
+                return this._connectedControl.centerX + this._x2;
             }
             }
             return this._x2;
             return this._x2;
         }
         }
@@ -83,7 +93,7 @@ module BABYLON.GUI {
 
 
         public get y2(): number {
         public get y2(): number {
             if (this._connectedControl) {
             if (this._connectedControl) {
-                return this._connectedControl.centerY;
+                return this._connectedControl.centerY + this._y2;
             }
             }
             return this._y2;
             return this._y2;
         }
         }
@@ -130,30 +140,30 @@ module BABYLON.GUI {
             context.save();
             context.save();
 
 
             this._applyStates(context);
             this._applyStates(context);
-            super._processMeasures(parentMeasure, context);
+            if (this._processMeasures(parentMeasure, context)) {
+                context.strokeStyle = this.color;
+                context.lineWidth = this._lineWidth;
+                context.setLineDash(this._dash);
 
 
-            context.strokeStyle = this.color;
-            context.lineWidth = this._lineWidth;
-            context.setLineDash(this._dash);
+                context.beginPath();
+                context.moveTo(this._x1, this._y1);
+                context.lineTo(this.x2, this.y2);
 
 
-            context.beginPath();
-            context.moveTo(this._x1, this._y1);
-            context.lineTo(this.x2, this.y2);
-
-            context.stroke();
+                context.stroke();
+            }
 
 
             context.restore();
             context.restore();
         }
         }
 
 
         public _measure(): void {  
         public _measure(): void {  
             // Width / Height
             // Width / Height
-            this._currentMeasure.width = Math.abs(this._x1 - this.x2);
-            this._currentMeasure.height = Math.abs(this._y1 - this.y2);
+            this._currentMeasure.width = Math.abs(this._x1 - this.x2) + this._lineWidth;
+            this._currentMeasure.height = Math.abs(this._y1 - this.y2) + this._lineWidth;
         }
         }
 
 
         protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {          
         protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {          
-            this._currentMeasure.left = Math.min(this._x1, this.x2);
-            this._currentMeasure.top = Math.min(this._y1, this.y2);            
+            this._currentMeasure.left = Math.min(this._x1, this.x2) - this._lineWidth / 2;
+            this._currentMeasure.top = Math.min(this._y1, this.y2) - this._lineWidth / 2;            
         }   
         }   
 
 
         public _moveToProjectedPosition(projectedPosition: Vector3): void {
         public _moveToProjectedPosition(projectedPosition: Vector3): void {

+ 0 - 1
gui/src/controls/rectangle.ts

@@ -3,7 +3,6 @@
 module BABYLON.GUI {
 module BABYLON.GUI {
     export class Rectangle extends Container {
     export class Rectangle extends Container {
         private _thickness = 1;
         private _thickness = 1;
-        private _background: string;
         private _cornerRadius = 0;
         private _cornerRadius = 0;
         
         
         public get thickness(): number {
         public get thickness(): number {

+ 31 - 5
gui/src/controls/stackPanel.ts

@@ -2,22 +2,48 @@
 
 
 module BABYLON.GUI {
 module BABYLON.GUI {
     export class StackPanel extends Container {
     export class StackPanel extends Container {
+        private _isVertical = true;
+
+        public get isVertical(): boolean {
+            return this._isVertical;
+        }
+
+        public set isVertical(value: boolean) {
+            if (this._isVertical === value) {
+                return;
+            }
+
+            this._isVertical = value;
+            this._markAsDirty();
+        }           
     
     
         constructor(public name: string) {
         constructor(public name: string) {
             super(name);
             super(name);
         }
         }
 
 
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
-            var top = 0;
+            var stack = 0;
             for (var child of this._children) {
             for (var child of this._children) {
                 child._currentMeasure.copyFrom(parentMeasure);
                 child._currentMeasure.copyFrom(parentMeasure);
                 child._measure();
                 child._measure();
-                child.top = top + "px";
-                top += child._currentMeasure.height;
-                child.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+
+                if (this._isVertical) {
+                    child.top = stack + "px";
+                    stack += child._currentMeasure.height;
+                    child.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+                } else {
+                    child.left = stack + "px";
+                    stack += child._currentMeasure.width;
+                    child.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+
+                }
             }
             }
 
 
-            this.height = top + "px";
+            if (this._isVertical) {
+                this.height = stack + "px";
+            } else {
+                this.width = stack + "px";
+            }
 
 
             super._additionalProcessing(parentMeasure, context);
             super._additionalProcessing(parentMeasure, context);
         }    
         }    

+ 5 - 5
gui/src/controls/textBlock.ts

@@ -2,7 +2,7 @@
 
 
 module BABYLON.GUI {
 module BABYLON.GUI {
     export class TextBlock extends Control {
     export class TextBlock extends Control {
-        private _text: string;
+        private _text = "";
         private _textY: number;
         private _textY: number;
         private _textWrapping = false;
         private _textWrapping = false;
         private _textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
         private _textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
@@ -89,11 +89,11 @@ module BABYLON.GUI {
             context.save();
             context.save();
 
 
             this._applyStates(context);
             this._applyStates(context);
-            super._processMeasures(parentMeasure, context);
-            
-            // Render lines
-            this._renderLines(context);
 
 
+            if (this._processMeasures(parentMeasure, context)) {            
+                // Render lines
+                this._renderLines(context);
+            }
             context.restore();
             context.restore();
         }
         }
 
 

+ 2 - 2
gui/src/valueAndUnit.ts

@@ -16,9 +16,9 @@ module BABYLON.GUI {
         public toString(): string {
         public toString(): string {
             switch (this.unit) {
             switch (this.unit) {
                 case ValueAndUnit.UNITMODE_PERCENTAGE:
                 case ValueAndUnit.UNITMODE_PERCENTAGE:
-                    return this.unit + "%";
+                    return this.value + "%";
                 case ValueAndUnit.UNITMODE_PIXEL:
                 case ValueAndUnit.UNITMODE_PIXEL:
-                    return this.unit + "px";
+                    return this.value + "px";
             }
             }
 
 
             return this.unit.toString();
             return this.unit.toString();

+ 5 - 2
src/Cameras/babylon.arcRotateCamera.ts

@@ -56,6 +56,9 @@ module BABYLON {
         @serialize()
         @serialize()
         public inertialPanningY: number = 0;
         public inertialPanningY: number = 0;
 
 
+        @serialize()
+        public panningInertia = 0.9;
+
         //-- begin properties for backward compatibility for inputs
         //-- begin properties for backward compatibility for inputs
         public get angularSensibilityX() {
         public get angularSensibilityX() {
             var pointers = <ArcRotateCameraPointersInput>this.inputs.attached["pointers"];
             var pointers = <ArcRotateCameraPointersInput>this.inputs.attached["pointers"];
@@ -343,8 +346,8 @@ module BABYLON {
                     this._target.addInPlace(this._transformedDirection);
                     this._target.addInPlace(this._transformedDirection);
                 }
                 }
 
 
-                this.inertialPanningX *= this.inertia;
-                this.inertialPanningY *= this.inertia;
+                this.inertialPanningX *= this.panningInertia;
+                this.inertialPanningY *= this.panningInertia;
 
 
                 if (Math.abs(this.inertialPanningX) < this.speed * Epsilon)
                 if (Math.abs(this.inertialPanningX) < this.speed * Epsilon)
                     this.inertialPanningX = 0;
                     this.inertialPanningX = 0;

+ 25 - 17
src/Materials/Textures/babylon.videoTexture.ts

@@ -4,8 +4,8 @@
 
 
         private _autoLaunch = true;
         private _autoLaunch = true;
         private _lastUpdate: number;
         private _lastUpdate: number;
-        private _generateMipMaps: boolean
-
+        private _generateMipMaps: boolean
+        private _setTextureReady: () => void;
         /**
         /**
          * Creates a video texture.
          * Creates a video texture.
          * Sample : https://doc.babylonjs.com/tutorials/01._Advanced_Texturing
          * Sample : https://doc.babylonjs.com/tutorials/01._Advanced_Texturing
@@ -58,17 +58,20 @@
 
 
             this._lastUpdate = Tools.Now;
             this._lastUpdate = Tools.Now;
         }
         }
-
-        private _createTexture(): void {
+
+        private __setTextureReady(): void {
+            this._texture.isReady = true;
+        }
+
+        private _createTexture(): void {
             this._texture = this.getScene().getEngine().createDynamicTexture(this.video.videoWidth, this.video.videoHeight, this._generateMipMaps, this._samplingMode);
             this._texture = this.getScene().getEngine().createDynamicTexture(this.video.videoWidth, this.video.videoHeight, this._generateMipMaps, this._samplingMode);
 
 
             if (this._autoLaunch) {
             if (this._autoLaunch) {
                 this._autoLaunch = false;
                 this._autoLaunch = false;
                 this.video.play();
                 this.video.play();
             }
             }
-            this.video.addEventListener("playing", () => {
-                this._texture.isReady = true;
-            });
+            this._setTextureReady = this.__setTextureReady.bind(this);
+            this.video.addEventListener("playing", this._setTextureReady);
         }
         }
 
 
         public update(): boolean {
         public update(): boolean {
@@ -81,20 +84,25 @@
             this._lastUpdate = now;
             this._lastUpdate = now;
             this.getScene().getEngine().updateVideoTexture(this._texture, this.video, this._invertY);
             this.getScene().getEngine().updateVideoTexture(this._texture, this.video, this._invertY);
             return true;
             return true;
+        }
+
+        public dispose(): void {
+            super.dispose();
+            this.video.removeEventListener("playing", this._setTextureReady);
         }
         }
 
 
-        public static CreateFromWebCam(scene: Scene, onReady: (videoTexture: VideoTexture) => void, constraints: { 
-                minWidth: number, 
-                maxWidth: number, 
-                minHeight: number, 
+        public static CreateFromWebCam(scene: Scene, onReady: (videoTexture: VideoTexture) => void, constraints: {
+                minWidth: number,
+                maxWidth: number,
+                minHeight: number,
                 maxHeight: number,
                 maxHeight: number,
                 deviceId: string
                 deviceId: string
             }): void {
             }): void {
             var video = document.createElement("video");
             var video = document.createElement("video");
             var constraintsDeviceId;
             var constraintsDeviceId;
             if (constraints && constraints.deviceId){
             if (constraints && constraints.deviceId){
-                constraintsDeviceId = { 
-                    exact: constraints.deviceId                     
+                constraintsDeviceId = {
+                    exact: constraints.deviceId
                 }
                 }
             }
             }
 
 
@@ -102,7 +110,7 @@
 		    window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
 		    window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
 
 
 		    if (navigator.getUserMedia) {
 		    if (navigator.getUserMedia) {
-			    navigator.getUserMedia({                     
+			    navigator.getUserMedia({
                     video: {
                     video: {
                         deviceId: constraintsDeviceId,
                         deviceId: constraintsDeviceId,
                         width: {
                         width: {
@@ -121,16 +129,16 @@
                     } else {
                     } else {
                         video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
                         video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
                     }
                     }
-                    
+
                     video.play();
                     video.play();
 
 
                     if (onReady) {
                     if (onReady) {
                         onReady(new BABYLON.VideoTexture("video", video, scene, true, true));
                         onReady(new BABYLON.VideoTexture("video", video, scene, true, true));
                     }
                     }
 			    }, function (e) {
 			    }, function (e) {
-                    Tools.Error(e.name); 
+                    Tools.Error(e.name);
                 });
                 });
             }
             }
         }
         }
     }
     }
-}
+}

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

@@ -272,11 +272,11 @@
             //Future reference - try and find the best place to add a reference to the pointDepth variable.
             //Future reference - try and find the best place to add a reference to the pointDepth variable.
             var arraySize = pointDepth || ~~(Math.sqrt(pos.length / 3) - 1);
             var arraySize = pointDepth || ~~(Math.sqrt(pos.length / 3) - 1);
 
 
-            var dim = Math.min(object.getBoundingInfo().boundingBox.extendSize.x, object.getBoundingInfo().boundingBox.extendSize.z);
+            var dim = Math.min(object.getBoundingInfo().boundingBox.extendSizeWorld.x, object.getBoundingInfo().boundingBox.extendSizeWorld.z);
 
 
             var elementSize = dim * 2 / arraySize;
             var elementSize = dim * 2 / arraySize;
 
 
-            var minY = object.getBoundingInfo().boundingBox.extendSize.y;
+            var minY = object.getBoundingInfo().boundingBox.extendSizeWorld.y;
 
 
             for (var i = 0; i < pos.length; i = i + 3) {
             for (var i = 0; i < pos.length; i = i + 3) {
                 var x = Math.round((pos[i + 0]) / elementSize + arraySize / 2);
                 var x = Math.round((pos[i + 0]) / elementSize + arraySize / 2);
@@ -367,17 +367,17 @@
                 mesh.rotationQuaternion = rotationQuaternion;
                 mesh.rotationQuaternion = rotationQuaternion;
 
 
                 //calculate the new center using a pivot (since Cannon.js doesn't center height maps)
                 //calculate the new center using a pivot (since Cannon.js doesn't center height maps)
-                var p = Matrix.Translation(mesh.getBoundingInfo().boundingBox.extendSize.x, 0, -mesh.getBoundingInfo().boundingBox.extendSize.z);
+                var p = Matrix.Translation(mesh.getBoundingInfo().boundingBox.extendSizeWorld.x, 0, -mesh.getBoundingInfo().boundingBox.extendSizeWorld.z);
                 mesh.setPivotMatrix(p);
                 mesh.setPivotMatrix(p);
                 mesh.computeWorldMatrix(true);
                 mesh.computeWorldMatrix(true);
 
 
                 //calculate the translation
                 //calculate the translation
-                var translation = mesh.getBoundingInfo().boundingBox.center.subtract(center).subtract(mesh.position).negate();
+                var translation = mesh.getBoundingInfo().boundingBox.centerWorld.subtract(center).subtract(mesh.position).negate();
 
 
-                this._tmpPosition.copyFromFloats(translation.x, translation.y - mesh.getBoundingInfo().boundingBox.extendSize.y, translation.z);
+                this._tmpPosition.copyFromFloats(translation.x, translation.y - mesh.getBoundingInfo().boundingBox.extendSizeWorld.y, translation.z);
                 //add it inverted to the delta 
                 //add it inverted to the delta 
-                this._tmpDeltaPosition.copyFrom(mesh.getBoundingInfo().boundingBox.center.subtract(c));
-                this._tmpDeltaPosition.y += mesh.getBoundingInfo().boundingBox.extendSize.y;
+                this._tmpDeltaPosition.copyFrom(mesh.getBoundingInfo().boundingBox.centerWorld.subtract(c));
+                this._tmpDeltaPosition.y += mesh.getBoundingInfo().boundingBox.extendSizeWorld.y;
 
 
                 mesh.setPivotMatrix(oldPivot);
                 mesh.setPivotMatrix(oldPivot);
                 mesh.computeWorldMatrix(true);
                 mesh.computeWorldMatrix(true);

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

@@ -86,6 +86,8 @@ module BABYLON {
                 //If the mesh has a parent, don't initialize the physicsBody. Instead wait for the parent to do that.
                 //If the mesh has a parent, don't initialize the physicsBody. Instead wait for the parent to do that.
                 if (!this.object.parent) {
                 if (!this.object.parent) {
                     this._init();
                     this._init();
+                } else if (this.object.parent.physicsImpostor) {
+                    Tools.Warn("You must affect impostors to children before affecting impostor to parent.");
                 }
                 }
             }
             }
         }
         }

+ 9 - 0
src/babylon.engine.ts

@@ -245,6 +245,7 @@
         private static _ALPHA_MAXIMIZED = 5;
         private static _ALPHA_MAXIMIZED = 5;
         private static _ALPHA_ONEONE = 6;
         private static _ALPHA_ONEONE = 6;
         private static _ALPHA_PREMULTIPLIED = 7;
         private static _ALPHA_PREMULTIPLIED = 7;
+        private static _ALPHA_PREMULTIPLIED_PORTERDUFF = 8;
 
 
         private static _DELAYLOADSTATE_NONE = 0;
         private static _DELAYLOADSTATE_NONE = 0;
         private static _DELAYLOADSTATE_LOADED = 1;
         private static _DELAYLOADSTATE_LOADED = 1;
@@ -376,6 +377,10 @@
             return Engine._ALPHA_PREMULTIPLIED;
             return Engine._ALPHA_PREMULTIPLIED;
         }
         }
 
 
+        public static get ALPHA_PREMULTIPLIED_PORTERDUFF(): number {
+            return Engine._ALPHA_PREMULTIPLIED_PORTERDUFF;
+        }
+
         public static get DELAYLOADSTATE_NONE(): number {
         public static get DELAYLOADSTATE_NONE(): number {
             return Engine._DELAYLOADSTATE_NONE;
             return Engine._DELAYLOADSTATE_NONE;
         }
         }
@@ -2167,6 +2172,10 @@
                     this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
                     this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
                     this._alphaState.alphaBlend = true;
                     this._alphaState.alphaBlend = true;
                     break;
                     break;
+                case Engine.ALPHA_PREMULTIPLIED_PORTERDUFF:
+                    this._alphaState.setAlphaBlendFunctionParameters(this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA);
+                    this._alphaState.alphaBlend = true;
+                    break;
                 case Engine.ALPHA_COMBINE:
                 case Engine.ALPHA_COMBINE:
                     this._alphaState.setAlphaBlendFunctionParameters(this._gl.SRC_ALPHA, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
                     this._alphaState.setAlphaBlendFunctionParameters(this._gl.SRC_ALPHA, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE);
                     this._alphaState.alphaBlend = true;
                     this._alphaState.alphaBlend = true;

+ 3 - 3
src/babylon.scene.ts

@@ -1128,7 +1128,7 @@
                 var canvas = this._engine.getRenderingCanvas();
                 var canvas = this._engine.getRenderingCanvas();
 
 
                 if (!this.pointerMovePredicate) {
                 if (!this.pointerMovePredicate) {
-                    this.pointerMovePredicate = (mesh: AbstractMesh): boolean => mesh.isPickable && mesh.isVisible && mesh.isReady() && (this.constantlyUpdateMeshUnderPointer || (mesh.actionManager !== null && mesh.actionManager !== undefined));
+                    this.pointerMovePredicate = (mesh: AbstractMesh): boolean => mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.isEnabled() && (this.constantlyUpdateMeshUnderPointer || (mesh.actionManager !== null && mesh.actionManager !== undefined));
                 }
                 }
 
 
                 // Meshes
                 // Meshes
@@ -1205,7 +1205,7 @@
 
 
                 if (!this.pointerDownPredicate) {
                 if (!this.pointerDownPredicate) {
                     this.pointerDownPredicate = (mesh: AbstractMesh): boolean => {
                     this.pointerDownPredicate = (mesh: AbstractMesh): boolean => {
-                        return mesh.isPickable && mesh.isVisible && mesh.isReady();
+                        return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.isEnabled();
                     };
                     };
                 }
                 }
 
 
@@ -1335,7 +1335,7 @@
 
 
                     if (!this.pointerUpPredicate) {
                     if (!this.pointerUpPredicate) {
                         this.pointerUpPredicate = (mesh: AbstractMesh): boolean => {
                         this.pointerUpPredicate = (mesh: AbstractMesh): boolean => {
-                            return mesh.isPickable && mesh.isVisible && mesh.isReady();
+                            return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.isEnabled();
                         };
                         };
                     }
                     }