David Catuhe 7 år sedan
förälder
incheckning
7d2b2f8f4f

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 7768 - 7720
Playground/babylon.d.txt


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 18860 - 18846
dist/preview release/babylon.d.ts


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 40 - 40
dist/preview release/babylon.js


+ 142 - 47
dist/preview release/babylon.max.js

@@ -11436,6 +11436,7 @@ var BABYLON;
              * Defines whether the engine has been created with the premultipliedAlpha option on or not.
              */
             this.premultipliedAlpha = true;
+            this._viewportCached = new BABYLON.Vector4(0, 0, 0, 0);
             this._onVRFullScreenTriggered = function () {
                 if (_this._vrDisplay && _this._vrDisplay.isPresenting) {
                     //get the old size before we change
@@ -11451,6 +11452,7 @@ var BABYLON;
                     _this.setSize(_this._oldSize.width, _this._oldSize.height);
                 }
             };
+            this._unpackFlipYCached = null;
             this._boundUniforms = {};
             // Register promises
             BABYLON.PromisePolyfill.Apply();
@@ -12904,6 +12906,19 @@ var BABYLON;
                 gl.disable(gl.SCISSOR_TEST);
             }
         };
+        /** @hidden */
+        Engine.prototype._viewport = function (x, y, width, height) {
+            if (x !== this._viewportCached.x ||
+                y !== this._viewportCached.y ||
+                width !== this._viewportCached.z ||
+                height !== this._viewportCached.w) {
+                this._viewportCached.x = x;
+                this._viewportCached.y = y;
+                this._viewportCached.z = width;
+                this._viewportCached.w = height;
+                this._gl.viewport(x, y, width, height);
+            }
+        };
         /**
          * Set the WebGL's viewport
          * @param viewport defines the viewport element to be used
@@ -12916,7 +12931,7 @@ var BABYLON;
             var x = viewport.x || 0;
             var y = viewport.y || 0;
             this._cachedViewport = viewport;
-            this._gl.viewport(x * width, y * height, width * viewport.width, height * viewport.height);
+            this._viewport(x * width, y * height, width * viewport.width, height * viewport.height);
         };
         /**
          * Directly set the WebGL Viewport
@@ -12929,7 +12944,7 @@ var BABYLON;
         Engine.prototype.setDirectViewport = function (x, y, width, height) {
             var currentViewport = this._cachedViewport;
             this._cachedViewport = null;
-            this._gl.viewport(x, y, width, height);
+            this._viewport(x, y, width, height);
             return currentViewport;
         };
         /**
@@ -13153,7 +13168,7 @@ var BABYLON;
                         requiredHeight = requiredHeight / Math.pow(2, lodLevel);
                     }
                 }
-                gl.viewport(0, 0, requiredWidth, requiredHeight);
+                this._viewport(0, 0, requiredWidth, requiredHeight);
             }
             this.wipeCaches();
         };
@@ -14550,6 +14565,11 @@ var BABYLON;
                 return;
             }
             this._currentEffect = null;
+            this._unpackFlipYCached = null;
+            this._viewportCached.x = 0;
+            this._viewportCached.y = 0;
+            this._viewportCached.z = 0;
+            this._viewportCached.w = 0;
             if (bruteForce) {
                 this.resetTextureCache();
                 this._currentProgram = null;
@@ -14643,7 +14663,7 @@ var BABYLON;
             var isTGA = (extension.indexOf(".tga") === 0);
             // determine if a ktx file should be substituted
             var isKTX = false;
-            if (this._textureFormatInUse && !isBase64 && !fallback) {
+            if (this._textureFormatInUse && !isBase64 && !fallback && !buffer) {
                 url = url.substring(0, lastDot) + this._textureFormatInUse;
                 isKTX = true;
             }
@@ -14668,7 +14688,8 @@ var BABYLON;
                 if (scene) {
                     scene._removePendingData(texture);
                 }
-                if (onLoadObserver) {
+                if (onLoadObserver && !isKTX) {
+                    //dont remove the observer if its a ktx file, since the fallback createTexture call will require it.
                     texture.onLoadedObservable.remove(onLoadObserver);
                 }
                 // fallback for when compressed file not found to try again.  For instance, etc1 does not have an alpha capable type
@@ -14832,7 +14853,7 @@ var BABYLON;
             var internalFormat = this._getInternalFormat(format);
             var textureType = this._getWebGLTextureType(type);
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             if (!this._doNotHandleContextLost) {
                 texture._bufferView = data;
                 texture.format = format;
@@ -14899,6 +14920,13 @@ var BABYLON;
             this._internalTexturesCache.push(texture);
             return texture;
         };
+        /** @hidden */
+        Engine.prototype._unpackFlipY = function (value) {
+            if (this._unpackFlipYCached !== value) {
+                this._unpackFlipYCached = value;
+                this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, value ? 1 : 0);
+            }
+        };
         /**
          * Creates a dynamic texture
          * @param width defines the width of the texture
@@ -14963,7 +14991,7 @@ var BABYLON;
                 return;
             }
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 1 : 0);
+            this._unpackFlipY(invertY);
             if (premulAlpha) {
                 this._gl.pixelStorei(this._gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
             }
@@ -14988,8 +15016,8 @@ var BABYLON;
             if (!texture || texture._isDisabled) {
                 return;
             }
-            this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 0 : 1); // Video are upside down by default
+            var wasPreviouslyBound = this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
+            this._unpackFlipY(!invertY); // Video are upside down by default
             try {
                 // Testing video texture support
                 if (this._videoTextureSupported === undefined) {
@@ -15022,7 +15050,9 @@ var BABYLON;
                 if (texture.generateMipMaps) {
                     this._gl.generateMipmap(this._gl.TEXTURE_2D);
                 }
-                this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+                if (!wasPreviouslyBound) {
+                    this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+                }
                 //    this.resetTextureCache();
                 texture.isReady = true;
             }
@@ -15573,7 +15603,7 @@ var BABYLON;
             var internalFormat = this._getRGBABufferInternalSizedFormat(texture.type, format);
             var bindTarget = texture.isCube ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D;
             this._bindTextureDirectly(bindTarget, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture.invertY ? 1 : 0);
+            this._unpackFlipY(texture.invertY);
             var target = gl.TEXTURE_2D;
             if (texture.isCube) {
                 var target = gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex;
@@ -15705,7 +15735,7 @@ var BABYLON;
                     if (loadData.isDDS) {
                         var info = loadData.info;
                         var data = loadData.data;
-                        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                        _this._unpackFlipY(info.isCompressed);
                         BABYLON.DDSTools.UploadDDSLevels(_this, _this._gl, data, info, true, 6, mipmapIndex);
                     }
                     else {
@@ -15786,7 +15816,7 @@ var BABYLON;
                     var ktx = new BABYLON.KhronosTextureContainer(data, 6);
                     var loadMipmap = ktx.numberOfMipmapLevels > 1 && !noMipmap;
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
+                    _this._unpackFlipY(true);
                     ktx.uploadLevels(_this._gl, !noMipmap);
                     _this.setCubeMapTextureParams(gl, loadMipmap);
                     texture.width = ktx.pixelWidth;
@@ -15825,7 +15855,7 @@ var BABYLON;
                             info = BABYLON.DDSTools.GetDDSInfo(data);
                             loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
                             _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                            _this._unpackFlipY(info.isCompressed);
                             BABYLON.DDSTools.UploadDDSLevels(_this, _this._gl, data, info, loadMipmap, 6, -1, index);
                             if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                                 gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
@@ -15850,7 +15880,7 @@ var BABYLON;
                         }
                         var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
                         _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                        _this._unpackFlipY(info.isCompressed);
                         BABYLON.DDSTools.UploadDDSLevels(_this, _this._gl, data, info, loadMipmap, 6);
                         if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                             gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
@@ -15884,7 +15914,7 @@ var BABYLON;
                         gl.TEXTURE_CUBE_MAP_NEGATIVE_X, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z
                     ];
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+                    _this._unpackFlipY(false);
                     var internalFormat = format ? _this._getInternalFormat(format) : _this._gl.RGBA;
                     for (var index = 0; index < faces.length; index++) {
                         _this._workingContext.drawImage(imgs[index], 0, 0, imgs[index].width, imgs[index].height, 0, 0, width, height);
@@ -15946,7 +15976,7 @@ var BABYLON;
                 needConversion = true;
             }
             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             if (texture.width % 4 !== 0) {
                 gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
             }
@@ -16084,7 +16114,7 @@ var BABYLON;
                         needConversion = true;
                     }
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+                    _this._unpackFlipY(false);
                     var mipData = mipmapGenerator(faceDataArrays);
                     for (var level = 0; level < mipData.length; level++) {
                         var mipSize = width >> level;
@@ -16131,7 +16161,7 @@ var BABYLON;
             var internalFormat = this._getInternalFormat(format);
             var internalSizedFomat = this._getRGBABufferInternalSizedFormat(textureType, format);
             this._bindTextureDirectly(this._gl.TEXTURE_3D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             if (!this._doNotHandleContextLost) {
                 texture._bufferView = data;
                 texture.format = format;
@@ -16235,7 +16265,7 @@ var BABYLON;
                 return;
             }
             this._bindTextureDirectly(gl.TEXTURE_2D, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             texture.baseWidth = width;
             texture.baseHeight = height;
             texture.width = potWidth;
@@ -16422,6 +16452,7 @@ var BABYLON;
         Engine.prototype._bindTextureDirectly = function (target, texture, forTextureDataUpdate, force) {
             if (forTextureDataUpdate === void 0) { forTextureDataUpdate = false; }
             if (force === void 0) { force = false; }
+            var wasPreviouslyBound = false;
             if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
                 this._activeChannel = texture._designatedSlot;
             }
@@ -16447,11 +16478,13 @@ var BABYLON;
                 }
             }
             else if (forTextureDataUpdate) {
+                wasPreviouslyBound = true;
                 this._activateCurrentTexture();
             }
             if (isTextureForRendering && !forTextureDataUpdate) {
                 this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
             }
+            return wasPreviouslyBound;
         };
         /** @hidden */
         Engine.prototype._bindTexture = function (channel, texture) {
@@ -30235,6 +30268,10 @@ var BABYLON;
             /** @hidden */
             this._comparisonFunction = 0;
             /** @hidden */
+            this._lodGenerationScale = 0;
+            /** @hidden */
+            this._lodGenerationOffset = 0;
+            /** @hidden */
             this._isRGBD = false;
             /** @hidden */
             this._references = 1;
@@ -30516,6 +30553,7 @@ var BABYLON;
             */
             this.onDisposeObservable = new BABYLON.Observable();
             this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
+            this._cachedSize = BABYLON.Size.Zero();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             if (this._scene) {
                 this._scene.textures.push(this);
@@ -30665,13 +30703,19 @@ var BABYLON;
             return false;
         };
         BaseTexture.prototype.getSize = function () {
-            if (this._texture && this._texture.width) {
-                return new BABYLON.Size(this._texture.width, this._texture.height);
-            }
-            if (this._texture && this._texture._size) {
-                return new BABYLON.Size(this._texture._size, this._texture._size);
+            if (this._texture) {
+                if (this._texture.width) {
+                    this._cachedSize.width = this._texture.width;
+                    this._cachedSize.height = this._texture.height;
+                    return this._cachedSize;
+                }
+                if (this._texture._size) {
+                    this._cachedSize.width = this._texture._size;
+                    this._cachedSize.height = this._texture._size;
+                    return this._cachedSize;
+                }
             }
-            return BABYLON.Size.Zero();
+            return this._cachedSize;
         };
         BaseTexture.prototype.getBaseSize = function () {
             if (!this.isReady() || !this._texture)
@@ -31268,8 +31312,8 @@ var BABYLON;
         };
         Texture.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
-            if (this.onLoadObservable) {
-                this.onLoadObservable.clear();
+            if (this._onLoadObservable) {
+                this._onLoadObservable.clear();
                 this._onLoadObservable = null;
             }
             this._delayedOnLoad = null;
@@ -31553,6 +31597,7 @@ var BABYLON;
                         system.clone(system.name, _this);
                     }
                 }
+                _this.refreshBoundingInfo();
                 _this.computeWorldMatrix(true);
             }
             // Parent
@@ -55829,6 +55874,9 @@ var BABYLON;
                     this.colorDead.subtractToRef(particle.color, this._colorDiff);
                     this._colorDiff.scaleToRef(1.0 / particle.lifeTime, particle.colorStep);
                 }
+                else {
+                    particle.color.copyFrom(this._colorGradients[0].color);
+                }
             }
         };
         ParticleSystem.prototype._getEffect = function () {
@@ -64342,6 +64390,7 @@ var BABYLON;
                 autoUpdateTexture: true,
             }; }
             var _this = _super.call(this, null, scene, !generateMipMaps, invertY) || this;
+            _this._onUserActionRequestedObservable = null;
             _this._stillImageCaptured = false;
             _this._createInternalTexture = function () {
                 if (_this._texture != null) {
@@ -64360,16 +64409,39 @@ var BABYLON;
                 _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this._samplingMode);
                 if (!_this.video.autoplay) {
                     var oldHandler_1 = _this.video.onplaying;
+                    var error_1 = false;
                     _this.video.onplaying = function () {
                         _this.video.onplaying = oldHandler_1;
                         _this._texture.isReady = true;
                         _this._updateInternalTexture();
-                        _this.video.pause();
+                        if (!error_1) {
+                            _this.video.pause();
+                        }
                         if (_this._onLoadObservable && _this._onLoadObservable.hasObservers()) {
                             _this.onLoadObservable.notifyObservers(_this);
                         }
                     };
-                    _this.video.play();
+                    var playing = _this.video.play();
+                    if (playing) {
+                        playing.then(function () {
+                            // Everything is good.
+                        })
+                            .catch(function () {
+                            error_1 = true;
+                            // On Chrome for instance, new policies might prevent playing without user interaction.
+                            if (_this._onUserActionRequestedObservable && _this._onUserActionRequestedObservable.hasObservers()) {
+                                _this._onUserActionRequestedObservable.notifyObservers(_this);
+                            }
+                        });
+                    }
+                    else {
+                        _this.video.onplaying = oldHandler_1;
+                        _this._texture.isReady = true;
+                        _this._updateInternalTexture();
+                        if (_this._onLoadObservable && _this._onLoadObservable.hasObservers()) {
+                            _this.onLoadObservable.notifyObservers(_this);
+                        }
+                    }
                 }
                 else {
                     _this._texture.isReady = true;
@@ -64401,12 +64473,16 @@ var BABYLON;
             _this.autoUpdateTexture = settings.autoUpdateTexture;
             _this.name = name || _this._getName(src);
             _this.video = _this._getVideo(src);
+            if (settings.poster) {
+                _this.video.poster = settings.poster;
+            }
             if (settings.autoPlay !== undefined) {
                 _this.video.autoplay = settings.autoPlay;
             }
             if (settings.loop !== undefined) {
                 _this.video.loop = settings.loop;
             }
+            _this.video.setAttribute("playsinline", "");
             _this.video.addEventListener("canplay", _this._createInternalTexture);
             _this.video.addEventListener("paused", _this._updateInternalTexture);
             _this.video.addEventListener("seeked", _this._updateInternalTexture);
@@ -64416,6 +64492,16 @@ var BABYLON;
             }
             return _this;
         }
+        Object.defineProperty(VideoTexture.prototype, "onUserActionRequestedObservable", {
+            get: function () {
+                if (!this._onUserActionRequestedObservable) {
+                    this._onUserActionRequestedObservable = new BABYLON.Observable();
+                }
+                return this._onUserActionRequestedObservable;
+            },
+            enumerable: true,
+            configurable: true
+        });
         VideoTexture.prototype._getName = function (src) {
             if (src instanceof HTMLVideoElement) {
                 return src.currentSrc;
@@ -64486,6 +64572,10 @@ var BABYLON;
         };
         VideoTexture.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
+            if (this._onUserActionRequestedObservable) {
+                this._onUserActionRequestedObservable.clear();
+                this._onUserActionRequestedObservable = null;
+            }
             this.video.removeEventListener("canplay", this._createInternalTexture);
             this.video.removeEventListener("paused", this._updateInternalTexture);
             this.video.removeEventListener("seeked", this._updateInternalTexture);
@@ -88042,6 +88132,10 @@ var BABYLON;
                         return;
                     }
                 }
+                var pointerEvent = (prePointerInfo.event);
+                if (originalScene.isPointerCaptured(pointerEvent.pointerId)) {
+                    return;
+                }
                 var utilityScenePick = prePointerInfo.ray ? _this.utilityLayerScene.pickWithRay(prePointerInfo.ray) : _this.utilityLayerScene.pick(originalScene.pointerX, originalScene.pointerY);
                 if (!prePointerInfo.ray && utilityScenePick) {
                     prePointerInfo.ray = utilityScenePick.ray;
@@ -88053,7 +88147,6 @@ var BABYLON;
                     if (!prePointerInfo.skipOnPointerObservable) {
                         _this.utilityLayerScene.onPointerObservable.notifyObservers(new BABYLON.PointerInfo(prePointerInfo.type, prePointerInfo.event, utilityScenePick));
                     }
-                    var pointerEvent = (prePointerInfo.event);
                     if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && _this._pointerCaptures[pointerEvent.pointerId]) {
                         _this._pointerCaptures[pointerEvent.pointerId] = false;
                     }
@@ -88070,40 +88163,40 @@ var BABYLON;
                 }
                 else {
                     var originalScenePick = prePointerInfo.ray ? originalScene.pickWithRay(prePointerInfo.ray) : originalScene.pick(originalScene.pointerX, originalScene.pointerY);
-                    var pointerEvent = (prePointerInfo.event);
+                    var pointerEvent_1 = (prePointerInfo.event);
                     // If the layer can be occluded by the original scene, only fire pointer events to the first layer that hit they ray
                     if (originalScenePick && utilityScenePick) {
                         // No pick in utility scene
-                        if (utilityScenePick.distance === 0) {
+                        if (utilityScenePick.distance === 0 && originalScenePick.pickedMesh) {
                             if (_this.mainSceneTrackerPredicate && _this.mainSceneTrackerPredicate(originalScenePick.pickedMesh)) {
                                 // We touched an utility mesh present in the main scene
-                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent);
+                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent_1);
                                 prePointerInfo.skipOnPointerObservable = true;
                             }
                             else if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERDOWN) {
-                                _this._pointerCaptures[pointerEvent.pointerId] = true;
+                                _this._pointerCaptures[pointerEvent_1.pointerId] = true;
                             }
                         }
-                        // We pick something in utility scene or the pick in utility is closer than the one in main scene
-                        if (!_this._pointerCaptures[pointerEvent.pointerId] && (utilityScenePick.distance < originalScenePick.distance || originalScenePick.distance === 0)) {
-                            _this._notifyObservers(prePointerInfo, utilityScenePick, pointerEvent);
+                        else if (!_this._pointerCaptures[pointerEvent_1.pointerId] && (utilityScenePick.distance < originalScenePick.distance || originalScenePick.distance === 0)) {
+                            // We pick something in utility scene or the pick in utility is closer than the one in main scene
+                            _this._notifyObservers(prePointerInfo, utilityScenePick, pointerEvent_1);
                             prePointerInfo.skipOnPointerObservable = utilityScenePick.distance > 0;
                         }
-                        else if (!_this._pointerCaptures[pointerEvent.pointerId] && (utilityScenePick.distance > originalScenePick.distance)) {
+                        else if (!_this._pointerCaptures[pointerEvent_1.pointerId] && (utilityScenePick.distance > originalScenePick.distance)) {
                             // We have a pick in both scenes but main is closer than utility
                             // We touched an utility mesh present in the main scene
                             if (_this.mainSceneTrackerPredicate && _this.mainSceneTrackerPredicate(originalScenePick.pickedMesh)) {
-                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent);
+                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent_1);
                                 prePointerInfo.skipOnPointerObservable = true;
                             }
-                            else if (_this._lastPointerEvents[pointerEvent.pointerId]) {
+                            else if (_this._lastPointerEvents[pointerEvent_1.pointerId]) {
                                 // We need to send a last pointerup to the utilityLayerScene to make sure animations can complete
-                                _this.onPointerOutObservable.notifyObservers(pointerEvent.pointerId);
-                                delete _this._lastPointerEvents[pointerEvent.pointerId];
+                                _this.onPointerOutObservable.notifyObservers(pointerEvent_1.pointerId);
+                                delete _this._lastPointerEvents[pointerEvent_1.pointerId];
                             }
                         }
-                        if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && _this._pointerCaptures[pointerEvent.pointerId]) {
-                            _this._pointerCaptures[pointerEvent.pointerId] = false;
+                        if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && _this._pointerCaptures[pointerEvent_1.pointerId]) {
+                            _this._pointerCaptures[pointerEvent_1.pointerId] = false;
                         }
                     }
                 }
@@ -99301,7 +99394,9 @@ var BABYLON;
         NullEngine.prototype._bindTextureDirectly = function (target, texture) {
             if (this._boundTexturesCache[this._activeChannel] !== texture) {
                 this._boundTexturesCache[this._activeChannel] = texture;
+                return true;
             }
+            return false;
         };
         NullEngine.prototype._bindTexture = function (channel, texture) {
             if (channel < 0) {
@@ -100980,7 +101075,7 @@ var BABYLON;
                 }
             }
             this._uniformBuffer.update();
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         };
         /**
          * Dispose the material.
@@ -101848,7 +101943,7 @@ var BABYLON;
             options.loop = options.loop === undefined ? true : Boolean(options.loop);
             options.size = Math.abs(options.size) || (scene.activeCamera ? scene.activeCamera.maxZ * 0.48 : 1000);
             // create
-            var tempOptions = { loop: options.loop, autoPlay: options.autoPlay, autoUpdateTexture: true };
+            var tempOptions = { loop: options.loop, autoPlay: options.autoPlay, autoUpdateTexture: true, poster: options.poster };
             var material = _this._material = new BABYLON.BackgroundMaterial(name + "_material", scene);
             var texture = _this._videoTexture = new BABYLON.VideoTexture(name + "_texture", urlsOrVideo, scene, false, false, BABYLON.Texture.TRILINEAR_SAMPLINGMODE, tempOptions);
             _this._mesh = BABYLON.MeshBuilder.CreateIcoSphere(name + "_mesh", {

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

@@ -11403,6 +11403,7 @@ var BABYLON;
              * Defines whether the engine has been created with the premultipliedAlpha option on or not.
              */
             this.premultipliedAlpha = true;
+            this._viewportCached = new BABYLON.Vector4(0, 0, 0, 0);
             this._onVRFullScreenTriggered = function () {
                 if (_this._vrDisplay && _this._vrDisplay.isPresenting) {
                     //get the old size before we change
@@ -11418,6 +11419,7 @@ var BABYLON;
                     _this.setSize(_this._oldSize.width, _this._oldSize.height);
                 }
             };
+            this._unpackFlipYCached = null;
             this._boundUniforms = {};
             // Register promises
             BABYLON.PromisePolyfill.Apply();
@@ -12871,6 +12873,19 @@ var BABYLON;
                 gl.disable(gl.SCISSOR_TEST);
             }
         };
+        /** @hidden */
+        Engine.prototype._viewport = function (x, y, width, height) {
+            if (x !== this._viewportCached.x ||
+                y !== this._viewportCached.y ||
+                width !== this._viewportCached.z ||
+                height !== this._viewportCached.w) {
+                this._viewportCached.x = x;
+                this._viewportCached.y = y;
+                this._viewportCached.z = width;
+                this._viewportCached.w = height;
+                this._gl.viewport(x, y, width, height);
+            }
+        };
         /**
          * Set the WebGL's viewport
          * @param viewport defines the viewport element to be used
@@ -12883,7 +12898,7 @@ var BABYLON;
             var x = viewport.x || 0;
             var y = viewport.y || 0;
             this._cachedViewport = viewport;
-            this._gl.viewport(x * width, y * height, width * viewport.width, height * viewport.height);
+            this._viewport(x * width, y * height, width * viewport.width, height * viewport.height);
         };
         /**
          * Directly set the WebGL Viewport
@@ -12896,7 +12911,7 @@ var BABYLON;
         Engine.prototype.setDirectViewport = function (x, y, width, height) {
             var currentViewport = this._cachedViewport;
             this._cachedViewport = null;
-            this._gl.viewport(x, y, width, height);
+            this._viewport(x, y, width, height);
             return currentViewport;
         };
         /**
@@ -13120,7 +13135,7 @@ var BABYLON;
                         requiredHeight = requiredHeight / Math.pow(2, lodLevel);
                     }
                 }
-                gl.viewport(0, 0, requiredWidth, requiredHeight);
+                this._viewport(0, 0, requiredWidth, requiredHeight);
             }
             this.wipeCaches();
         };
@@ -14517,6 +14532,11 @@ var BABYLON;
                 return;
             }
             this._currentEffect = null;
+            this._unpackFlipYCached = null;
+            this._viewportCached.x = 0;
+            this._viewportCached.y = 0;
+            this._viewportCached.z = 0;
+            this._viewportCached.w = 0;
             if (bruteForce) {
                 this.resetTextureCache();
                 this._currentProgram = null;
@@ -14610,7 +14630,7 @@ var BABYLON;
             var isTGA = (extension.indexOf(".tga") === 0);
             // determine if a ktx file should be substituted
             var isKTX = false;
-            if (this._textureFormatInUse && !isBase64 && !fallback) {
+            if (this._textureFormatInUse && !isBase64 && !fallback && !buffer) {
                 url = url.substring(0, lastDot) + this._textureFormatInUse;
                 isKTX = true;
             }
@@ -14635,7 +14655,8 @@ var BABYLON;
                 if (scene) {
                     scene._removePendingData(texture);
                 }
-                if (onLoadObserver) {
+                if (onLoadObserver && !isKTX) {
+                    //dont remove the observer if its a ktx file, since the fallback createTexture call will require it.
                     texture.onLoadedObservable.remove(onLoadObserver);
                 }
                 // fallback for when compressed file not found to try again.  For instance, etc1 does not have an alpha capable type
@@ -14799,7 +14820,7 @@ var BABYLON;
             var internalFormat = this._getInternalFormat(format);
             var textureType = this._getWebGLTextureType(type);
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             if (!this._doNotHandleContextLost) {
                 texture._bufferView = data;
                 texture.format = format;
@@ -14866,6 +14887,13 @@ var BABYLON;
             this._internalTexturesCache.push(texture);
             return texture;
         };
+        /** @hidden */
+        Engine.prototype._unpackFlipY = function (value) {
+            if (this._unpackFlipYCached !== value) {
+                this._unpackFlipYCached = value;
+                this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, value ? 1 : 0);
+            }
+        };
         /**
          * Creates a dynamic texture
          * @param width defines the width of the texture
@@ -14930,7 +14958,7 @@ var BABYLON;
                 return;
             }
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 1 : 0);
+            this._unpackFlipY(invertY);
             if (premulAlpha) {
                 this._gl.pixelStorei(this._gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
             }
@@ -14955,8 +14983,8 @@ var BABYLON;
             if (!texture || texture._isDisabled) {
                 return;
             }
-            this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 0 : 1); // Video are upside down by default
+            var wasPreviouslyBound = this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
+            this._unpackFlipY(!invertY); // Video are upside down by default
             try {
                 // Testing video texture support
                 if (this._videoTextureSupported === undefined) {
@@ -14989,7 +15017,9 @@ var BABYLON;
                 if (texture.generateMipMaps) {
                     this._gl.generateMipmap(this._gl.TEXTURE_2D);
                 }
-                this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+                if (!wasPreviouslyBound) {
+                    this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+                }
                 //    this.resetTextureCache();
                 texture.isReady = true;
             }
@@ -15540,7 +15570,7 @@ var BABYLON;
             var internalFormat = this._getRGBABufferInternalSizedFormat(texture.type, format);
             var bindTarget = texture.isCube ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D;
             this._bindTextureDirectly(bindTarget, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture.invertY ? 1 : 0);
+            this._unpackFlipY(texture.invertY);
             var target = gl.TEXTURE_2D;
             if (texture.isCube) {
                 var target = gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex;
@@ -15672,7 +15702,7 @@ var BABYLON;
                     if (loadData.isDDS) {
                         var info = loadData.info;
                         var data = loadData.data;
-                        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                        _this._unpackFlipY(info.isCompressed);
                         BABYLON.DDSTools.UploadDDSLevels(_this, _this._gl, data, info, true, 6, mipmapIndex);
                     }
                     else {
@@ -15753,7 +15783,7 @@ var BABYLON;
                     var ktx = new BABYLON.KhronosTextureContainer(data, 6);
                     var loadMipmap = ktx.numberOfMipmapLevels > 1 && !noMipmap;
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
+                    _this._unpackFlipY(true);
                     ktx.uploadLevels(_this._gl, !noMipmap);
                     _this.setCubeMapTextureParams(gl, loadMipmap);
                     texture.width = ktx.pixelWidth;
@@ -15792,7 +15822,7 @@ var BABYLON;
                             info = BABYLON.DDSTools.GetDDSInfo(data);
                             loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
                             _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                            _this._unpackFlipY(info.isCompressed);
                             BABYLON.DDSTools.UploadDDSLevels(_this, _this._gl, data, info, loadMipmap, 6, -1, index);
                             if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                                 gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
@@ -15817,7 +15847,7 @@ var BABYLON;
                         }
                         var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
                         _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                        _this._unpackFlipY(info.isCompressed);
                         BABYLON.DDSTools.UploadDDSLevels(_this, _this._gl, data, info, loadMipmap, 6);
                         if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                             gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
@@ -15851,7 +15881,7 @@ var BABYLON;
                         gl.TEXTURE_CUBE_MAP_NEGATIVE_X, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z
                     ];
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+                    _this._unpackFlipY(false);
                     var internalFormat = format ? _this._getInternalFormat(format) : _this._gl.RGBA;
                     for (var index = 0; index < faces.length; index++) {
                         _this._workingContext.drawImage(imgs[index], 0, 0, imgs[index].width, imgs[index].height, 0, 0, width, height);
@@ -15913,7 +15943,7 @@ var BABYLON;
                 needConversion = true;
             }
             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             if (texture.width % 4 !== 0) {
                 gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
             }
@@ -16051,7 +16081,7 @@ var BABYLON;
                         needConversion = true;
                     }
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+                    _this._unpackFlipY(false);
                     var mipData = mipmapGenerator(faceDataArrays);
                     for (var level = 0; level < mipData.length; level++) {
                         var mipSize = width >> level;
@@ -16098,7 +16128,7 @@ var BABYLON;
             var internalFormat = this._getInternalFormat(format);
             var internalSizedFomat = this._getRGBABufferInternalSizedFormat(textureType, format);
             this._bindTextureDirectly(this._gl.TEXTURE_3D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             if (!this._doNotHandleContextLost) {
                 texture._bufferView = data;
                 texture.format = format;
@@ -16202,7 +16232,7 @@ var BABYLON;
                 return;
             }
             this._bindTextureDirectly(gl.TEXTURE_2D, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             texture.baseWidth = width;
             texture.baseHeight = height;
             texture.width = potWidth;
@@ -16389,6 +16419,7 @@ var BABYLON;
         Engine.prototype._bindTextureDirectly = function (target, texture, forTextureDataUpdate, force) {
             if (forTextureDataUpdate === void 0) { forTextureDataUpdate = false; }
             if (force === void 0) { force = false; }
+            var wasPreviouslyBound = false;
             if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
                 this._activeChannel = texture._designatedSlot;
             }
@@ -16414,11 +16445,13 @@ var BABYLON;
                 }
             }
             else if (forTextureDataUpdate) {
+                wasPreviouslyBound = true;
                 this._activateCurrentTexture();
             }
             if (isTextureForRendering && !forTextureDataUpdate) {
                 this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
             }
+            return wasPreviouslyBound;
         };
         /** @hidden */
         Engine.prototype._bindTexture = function (channel, texture) {
@@ -30202,6 +30235,10 @@ var BABYLON;
             /** @hidden */
             this._comparisonFunction = 0;
             /** @hidden */
+            this._lodGenerationScale = 0;
+            /** @hidden */
+            this._lodGenerationOffset = 0;
+            /** @hidden */
             this._isRGBD = false;
             /** @hidden */
             this._references = 1;
@@ -30483,6 +30520,7 @@ var BABYLON;
             */
             this.onDisposeObservable = new BABYLON.Observable();
             this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
+            this._cachedSize = BABYLON.Size.Zero();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             if (this._scene) {
                 this._scene.textures.push(this);
@@ -30632,13 +30670,19 @@ var BABYLON;
             return false;
         };
         BaseTexture.prototype.getSize = function () {
-            if (this._texture && this._texture.width) {
-                return new BABYLON.Size(this._texture.width, this._texture.height);
-            }
-            if (this._texture && this._texture._size) {
-                return new BABYLON.Size(this._texture._size, this._texture._size);
+            if (this._texture) {
+                if (this._texture.width) {
+                    this._cachedSize.width = this._texture.width;
+                    this._cachedSize.height = this._texture.height;
+                    return this._cachedSize;
+                }
+                if (this._texture._size) {
+                    this._cachedSize.width = this._texture._size;
+                    this._cachedSize.height = this._texture._size;
+                    return this._cachedSize;
+                }
             }
-            return BABYLON.Size.Zero();
+            return this._cachedSize;
         };
         BaseTexture.prototype.getBaseSize = function () {
             if (!this.isReady() || !this._texture)
@@ -31235,8 +31279,8 @@ var BABYLON;
         };
         Texture.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
-            if (this.onLoadObservable) {
-                this.onLoadObservable.clear();
+            if (this._onLoadObservable) {
+                this._onLoadObservable.clear();
                 this._onLoadObservable = null;
             }
             this._delayedOnLoad = null;
@@ -31520,6 +31564,7 @@ var BABYLON;
                         system.clone(system.name, _this);
                     }
                 }
+                _this.refreshBoundingInfo();
                 _this.computeWorldMatrix(true);
             }
             // Parent
@@ -55796,6 +55841,9 @@ var BABYLON;
                     this.colorDead.subtractToRef(particle.color, this._colorDiff);
                     this._colorDiff.scaleToRef(1.0 / particle.lifeTime, particle.colorStep);
                 }
+                else {
+                    particle.color.copyFrom(this._colorGradients[0].color);
+                }
             }
         };
         ParticleSystem.prototype._getEffect = function () {
@@ -64309,6 +64357,7 @@ var BABYLON;
                 autoUpdateTexture: true,
             }; }
             var _this = _super.call(this, null, scene, !generateMipMaps, invertY) || this;
+            _this._onUserActionRequestedObservable = null;
             _this._stillImageCaptured = false;
             _this._createInternalTexture = function () {
                 if (_this._texture != null) {
@@ -64327,16 +64376,39 @@ var BABYLON;
                 _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this._samplingMode);
                 if (!_this.video.autoplay) {
                     var oldHandler_1 = _this.video.onplaying;
+                    var error_1 = false;
                     _this.video.onplaying = function () {
                         _this.video.onplaying = oldHandler_1;
                         _this._texture.isReady = true;
                         _this._updateInternalTexture();
-                        _this.video.pause();
+                        if (!error_1) {
+                            _this.video.pause();
+                        }
                         if (_this._onLoadObservable && _this._onLoadObservable.hasObservers()) {
                             _this.onLoadObservable.notifyObservers(_this);
                         }
                     };
-                    _this.video.play();
+                    var playing = _this.video.play();
+                    if (playing) {
+                        playing.then(function () {
+                            // Everything is good.
+                        })
+                            .catch(function () {
+                            error_1 = true;
+                            // On Chrome for instance, new policies might prevent playing without user interaction.
+                            if (_this._onUserActionRequestedObservable && _this._onUserActionRequestedObservable.hasObservers()) {
+                                _this._onUserActionRequestedObservable.notifyObservers(_this);
+                            }
+                        });
+                    }
+                    else {
+                        _this.video.onplaying = oldHandler_1;
+                        _this._texture.isReady = true;
+                        _this._updateInternalTexture();
+                        if (_this._onLoadObservable && _this._onLoadObservable.hasObservers()) {
+                            _this.onLoadObservable.notifyObservers(_this);
+                        }
+                    }
                 }
                 else {
                     _this._texture.isReady = true;
@@ -64368,12 +64440,16 @@ var BABYLON;
             _this.autoUpdateTexture = settings.autoUpdateTexture;
             _this.name = name || _this._getName(src);
             _this.video = _this._getVideo(src);
+            if (settings.poster) {
+                _this.video.poster = settings.poster;
+            }
             if (settings.autoPlay !== undefined) {
                 _this.video.autoplay = settings.autoPlay;
             }
             if (settings.loop !== undefined) {
                 _this.video.loop = settings.loop;
             }
+            _this.video.setAttribute("playsinline", "");
             _this.video.addEventListener("canplay", _this._createInternalTexture);
             _this.video.addEventListener("paused", _this._updateInternalTexture);
             _this.video.addEventListener("seeked", _this._updateInternalTexture);
@@ -64383,6 +64459,16 @@ var BABYLON;
             }
             return _this;
         }
+        Object.defineProperty(VideoTexture.prototype, "onUserActionRequestedObservable", {
+            get: function () {
+                if (!this._onUserActionRequestedObservable) {
+                    this._onUserActionRequestedObservable = new BABYLON.Observable();
+                }
+                return this._onUserActionRequestedObservable;
+            },
+            enumerable: true,
+            configurable: true
+        });
         VideoTexture.prototype._getName = function (src) {
             if (src instanceof HTMLVideoElement) {
                 return src.currentSrc;
@@ -64453,6 +64539,10 @@ var BABYLON;
         };
         VideoTexture.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
+            if (this._onUserActionRequestedObservable) {
+                this._onUserActionRequestedObservable.clear();
+                this._onUserActionRequestedObservable = null;
+            }
             this.video.removeEventListener("canplay", this._createInternalTexture);
             this.video.removeEventListener("paused", this._updateInternalTexture);
             this.video.removeEventListener("seeked", this._updateInternalTexture);
@@ -88009,6 +88099,10 @@ var BABYLON;
                         return;
                     }
                 }
+                var pointerEvent = (prePointerInfo.event);
+                if (originalScene.isPointerCaptured(pointerEvent.pointerId)) {
+                    return;
+                }
                 var utilityScenePick = prePointerInfo.ray ? _this.utilityLayerScene.pickWithRay(prePointerInfo.ray) : _this.utilityLayerScene.pick(originalScene.pointerX, originalScene.pointerY);
                 if (!prePointerInfo.ray && utilityScenePick) {
                     prePointerInfo.ray = utilityScenePick.ray;
@@ -88020,7 +88114,6 @@ var BABYLON;
                     if (!prePointerInfo.skipOnPointerObservable) {
                         _this.utilityLayerScene.onPointerObservable.notifyObservers(new BABYLON.PointerInfo(prePointerInfo.type, prePointerInfo.event, utilityScenePick));
                     }
-                    var pointerEvent = (prePointerInfo.event);
                     if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && _this._pointerCaptures[pointerEvent.pointerId]) {
                         _this._pointerCaptures[pointerEvent.pointerId] = false;
                     }
@@ -88037,40 +88130,40 @@ var BABYLON;
                 }
                 else {
                     var originalScenePick = prePointerInfo.ray ? originalScene.pickWithRay(prePointerInfo.ray) : originalScene.pick(originalScene.pointerX, originalScene.pointerY);
-                    var pointerEvent = (prePointerInfo.event);
+                    var pointerEvent_1 = (prePointerInfo.event);
                     // If the layer can be occluded by the original scene, only fire pointer events to the first layer that hit they ray
                     if (originalScenePick && utilityScenePick) {
                         // No pick in utility scene
-                        if (utilityScenePick.distance === 0) {
+                        if (utilityScenePick.distance === 0 && originalScenePick.pickedMesh) {
                             if (_this.mainSceneTrackerPredicate && _this.mainSceneTrackerPredicate(originalScenePick.pickedMesh)) {
                                 // We touched an utility mesh present in the main scene
-                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent);
+                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent_1);
                                 prePointerInfo.skipOnPointerObservable = true;
                             }
                             else if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERDOWN) {
-                                _this._pointerCaptures[pointerEvent.pointerId] = true;
+                                _this._pointerCaptures[pointerEvent_1.pointerId] = true;
                             }
                         }
-                        // We pick something in utility scene or the pick in utility is closer than the one in main scene
-                        if (!_this._pointerCaptures[pointerEvent.pointerId] && (utilityScenePick.distance < originalScenePick.distance || originalScenePick.distance === 0)) {
-                            _this._notifyObservers(prePointerInfo, utilityScenePick, pointerEvent);
+                        else if (!_this._pointerCaptures[pointerEvent_1.pointerId] && (utilityScenePick.distance < originalScenePick.distance || originalScenePick.distance === 0)) {
+                            // We pick something in utility scene or the pick in utility is closer than the one in main scene
+                            _this._notifyObservers(prePointerInfo, utilityScenePick, pointerEvent_1);
                             prePointerInfo.skipOnPointerObservable = utilityScenePick.distance > 0;
                         }
-                        else if (!_this._pointerCaptures[pointerEvent.pointerId] && (utilityScenePick.distance > originalScenePick.distance)) {
+                        else if (!_this._pointerCaptures[pointerEvent_1.pointerId] && (utilityScenePick.distance > originalScenePick.distance)) {
                             // We have a pick in both scenes but main is closer than utility
                             // We touched an utility mesh present in the main scene
                             if (_this.mainSceneTrackerPredicate && _this.mainSceneTrackerPredicate(originalScenePick.pickedMesh)) {
-                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent);
+                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent_1);
                                 prePointerInfo.skipOnPointerObservable = true;
                             }
-                            else if (_this._lastPointerEvents[pointerEvent.pointerId]) {
+                            else if (_this._lastPointerEvents[pointerEvent_1.pointerId]) {
                                 // We need to send a last pointerup to the utilityLayerScene to make sure animations can complete
-                                _this.onPointerOutObservable.notifyObservers(pointerEvent.pointerId);
-                                delete _this._lastPointerEvents[pointerEvent.pointerId];
+                                _this.onPointerOutObservable.notifyObservers(pointerEvent_1.pointerId);
+                                delete _this._lastPointerEvents[pointerEvent_1.pointerId];
                             }
                         }
-                        if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && _this._pointerCaptures[pointerEvent.pointerId]) {
-                            _this._pointerCaptures[pointerEvent.pointerId] = false;
+                        if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && _this._pointerCaptures[pointerEvent_1.pointerId]) {
+                            _this._pointerCaptures[pointerEvent_1.pointerId] = false;
                         }
                     }
                 }
@@ -99268,7 +99361,9 @@ var BABYLON;
         NullEngine.prototype._bindTextureDirectly = function (target, texture) {
             if (this._boundTexturesCache[this._activeChannel] !== texture) {
                 this._boundTexturesCache[this._activeChannel] = texture;
+                return true;
             }
+            return false;
         };
         NullEngine.prototype._bindTexture = function (channel, texture) {
             if (channel < 0) {
@@ -100947,7 +101042,7 @@ var BABYLON;
                 }
             }
             this._uniformBuffer.update();
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         };
         /**
          * Dispose the material.
@@ -101815,7 +101910,7 @@ var BABYLON;
             options.loop = options.loop === undefined ? true : Boolean(options.loop);
             options.size = Math.abs(options.size) || (scene.activeCamera ? scene.activeCamera.maxZ * 0.48 : 1000);
             // create
-            var tempOptions = { loop: options.loop, autoPlay: options.autoPlay, autoUpdateTexture: true };
+            var tempOptions = { loop: options.loop, autoPlay: options.autoPlay, autoUpdateTexture: true, poster: options.poster };
             var material = _this._material = new BABYLON.BackgroundMaterial(name + "_material", scene);
             var texture = _this._videoTexture = new BABYLON.VideoTexture(name + "_texture", urlsOrVideo, scene, false, false, BABYLON.Texture.TRILINEAR_SAMPLINGMODE, tempOptions);
             _this._mesh = BABYLON.MeshBuilder.CreateIcoSphere(name + "_mesh", {

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 46 - 46
dist/preview release/babylon.worker.js


+ 142 - 47
dist/preview release/es6.js

@@ -11403,6 +11403,7 @@ var BABYLON;
              * Defines whether the engine has been created with the premultipliedAlpha option on or not.
              */
             this.premultipliedAlpha = true;
+            this._viewportCached = new BABYLON.Vector4(0, 0, 0, 0);
             this._onVRFullScreenTriggered = function () {
                 if (_this._vrDisplay && _this._vrDisplay.isPresenting) {
                     //get the old size before we change
@@ -11418,6 +11419,7 @@ var BABYLON;
                     _this.setSize(_this._oldSize.width, _this._oldSize.height);
                 }
             };
+            this._unpackFlipYCached = null;
             this._boundUniforms = {};
             // Register promises
             BABYLON.PromisePolyfill.Apply();
@@ -12871,6 +12873,19 @@ var BABYLON;
                 gl.disable(gl.SCISSOR_TEST);
             }
         };
+        /** @hidden */
+        Engine.prototype._viewport = function (x, y, width, height) {
+            if (x !== this._viewportCached.x ||
+                y !== this._viewportCached.y ||
+                width !== this._viewportCached.z ||
+                height !== this._viewportCached.w) {
+                this._viewportCached.x = x;
+                this._viewportCached.y = y;
+                this._viewportCached.z = width;
+                this._viewportCached.w = height;
+                this._gl.viewport(x, y, width, height);
+            }
+        };
         /**
          * Set the WebGL's viewport
          * @param viewport defines the viewport element to be used
@@ -12883,7 +12898,7 @@ var BABYLON;
             var x = viewport.x || 0;
             var y = viewport.y || 0;
             this._cachedViewport = viewport;
-            this._gl.viewport(x * width, y * height, width * viewport.width, height * viewport.height);
+            this._viewport(x * width, y * height, width * viewport.width, height * viewport.height);
         };
         /**
          * Directly set the WebGL Viewport
@@ -12896,7 +12911,7 @@ var BABYLON;
         Engine.prototype.setDirectViewport = function (x, y, width, height) {
             var currentViewport = this._cachedViewport;
             this._cachedViewport = null;
-            this._gl.viewport(x, y, width, height);
+            this._viewport(x, y, width, height);
             return currentViewport;
         };
         /**
@@ -13120,7 +13135,7 @@ var BABYLON;
                         requiredHeight = requiredHeight / Math.pow(2, lodLevel);
                     }
                 }
-                gl.viewport(0, 0, requiredWidth, requiredHeight);
+                this._viewport(0, 0, requiredWidth, requiredHeight);
             }
             this.wipeCaches();
         };
@@ -14517,6 +14532,11 @@ var BABYLON;
                 return;
             }
             this._currentEffect = null;
+            this._unpackFlipYCached = null;
+            this._viewportCached.x = 0;
+            this._viewportCached.y = 0;
+            this._viewportCached.z = 0;
+            this._viewportCached.w = 0;
             if (bruteForce) {
                 this.resetTextureCache();
                 this._currentProgram = null;
@@ -14610,7 +14630,7 @@ var BABYLON;
             var isTGA = (extension.indexOf(".tga") === 0);
             // determine if a ktx file should be substituted
             var isKTX = false;
-            if (this._textureFormatInUse && !isBase64 && !fallback) {
+            if (this._textureFormatInUse && !isBase64 && !fallback && !buffer) {
                 url = url.substring(0, lastDot) + this._textureFormatInUse;
                 isKTX = true;
             }
@@ -14635,7 +14655,8 @@ var BABYLON;
                 if (scene) {
                     scene._removePendingData(texture);
                 }
-                if (onLoadObserver) {
+                if (onLoadObserver && !isKTX) {
+                    //dont remove the observer if its a ktx file, since the fallback createTexture call will require it.
                     texture.onLoadedObservable.remove(onLoadObserver);
                 }
                 // fallback for when compressed file not found to try again.  For instance, etc1 does not have an alpha capable type
@@ -14799,7 +14820,7 @@ var BABYLON;
             var internalFormat = this._getInternalFormat(format);
             var textureType = this._getWebGLTextureType(type);
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             if (!this._doNotHandleContextLost) {
                 texture._bufferView = data;
                 texture.format = format;
@@ -14866,6 +14887,13 @@ var BABYLON;
             this._internalTexturesCache.push(texture);
             return texture;
         };
+        /** @hidden */
+        Engine.prototype._unpackFlipY = function (value) {
+            if (this._unpackFlipYCached !== value) {
+                this._unpackFlipYCached = value;
+                this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, value ? 1 : 0);
+            }
+        };
         /**
          * Creates a dynamic texture
          * @param width defines the width of the texture
@@ -14930,7 +14958,7 @@ var BABYLON;
                 return;
             }
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 1 : 0);
+            this._unpackFlipY(invertY);
             if (premulAlpha) {
                 this._gl.pixelStorei(this._gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
             }
@@ -14955,8 +14983,8 @@ var BABYLON;
             if (!texture || texture._isDisabled) {
                 return;
             }
-            this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 0 : 1); // Video are upside down by default
+            var wasPreviouslyBound = this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
+            this._unpackFlipY(!invertY); // Video are upside down by default
             try {
                 // Testing video texture support
                 if (this._videoTextureSupported === undefined) {
@@ -14989,7 +15017,9 @@ var BABYLON;
                 if (texture.generateMipMaps) {
                     this._gl.generateMipmap(this._gl.TEXTURE_2D);
                 }
-                this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+                if (!wasPreviouslyBound) {
+                    this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+                }
                 //    this.resetTextureCache();
                 texture.isReady = true;
             }
@@ -15540,7 +15570,7 @@ var BABYLON;
             var internalFormat = this._getRGBABufferInternalSizedFormat(texture.type, format);
             var bindTarget = texture.isCube ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D;
             this._bindTextureDirectly(bindTarget, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture.invertY ? 1 : 0);
+            this._unpackFlipY(texture.invertY);
             var target = gl.TEXTURE_2D;
             if (texture.isCube) {
                 var target = gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex;
@@ -15672,7 +15702,7 @@ var BABYLON;
                     if (loadData.isDDS) {
                         var info = loadData.info;
                         var data = loadData.data;
-                        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                        _this._unpackFlipY(info.isCompressed);
                         BABYLON.DDSTools.UploadDDSLevels(_this, _this._gl, data, info, true, 6, mipmapIndex);
                     }
                     else {
@@ -15753,7 +15783,7 @@ var BABYLON;
                     var ktx = new BABYLON.KhronosTextureContainer(data, 6);
                     var loadMipmap = ktx.numberOfMipmapLevels > 1 && !noMipmap;
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
+                    _this._unpackFlipY(true);
                     ktx.uploadLevels(_this._gl, !noMipmap);
                     _this.setCubeMapTextureParams(gl, loadMipmap);
                     texture.width = ktx.pixelWidth;
@@ -15792,7 +15822,7 @@ var BABYLON;
                             info = BABYLON.DDSTools.GetDDSInfo(data);
                             loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
                             _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                            _this._unpackFlipY(info.isCompressed);
                             BABYLON.DDSTools.UploadDDSLevels(_this, _this._gl, data, info, loadMipmap, 6, -1, index);
                             if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                                 gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
@@ -15817,7 +15847,7 @@ var BABYLON;
                         }
                         var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
                         _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                        _this._unpackFlipY(info.isCompressed);
                         BABYLON.DDSTools.UploadDDSLevels(_this, _this._gl, data, info, loadMipmap, 6);
                         if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                             gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
@@ -15851,7 +15881,7 @@ var BABYLON;
                         gl.TEXTURE_CUBE_MAP_NEGATIVE_X, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z
                     ];
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+                    _this._unpackFlipY(false);
                     var internalFormat = format ? _this._getInternalFormat(format) : _this._gl.RGBA;
                     for (var index = 0; index < faces.length; index++) {
                         _this._workingContext.drawImage(imgs[index], 0, 0, imgs[index].width, imgs[index].height, 0, 0, width, height);
@@ -15913,7 +15943,7 @@ var BABYLON;
                 needConversion = true;
             }
             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             if (texture.width % 4 !== 0) {
                 gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
             }
@@ -16051,7 +16081,7 @@ var BABYLON;
                         needConversion = true;
                     }
                     _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+                    _this._unpackFlipY(false);
                     var mipData = mipmapGenerator(faceDataArrays);
                     for (var level = 0; level < mipData.length; level++) {
                         var mipSize = width >> level;
@@ -16098,7 +16128,7 @@ var BABYLON;
             var internalFormat = this._getInternalFormat(format);
             var internalSizedFomat = this._getRGBABufferInternalSizedFormat(textureType, format);
             this._bindTextureDirectly(this._gl.TEXTURE_3D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             if (!this._doNotHandleContextLost) {
                 texture._bufferView = data;
                 texture.format = format;
@@ -16202,7 +16232,7 @@ var BABYLON;
                 return;
             }
             this._bindTextureDirectly(gl.TEXTURE_2D, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
             texture.baseWidth = width;
             texture.baseHeight = height;
             texture.width = potWidth;
@@ -16389,6 +16419,7 @@ var BABYLON;
         Engine.prototype._bindTextureDirectly = function (target, texture, forTextureDataUpdate, force) {
             if (forTextureDataUpdate === void 0) { forTextureDataUpdate = false; }
             if (force === void 0) { force = false; }
+            var wasPreviouslyBound = false;
             if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
                 this._activeChannel = texture._designatedSlot;
             }
@@ -16414,11 +16445,13 @@ var BABYLON;
                 }
             }
             else if (forTextureDataUpdate) {
+                wasPreviouslyBound = true;
                 this._activateCurrentTexture();
             }
             if (isTextureForRendering && !forTextureDataUpdate) {
                 this._bindSamplerUniformToChannel(texture._initialSlot, this._activeChannel);
             }
+            return wasPreviouslyBound;
         };
         /** @hidden */
         Engine.prototype._bindTexture = function (channel, texture) {
@@ -30202,6 +30235,10 @@ var BABYLON;
             /** @hidden */
             this._comparisonFunction = 0;
             /** @hidden */
+            this._lodGenerationScale = 0;
+            /** @hidden */
+            this._lodGenerationOffset = 0;
+            /** @hidden */
             this._isRGBD = false;
             /** @hidden */
             this._references = 1;
@@ -30483,6 +30520,7 @@ var BABYLON;
             */
             this.onDisposeObservable = new BABYLON.Observable();
             this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_NONE;
+            this._cachedSize = BABYLON.Size.Zero();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             if (this._scene) {
                 this._scene.textures.push(this);
@@ -30632,13 +30670,19 @@ var BABYLON;
             return false;
         };
         BaseTexture.prototype.getSize = function () {
-            if (this._texture && this._texture.width) {
-                return new BABYLON.Size(this._texture.width, this._texture.height);
-            }
-            if (this._texture && this._texture._size) {
-                return new BABYLON.Size(this._texture._size, this._texture._size);
+            if (this._texture) {
+                if (this._texture.width) {
+                    this._cachedSize.width = this._texture.width;
+                    this._cachedSize.height = this._texture.height;
+                    return this._cachedSize;
+                }
+                if (this._texture._size) {
+                    this._cachedSize.width = this._texture._size;
+                    this._cachedSize.height = this._texture._size;
+                    return this._cachedSize;
+                }
             }
-            return BABYLON.Size.Zero();
+            return this._cachedSize;
         };
         BaseTexture.prototype.getBaseSize = function () {
             if (!this.isReady() || !this._texture)
@@ -31235,8 +31279,8 @@ var BABYLON;
         };
         Texture.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
-            if (this.onLoadObservable) {
-                this.onLoadObservable.clear();
+            if (this._onLoadObservable) {
+                this._onLoadObservable.clear();
                 this._onLoadObservable = null;
             }
             this._delayedOnLoad = null;
@@ -31520,6 +31564,7 @@ var BABYLON;
                         system.clone(system.name, _this);
                     }
                 }
+                _this.refreshBoundingInfo();
                 _this.computeWorldMatrix(true);
             }
             // Parent
@@ -55796,6 +55841,9 @@ var BABYLON;
                     this.colorDead.subtractToRef(particle.color, this._colorDiff);
                     this._colorDiff.scaleToRef(1.0 / particle.lifeTime, particle.colorStep);
                 }
+                else {
+                    particle.color.copyFrom(this._colorGradients[0].color);
+                }
             }
         };
         ParticleSystem.prototype._getEffect = function () {
@@ -64309,6 +64357,7 @@ var BABYLON;
                 autoUpdateTexture: true,
             }; }
             var _this = _super.call(this, null, scene, !generateMipMaps, invertY) || this;
+            _this._onUserActionRequestedObservable = null;
             _this._stillImageCaptured = false;
             _this._createInternalTexture = function () {
                 if (_this._texture != null) {
@@ -64327,16 +64376,39 @@ var BABYLON;
                 _this._texture = _this._engine.createDynamicTexture(_this.video.videoWidth, _this.video.videoHeight, _this._generateMipMaps, _this._samplingMode);
                 if (!_this.video.autoplay) {
                     var oldHandler_1 = _this.video.onplaying;
+                    var error_1 = false;
                     _this.video.onplaying = function () {
                         _this.video.onplaying = oldHandler_1;
                         _this._texture.isReady = true;
                         _this._updateInternalTexture();
-                        _this.video.pause();
+                        if (!error_1) {
+                            _this.video.pause();
+                        }
                         if (_this._onLoadObservable && _this._onLoadObservable.hasObservers()) {
                             _this.onLoadObservable.notifyObservers(_this);
                         }
                     };
-                    _this.video.play();
+                    var playing = _this.video.play();
+                    if (playing) {
+                        playing.then(function () {
+                            // Everything is good.
+                        })
+                            .catch(function () {
+                            error_1 = true;
+                            // On Chrome for instance, new policies might prevent playing without user interaction.
+                            if (_this._onUserActionRequestedObservable && _this._onUserActionRequestedObservable.hasObservers()) {
+                                _this._onUserActionRequestedObservable.notifyObservers(_this);
+                            }
+                        });
+                    }
+                    else {
+                        _this.video.onplaying = oldHandler_1;
+                        _this._texture.isReady = true;
+                        _this._updateInternalTexture();
+                        if (_this._onLoadObservable && _this._onLoadObservable.hasObservers()) {
+                            _this.onLoadObservable.notifyObservers(_this);
+                        }
+                    }
                 }
                 else {
                     _this._texture.isReady = true;
@@ -64368,12 +64440,16 @@ var BABYLON;
             _this.autoUpdateTexture = settings.autoUpdateTexture;
             _this.name = name || _this._getName(src);
             _this.video = _this._getVideo(src);
+            if (settings.poster) {
+                _this.video.poster = settings.poster;
+            }
             if (settings.autoPlay !== undefined) {
                 _this.video.autoplay = settings.autoPlay;
             }
             if (settings.loop !== undefined) {
                 _this.video.loop = settings.loop;
             }
+            _this.video.setAttribute("playsinline", "");
             _this.video.addEventListener("canplay", _this._createInternalTexture);
             _this.video.addEventListener("paused", _this._updateInternalTexture);
             _this.video.addEventListener("seeked", _this._updateInternalTexture);
@@ -64383,6 +64459,16 @@ var BABYLON;
             }
             return _this;
         }
+        Object.defineProperty(VideoTexture.prototype, "onUserActionRequestedObservable", {
+            get: function () {
+                if (!this._onUserActionRequestedObservable) {
+                    this._onUserActionRequestedObservable = new BABYLON.Observable();
+                }
+                return this._onUserActionRequestedObservable;
+            },
+            enumerable: true,
+            configurable: true
+        });
         VideoTexture.prototype._getName = function (src) {
             if (src instanceof HTMLVideoElement) {
                 return src.currentSrc;
@@ -64453,6 +64539,10 @@ var BABYLON;
         };
         VideoTexture.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
+            if (this._onUserActionRequestedObservable) {
+                this._onUserActionRequestedObservable.clear();
+                this._onUserActionRequestedObservable = null;
+            }
             this.video.removeEventListener("canplay", this._createInternalTexture);
             this.video.removeEventListener("paused", this._updateInternalTexture);
             this.video.removeEventListener("seeked", this._updateInternalTexture);
@@ -88009,6 +88099,10 @@ var BABYLON;
                         return;
                     }
                 }
+                var pointerEvent = (prePointerInfo.event);
+                if (originalScene.isPointerCaptured(pointerEvent.pointerId)) {
+                    return;
+                }
                 var utilityScenePick = prePointerInfo.ray ? _this.utilityLayerScene.pickWithRay(prePointerInfo.ray) : _this.utilityLayerScene.pick(originalScene.pointerX, originalScene.pointerY);
                 if (!prePointerInfo.ray && utilityScenePick) {
                     prePointerInfo.ray = utilityScenePick.ray;
@@ -88020,7 +88114,6 @@ var BABYLON;
                     if (!prePointerInfo.skipOnPointerObservable) {
                         _this.utilityLayerScene.onPointerObservable.notifyObservers(new BABYLON.PointerInfo(prePointerInfo.type, prePointerInfo.event, utilityScenePick));
                     }
-                    var pointerEvent = (prePointerInfo.event);
                     if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && _this._pointerCaptures[pointerEvent.pointerId]) {
                         _this._pointerCaptures[pointerEvent.pointerId] = false;
                     }
@@ -88037,40 +88130,40 @@ var BABYLON;
                 }
                 else {
                     var originalScenePick = prePointerInfo.ray ? originalScene.pickWithRay(prePointerInfo.ray) : originalScene.pick(originalScene.pointerX, originalScene.pointerY);
-                    var pointerEvent = (prePointerInfo.event);
+                    var pointerEvent_1 = (prePointerInfo.event);
                     // If the layer can be occluded by the original scene, only fire pointer events to the first layer that hit they ray
                     if (originalScenePick && utilityScenePick) {
                         // No pick in utility scene
-                        if (utilityScenePick.distance === 0) {
+                        if (utilityScenePick.distance === 0 && originalScenePick.pickedMesh) {
                             if (_this.mainSceneTrackerPredicate && _this.mainSceneTrackerPredicate(originalScenePick.pickedMesh)) {
                                 // We touched an utility mesh present in the main scene
-                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent);
+                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent_1);
                                 prePointerInfo.skipOnPointerObservable = true;
                             }
                             else if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERDOWN) {
-                                _this._pointerCaptures[pointerEvent.pointerId] = true;
+                                _this._pointerCaptures[pointerEvent_1.pointerId] = true;
                             }
                         }
-                        // We pick something in utility scene or the pick in utility is closer than the one in main scene
-                        if (!_this._pointerCaptures[pointerEvent.pointerId] && (utilityScenePick.distance < originalScenePick.distance || originalScenePick.distance === 0)) {
-                            _this._notifyObservers(prePointerInfo, utilityScenePick, pointerEvent);
+                        else if (!_this._pointerCaptures[pointerEvent_1.pointerId] && (utilityScenePick.distance < originalScenePick.distance || originalScenePick.distance === 0)) {
+                            // We pick something in utility scene or the pick in utility is closer than the one in main scene
+                            _this._notifyObservers(prePointerInfo, utilityScenePick, pointerEvent_1);
                             prePointerInfo.skipOnPointerObservable = utilityScenePick.distance > 0;
                         }
-                        else if (!_this._pointerCaptures[pointerEvent.pointerId] && (utilityScenePick.distance > originalScenePick.distance)) {
+                        else if (!_this._pointerCaptures[pointerEvent_1.pointerId] && (utilityScenePick.distance > originalScenePick.distance)) {
                             // We have a pick in both scenes but main is closer than utility
                             // We touched an utility mesh present in the main scene
                             if (_this.mainSceneTrackerPredicate && _this.mainSceneTrackerPredicate(originalScenePick.pickedMesh)) {
-                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent);
+                                _this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent_1);
                                 prePointerInfo.skipOnPointerObservable = true;
                             }
-                            else if (_this._lastPointerEvents[pointerEvent.pointerId]) {
+                            else if (_this._lastPointerEvents[pointerEvent_1.pointerId]) {
                                 // We need to send a last pointerup to the utilityLayerScene to make sure animations can complete
-                                _this.onPointerOutObservable.notifyObservers(pointerEvent.pointerId);
-                                delete _this._lastPointerEvents[pointerEvent.pointerId];
+                                _this.onPointerOutObservable.notifyObservers(pointerEvent_1.pointerId);
+                                delete _this._lastPointerEvents[pointerEvent_1.pointerId];
                             }
                         }
-                        if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && _this._pointerCaptures[pointerEvent.pointerId]) {
-                            _this._pointerCaptures[pointerEvent.pointerId] = false;
+                        if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && _this._pointerCaptures[pointerEvent_1.pointerId]) {
+                            _this._pointerCaptures[pointerEvent_1.pointerId] = false;
                         }
                     }
                 }
@@ -99268,7 +99361,9 @@ var BABYLON;
         NullEngine.prototype._bindTextureDirectly = function (target, texture) {
             if (this._boundTexturesCache[this._activeChannel] !== texture) {
                 this._boundTexturesCache[this._activeChannel] = texture;
+                return true;
             }
+            return false;
         };
         NullEngine.prototype._bindTexture = function (channel, texture) {
             if (channel < 0) {
@@ -100947,7 +101042,7 @@ var BABYLON;
                 }
             }
             this._uniformBuffer.update();
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         };
         /**
          * Dispose the material.
@@ -101815,7 +101910,7 @@ var BABYLON;
             options.loop = options.loop === undefined ? true : Boolean(options.loop);
             options.size = Math.abs(options.size) || (scene.activeCamera ? scene.activeCamera.maxZ * 0.48 : 1000);
             // create
-            var tempOptions = { loop: options.loop, autoPlay: options.autoPlay, autoUpdateTexture: true };
+            var tempOptions = { loop: options.loop, autoPlay: options.autoPlay, autoUpdateTexture: true, poster: options.poster };
             var material = _this._material = new BABYLON.BackgroundMaterial(name + "_material", scene);
             var texture = _this._videoTexture = new BABYLON.VideoTexture(name + "_texture", urlsOrVideo, scene, false, false, BABYLON.Texture.TRILINEAR_SAMPLINGMODE, tempOptions);
             _this._mesh = BABYLON.MeshBuilder.CreateIcoSphere(name + "_mesh", {

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

@@ -2400,6 +2400,26 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     /**
+     * Class used to create an interactable object. It's a 3D button using a mesh coming from the current scene
+     */
+    class MeshButton3D extends Button3D {
+        /** @hidden */
+        protected _currentMesh: Mesh;
+        /**
+         * Creates a new 3D button based on a mesh
+         * @param mesh mesh to become a 3D button
+         * @param name defines the control name
+         */
+        constructor(mesh: Mesh, name?: string);
+        protected _getTypeName(): string;
+        protected _createNode(scene: Scene): TransformNode;
+        protected _affectMaterial(mesh: AbstractMesh): void;
+    }
+}
+
+
+declare module BABYLON.GUI {
+    /**
      * Class used to create a holographic button in 3D
      */
     class HolographicButton extends Button3D {

+ 73 - 5
dist/preview release/gui/babylon.gui.js

@@ -7990,6 +7990,74 @@ var BABYLON;
     var GUI;
     (function (GUI) {
         /**
+         * Class used to create an interactable object. It's a 3D button using a mesh coming from the current scene
+         */
+        var MeshButton3D = /** @class */ (function (_super) {
+            __extends(MeshButton3D, _super);
+            /**
+             * Creates a new 3D button based on a mesh
+             * @param mesh mesh to become a 3D button
+             * @param name defines the control name
+             */
+            function MeshButton3D(mesh, name) {
+                var _this = _super.call(this, name) || this;
+                _this._currentMesh = mesh;
+                /**
+                 * Provides a default behavior on hover/out & up/down
+                 * Override those function to create your own desired behavior specific to your mesh
+                 */
+                _this.pointerEnterAnimation = function () {
+                    if (!_this.mesh) {
+                        return;
+                    }
+                    _this.mesh.scaling.scaleInPlace(1.1);
+                };
+                _this.pointerOutAnimation = function () {
+                    if (!_this.mesh) {
+                        return;
+                    }
+                    _this.mesh.scaling.scaleInPlace(1.0 / 1.1);
+                };
+                _this.pointerDownAnimation = function () {
+                    if (!_this.mesh) {
+                        return;
+                    }
+                    _this.mesh.scaling.scaleInPlace(0.95);
+                };
+                _this.pointerUpAnimation = function () {
+                    if (!_this.mesh) {
+                        return;
+                    }
+                    _this.mesh.scaling.scaleInPlace(1.0 / 0.95);
+                };
+                return _this;
+            }
+            MeshButton3D.prototype._getTypeName = function () {
+                return "MeshButton3D";
+            };
+            // Mesh association
+            MeshButton3D.prototype._createNode = function (scene) {
+                var _this = this;
+                this._currentMesh.getChildMeshes().forEach(function (mesh) {
+                    mesh.metadata = _this;
+                });
+                return this._currentMesh;
+            };
+            MeshButton3D.prototype._affectMaterial = function (mesh) {
+            };
+            return MeshButton3D;
+        }(GUI.Button3D));
+        GUI.MeshButton3D = MeshButton3D;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));
+
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
+        /**
          * Class used to create a holographic button in 3D
          */
         var HolographicButton = /** @class */ (function (_super) {
@@ -8544,11 +8612,12 @@ var BABYLON;
                 configurable: true
             });
             SpherePanel.prototype._mapGridNode = function (control, nodePosition) {
-                var newPos = this._sphericalMapping(nodePosition);
                 var mesh = control.mesh;
                 if (!mesh) {
                     return;
                 }
+                var newPos = this._sphericalMapping(nodePosition);
+                control.position = newPos;
                 switch (this.orientation) {
                     case GUI.Container3D.FACEORIGIN_ORIENTATION:
                         mesh.lookAt(new BABYLON.Vector3(-newPos.x, -newPos.y, -newPos.z));
@@ -8563,7 +8632,6 @@ var BABYLON;
                         mesh.lookAt(new BABYLON.Vector3(0, 0, -1));
                         break;
                 }
-                control.position = newPos;
             };
             SpherePanel.prototype._sphericalMapping = function (source) {
                 var newPos = new BABYLON.Vector3(0, 0, this._radius);
@@ -8597,6 +8665,7 @@ var BABYLON;
                 if (!mesh) {
                     return;
                 }
+                control.position = nodePosition.clone();
                 switch (this.orientation) {
                     case GUI.Container3D.FACEORIGIN_ORIENTATION:
                     case GUI.Container3D.FACEFORWARD_ORIENTATION:
@@ -8607,7 +8676,6 @@ var BABYLON;
                         mesh.lookAt(new BABYLON.Vector3(0, 0, 1));
                         break;
                 }
-                control.position = nodePosition.clone();
             };
             return PlanePanel;
         }(GUI.VolumeBasedPanel));
@@ -8764,11 +8832,12 @@ var BABYLON;
                 configurable: true
             });
             CylinderPanel.prototype._mapGridNode = function (control, nodePosition) {
-                var newPos = this._cylindricalMapping(nodePosition);
                 var mesh = control.mesh;
                 if (!mesh) {
                     return;
                 }
+                var newPos = this._cylindricalMapping(nodePosition);
+                control.position = newPos;
                 switch (this.orientation) {
                     case GUI.Container3D.FACEORIGIN_ORIENTATION:
                         mesh.lookAt(new BABYLON.Vector3(-newPos.x, 0, -newPos.z));
@@ -8783,7 +8852,6 @@ var BABYLON;
                         mesh.lookAt(new BABYLON.Vector3(0, 0, -1));
                         break;
                 }
-                control.position = newPos;
             };
             CylinderPanel.prototype._cylindricalMapping = function (source) {
                 var newPos = new BABYLON.Vector3(0, source.y, this._radius);

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 2
dist/preview release/gui/babylon.gui.min.js


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

@@ -2405,6 +2405,26 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     /**
+     * Class used to create an interactable object. It's a 3D button using a mesh coming from the current scene
+     */
+    class MeshButton3D extends Button3D {
+        /** @hidden */
+        protected _currentMesh: Mesh;
+        /**
+         * Creates a new 3D button based on a mesh
+         * @param mesh mesh to become a 3D button
+         * @param name defines the control name
+         */
+        constructor(mesh: Mesh, name?: string);
+        protected _getTypeName(): string;
+        protected _createNode(scene: Scene): TransformNode;
+        protected _affectMaterial(mesh: AbstractMesh): void;
+    }
+}
+
+
+declare module BABYLON.GUI {
+    /**
      * Class used to create a holographic button in 3D
      */
     class HolographicButton extends Button3D {

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 2
dist/preview release/inspector/babylon.inspector.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 55 - 55
dist/preview release/viewer/babylon.viewer.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 144 - 49
dist/preview release/viewer/babylon.viewer.max.js


+ 3 - 4
gui/src/3D/controls/cylinderPanel.ts

@@ -27,12 +27,13 @@ module BABYLON.GUI {
         }              
 
         protected _mapGridNode(control: Control3D, nodePosition: Vector3) {            
-            let newPos = this._cylindricalMapping(nodePosition);
             let mesh = control.mesh;
 
             if (!mesh) {
                 return;
             }
+            let newPos = this._cylindricalMapping(nodePosition);
+            control.position = newPos;
 
             switch (this.orientation) {
                 case Container3D.FACEORIGIN_ORIENTATION:
@@ -47,9 +48,7 @@ module BABYLON.GUI {
                 case Container3D.FACEFORWARDREVERSED_ORIENTATION:
                     mesh.lookAt(new BABYLON.Vector3(0, 0, -1));
                     break;
-            }
-            
-            control.position = newPos;
+            }            
         }
 
         private _cylindricalMapping(source: Vector3)

+ 2 - 1
gui/src/3D/controls/planePanel.ts

@@ -12,6 +12,8 @@ module BABYLON.GUI {
                 return;
             }
 
+            control.position = nodePosition.clone();
+
             switch (this.orientation) {
                 case Container3D.FACEORIGIN_ORIENTATION:
                 case Container3D.FACEFORWARD_ORIENTATION:
@@ -23,7 +25,6 @@ module BABYLON.GUI {
                     break;
             }
             
-            control.position = nodePosition.clone();
         }
     }
 }

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

@@ -27,13 +27,15 @@ module BABYLON.GUI {
         }              
 
         protected _mapGridNode(control: Control3D, nodePosition: Vector3) {            
-            let newPos = this._sphericalMapping(nodePosition);
             let mesh = control.mesh;
 
             if (!mesh) {
                 return;
             }
 
+            let newPos = this._sphericalMapping(nodePosition);
+            control.position = newPos;
+
             switch (this.orientation) {
                 case Container3D.FACEORIGIN_ORIENTATION:
                     mesh.lookAt(new BABYLON.Vector3(-newPos.x, -newPos.y, -newPos.z));
@@ -47,9 +49,7 @@ module BABYLON.GUI {
                 case Container3D.FACEFORWARDREVERSED_ORIENTATION:
                     mesh.lookAt(new BABYLON.Vector3(0, 0, -1));
                     break;
-            }
-            
-            control.position = newPos;
+            }           
         }
 
         private _sphericalMapping(source: Vector3)

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

@@ -242,6 +242,7 @@
                         system.clone(system.name, this);
                     }
                 }
+                this.refreshBoundingInfo();
                 this.computeWorldMatrix(true);
             }
 

+ 9 - 6
src/Rendering/babylon.utilityLayerRenderer.ts

@@ -57,6 +57,11 @@ module BABYLON {
                     }
                 }
 
+                let pointerEvent = <PointerEvent>(prePointerInfo.event);
+                if (originalScene!.isPointerCaptured(pointerEvent.pointerId)) {
+                    return;
+                }
+
                 var utilityScenePick = prePointerInfo.ray ? this.utilityLayerScene.pickWithRay(prePointerInfo.ray) : this.utilityLayerScene.pick(originalScene.pointerX, originalScene.pointerY);
                 if(!prePointerInfo.ray && utilityScenePick){
                     prePointerInfo.ray = utilityScenePick.ray;
@@ -70,7 +75,6 @@ module BABYLON {
                     if(!prePointerInfo.skipOnPointerObservable){
                         this.utilityLayerScene.onPointerObservable.notifyObservers(new PointerInfo(prePointerInfo.type, prePointerInfo.event, utilityScenePick))
                     }
-                    let pointerEvent = <PointerEvent>(prePointerInfo.event);
                     if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERUP && this._pointerCaptures[pointerEvent.pointerId]) {
                         this._pointerCaptures[pointerEvent.pointerId] = false;
                     }
@@ -92,8 +96,9 @@ module BABYLON {
 
                     // If the layer can be occluded by the original scene, only fire pointer events to the first layer that hit they ray
                     if (originalScenePick && utilityScenePick){
+
                         // No pick in utility scene
-                        if (utilityScenePick.distance === 0) {
+                        if (utilityScenePick.distance === 0 && originalScenePick.pickedMesh) {
                             if (this.mainSceneTrackerPredicate && this.mainSceneTrackerPredicate(originalScenePick.pickedMesh)) {
                                 // We touched an utility mesh present in the main scene
                                 this._notifyObservers(prePointerInfo, originalScenePick, pointerEvent);
@@ -101,10 +106,8 @@ module BABYLON {
                             } else if (prePointerInfo.type === BABYLON.PointerEventTypes.POINTERDOWN) {
                                 this._pointerCaptures[pointerEvent.pointerId] = true;
                             } 
-                        }
-
-                        // We pick something in utility scene or the pick in utility is closer than the one in main scene
-                        if (!this._pointerCaptures[pointerEvent.pointerId] && (utilityScenePick.distance < originalScenePick.distance || originalScenePick.distance === 0)){
+                        } else if (!this._pointerCaptures[pointerEvent.pointerId] && (utilityScenePick.distance < originalScenePick.distance || originalScenePick.distance === 0)){
+                            // We pick something in utility scene or the pick in utility is closer than the one in main scene
                             this._notifyObservers(prePointerInfo, utilityScenePick, pointerEvent);
                             prePointerInfo.skipOnPointerObservable = utilityScenePick.distance > 0;
                         } else if (!this._pointerCaptures[pointerEvent.pointerId] && (utilityScenePick.distance > originalScenePick.distance)) {