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

Merge branch 'master' into xrCameraMovement

Trevor Baron пре 6 година
родитељ
комит
258f193cfe
44 измењених фајлова са 27848 додато и 27367 уклоњено
  1. 14313 14242
      Playground/babylon.d.txt
  2. BIN
      Playground/textures/gui/backgroundImage-vertical.png
  3. BIN
      Playground/textures/gui/backgroundImage.png
  4. BIN
      Playground/textures/gui/thumb.png
  5. BIN
      Playground/textures/gui/valueImage-vertical.png
  6. BIN
      Playground/textures/gui/valueImage.png
  7. 14 16
      Tools/Gulp/gulpfile.js
  8. 11013 10959
      dist/preview release/babylon.d.ts
  9. 1 1
      dist/preview release/babylon.js
  10. 330 236
      dist/preview release/babylon.max.js
  11. 330 236
      dist/preview release/babylon.no-module.max.js
  12. 1 1
      dist/preview release/babylon.worker.js
  13. 332 238
      dist/preview release/es6.js
  14. 20 3
      dist/preview release/gui/babylon.gui.d.ts
  15. 1 1
      dist/preview release/gui/babylon.gui.js
  16. 1 1
      dist/preview release/gui/babylon.gui.min.js
  17. 1 1
      dist/preview release/gui/babylon.gui.min.js.map
  18. 41 6
      dist/preview release/gui/babylon.gui.module.d.ts
  19. 3 0
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  20. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  21. 3 0
      dist/preview release/loaders/babylon.glTFFileLoader.js
  22. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  23. 3 0
      dist/preview release/loaders/babylonjs.loaders.js
  24. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  25. 1 22
      dist/preview release/viewer/babylon.viewer.d.ts
  26. 1 1
      dist/preview release/viewer/babylon.viewer.js
  27. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  28. 2 28
      dist/preview release/viewer/babylon.viewer.module.d.ts
  29. 25 0
      dist/preview release/what's new.md
  30. 20 3
      gui/src/2D/controls/baseSlider.ts
  31. 31 0
      gui/src/2D/controls/grid.ts
  32. 23 7
      gui/src/2D/controls/imageBasedSlider.ts
  33. 570 559
      gui/src/2D/controls/inputText.ts
  34. 1 16
      gui/src/2D/controls/slider.ts
  35. 1 1
      src/Cameras/XR/babylon.webXRInput.ts
  36. 37 31
      src/Culling/babylon.ray.ts
  37. 0 12
      src/Engine/babylon.engine.ts
  38. 6 35
      src/Lights/Shadows/babylon.shadowGenerator.ts
  39. 53 20
      src/Materials/babylon.material.ts
  40. 44 15
      src/Math/babylon.math.ts
  41. 4 1
      src/Particles/babylon.gpuParticleSystem.ts
  42. 28 87
      src/babylon.scene.ts
  43. BIN
      tests/validation/ReferenceImages/Sliders.png
  44. 589 583
      tests/validation/config.json

Разлика између датотеке није приказан због своје велике величине
+ 14313 - 14242
Playground/babylon.d.txt


BIN
Playground/textures/gui/backgroundImage-vertical.png


BIN
Playground/textures/gui/backgroundImage.png


BIN
Playground/textures/gui/thumb.png


BIN
Playground/textures/gui/valueImage-vertical.png


BIN
Playground/textures/gui/valueImage.png


+ 14 - 16
Tools/Gulp/gulpfile.js

@@ -355,15 +355,13 @@ gulp.task("typescript-compile", function() {
             summarizeFailureOutput: true
         }));
 
-    //If this gulp task is running on travis, file the build!
-    if (process.env.TRAVIS) {
-        tsResult.once("error", function() {
-            tsResult.once("finish", function() {
-                console.log("Typescript compile failed");
-                process.exit(1);
-            });
+    tsResult.once("error", function(err) {
+        tsResult.once("finish", function() {
+            console.log("Typescript compile failed");
+            console.error(err);
+            process.exit(1);
         });
-    }
+    });
 
     return merge2([
         tsResult.dts
@@ -891,14 +889,13 @@ gulp.task("modules-compile", function() {
         .pipe(tsProject());
 
     // If this gulp task is running on travis
-    if (process.env.TRAVIS) {
-        tsResult.once("error", function() {
-            tsResult.once("finish", function() {
-                console.log("Typescript compile failed");
-                process.exit(1);
-            });
+    tsResult.once("error", function(err) {
+        tsResult.once("finish", function() {
+            console.log("Typescript compile failed");
+            console.error(err);
+            process.exit(1);
         });
-    }
+    });
 
     return merge2([
         tsResult.dts
@@ -1205,8 +1202,9 @@ gulp.task("tests-unit-transpile", function(done) {
         .pipe(tsProject());
 
     tsResult.once("error", function() {
-        tsResult.once("finish", function() {
+        tsResult.once("finish", function(err) {
             console.log("Typescript compile failed");
+            console.error(err);
             process.exit(1);
         });
     });

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


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


+ 330 - 236
dist/preview release/babylon.max.js

@@ -5477,7 +5477,7 @@ var BABYLON;
         };
         /**
          * Returns a new Vector3 set from the index "offset" of the given Float32Array
-         * This function is deprecated.  Use FromArray instead
+         * This function is deprecated. Use FromArray instead
          * @param array defines the source array
          * @param offset defines the offset in the source array
          * @returns the new Vector3
@@ -5825,6 +5825,15 @@ var BABYLON;
             matrix.multiplyToRef(viewportMatrix, matrix);
             return Vector3.TransformCoordinates(vector, matrix);
         };
+        /** @hidden */
+        Vector3.UnprojectFromInvertedMatrixToRef = function (source, matrix, result) {
+            Vector3.TransformCoordinatesToRef(source, matrix, result);
+            var m = matrix.m;
+            var num = source.x * m[3] + source.y * m[7] + source.z * m[11] + m[15];
+            if (BABYLON.Scalar.WithinEpsilon(num, 1.0)) {
+                result.scaleInPlace(1.0 / num);
+            }
+        };
         /**
          * Unproject from screen space to object space
          * @param source defines the screen space Vector3 to use
@@ -5840,12 +5849,8 @@ var BABYLON;
             matrix.invert();
             source.x = source.x / viewportWidth * 2 - 1;
             source.y = -(source.y / viewportHeight * 2 - 1);
-            var vector = Vector3.TransformCoordinates(source, matrix);
-            var m = matrix.m;
-            var num = source.x * m[3] + source.y * m[7] + source.z * m[11] + m[15];
-            if (BABYLON.Scalar.WithinEpsilon(num, 1.0)) {
-                vector = vector.scale(1.0 / num);
-            }
+            var vector = new Vector3();
+            Vector3.UnprojectFromInvertedMatrixToRef(source, matrix, vector);
             return vector;
         };
         /**
@@ -5897,12 +5902,36 @@ var BABYLON;
             screenSource.x = sourceX / viewportWidth * 2 - 1;
             screenSource.y = -(sourceY / viewportHeight * 2 - 1);
             screenSource.z = 2 * sourceZ - 1.0;
-            Vector3.TransformCoordinatesToRef(screenSource, matrix, result);
-            var m = matrix.m;
-            var num = screenSource.x * m[3] + screenSource.y * m[7] + screenSource.z * m[11] + m[15];
-            if (BABYLON.Scalar.WithinEpsilon(num, 1.0)) {
-                result.scaleInPlace(1.0 / num);
-            }
+            Vector3.UnprojectFromInvertedMatrixToRef(screenSource, matrix, result);
+        };
+        /**
+          * Unproject a ray from screen space to object space
+          * @param sourceX defines the screen space x coordinate to use
+          * @param sourceY defines the screen space y coordinate to use
+          * @param viewportWidth defines the current width of the viewport
+          * @param viewportHeight defines the current height of the viewport
+          * @param world defines the world matrix to use (can be set to Identity to go to world space)
+          * @param view defines the view matrix to use
+          * @param projection defines the projection matrix to use
+          * @param ray defines the Ray where to store the result
+          */
+        Vector3.UnprojectRayToRef = function (sourceX, sourceY, viewportWidth, viewportHeight, world, view, projection, ray) {
+            var matrix = MathTmp.Matrix[0];
+            world.multiplyToRef(view, matrix);
+            matrix.multiplyToRef(projection, matrix);
+            matrix.invert();
+            var nearScreenSource = MathTmp.Vector3[0];
+            nearScreenSource.x = sourceX / viewportWidth * 2 - 1;
+            nearScreenSource.y = -(sourceY / viewportHeight * 2 - 1);
+            nearScreenSource.z = -1.0;
+            var farScreenSource = MathTmp.Vector3[1].copyFromFloats(nearScreenSource.x, nearScreenSource.y, 1.0);
+            var nearVec3 = MathTmp.Vector3[2];
+            var farVec3 = MathTmp.Vector3[3];
+            Vector3.UnprojectFromInvertedMatrixToRef(nearScreenSource, matrix, nearVec3);
+            Vector3.UnprojectFromInvertedMatrixToRef(farScreenSource, matrix, farVec3);
+            ray.origin.copyFrom(nearVec3);
+            farVec3.subtractToRef(nearVec3, ray.direction);
+            ray.direction.normalize();
         };
         /**
          * Gets the minimal coordinate values between two Vector3
@@ -13236,24 +13265,6 @@ var BABYLON;
         Engine.prototype.getCaps = function () {
             return this._caps;
         };
-        Object.defineProperty(Engine.prototype, "drawCalls", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("drawCalls is deprecated. Please use SceneInstrumentation class");
-                return 0;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(Engine.prototype, "drawCallsPerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("drawCallsPerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
         /**
          * Gets the current depth function
          * @returns a number defining the depth function
@@ -25614,6 +25625,10 @@ var BABYLON;
             */
             _this.onAfterStepObservable = new BABYLON.Observable();
             /**
+             * An event triggered when the activeCamera property is updated
+             */
+            _this.onActiveCameraChanged = new BABYLON.Observable();
+            /**
              * This Observable will be triggered before rendering each renderingGroup of each rendered camera.
              * The RenderinGroupInfo class contains all the information about the context in which the observable is called
              * If you wish to register an Observer only for a given set of renderingGroup, use the mask with a combination of the renderingGroup index elevated to the power of two (1 for renderingGroup 0, 2 for renderingrOup1, 4 for 2 and 8 for 3)
@@ -26252,6 +26267,21 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Scene.prototype, "activeCamera", {
+            /** Gets or sets the current active camera */
+            get: function () {
+                return this._activeCamera;
+            },
+            set: function (value) {
+                if (value === this._activeCamera) {
+                    return;
+                }
+                this._activeCamera = value;
+                this.onActiveCameraChanged.notifyObservers(this);
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Scene.prototype, "defaultMaterial", {
             /** The default material used on meshes when no material is affected */
             get: function () {
@@ -26553,48 +26583,6 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
-        /** @hidden */
-        Scene.prototype.getInterFramePerfCounter = function () {
-            BABYLON.Tools.Warn("getInterFramePerfCounter is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "interFramePerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("interFramePerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        /** @hidden */
-        Scene.prototype.getLastFrameDuration = function () {
-            BABYLON.Tools.Warn("getLastFrameDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "lastFramePerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("lastFramePerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        /** @hidden */
-        Scene.prototype.getEvaluateActiveMeshesDuration = function () {
-            BABYLON.Tools.Warn("getEvaluateActiveMeshesDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "evaluateActiveMeshesDurationPerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("evaluateActiveMeshesDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
         /**
          * Gets the array of active meshes
          * @returns an array of AbstractMesh
@@ -26602,53 +26590,6 @@ var BABYLON;
         Scene.prototype.getActiveMeshes = function () {
             return this._activeMeshes;
         };
-        /** @hidden */
-        Scene.prototype.getRenderTargetsDuration = function () {
-            BABYLON.Tools.Warn("getRenderTargetsDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        /** @hidden */
-        Scene.prototype.getRenderDuration = function () {
-            BABYLON.Tools.Warn("getRenderDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "renderDurationPerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("renderDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        /** @hidden */
-        Scene.prototype.getParticlesDuration = function () {
-            BABYLON.Tools.Warn("getParticlesDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "particlesDurationPerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("particlesDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        /** @hidden */
-        Scene.prototype.getSpritesDuration = function () {
-            BABYLON.Tools.Warn("getSpritesDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "spriteDuractionPerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("spriteDuractionPerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
         /**
          * Gets the animation ratio (which is 1.0 is the scene renders at 60fps and 2 if the scene renders at 30fps, etc.)
          * @returns a number
@@ -27135,6 +27076,7 @@ var BABYLON;
                     canvas.focus();
                 }
                 _this._initClickEvent(_this.onPrePointerObservable, _this.onPointerObservable, evt, function (clickInfo, pickResult) {
+                    _this._pointerCaptures[evt.pointerId] = false;
                     // PreObservable support
                     if (_this.onPrePointerObservable.hasObservers()) {
                         if (!clickInfo.ignore) {
@@ -27158,7 +27100,6 @@ var BABYLON;
                     if (!_this.cameraToUseForPointers && !_this.activeCamera) {
                         return;
                     }
-                    _this._pointerCaptures[evt.pointerId] = false;
                     if (!_this.pointerUpPredicate) {
                         _this.pointerUpPredicate = function (mesh) {
                             return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.isEnabled();
@@ -29530,6 +29471,7 @@ var BABYLON;
             this.onPointerObservable.clear();
             this.onPreKeyboardObservable.clear();
             this.onKeyboardObservable.clear();
+            this.onActiveCameraChanged.clear();
             this.detachControl();
             // Detach cameras
             var canvas = this._engine.getRenderingCanvas();
@@ -29703,7 +29645,7 @@ var BABYLON;
             // Moving coordinates to local viewport world
             x = x / this._engine.getHardwareScalingLevel() - viewport.x;
             y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
-            result.update(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), cameraViewSpace ? BABYLON.Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
+            result.update(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.IdentityReadOnly, cameraViewSpace ? BABYLON.Matrix.IdentityReadOnly : camera.getViewMatrix(), camera.getProjectionMatrix());
             return this;
         };
         /**
@@ -37295,20 +37237,27 @@ var BABYLON;
          * @param flag defines a flag used to determine which parts of the material have to be marked as dirty
          */
         Material.prototype.markAsDirty = function (flag) {
+            if (this.getScene().blockMaterialDirtyMechanism) {
+                return;
+            }
+            Material._DirtyCallbackArray.length = 0;
             if (flag & Material.TextureDirtyFlag) {
-                this._markAllSubMeshesAsTexturesDirty();
+                Material._DirtyCallbackArray.push(Material._TextureDirtyCallBack);
             }
             if (flag & Material.LightDirtyFlag) {
-                this._markAllSubMeshesAsLightsDirty();
+                Material._DirtyCallbackArray.push(Material._LightsDirtyCallBack);
             }
             if (flag & Material.FresnelDirtyFlag) {
-                this._markAllSubMeshesAsFresnelDirty();
+                Material._DirtyCallbackArray.push(Material._FresnelDirtyCallBack);
             }
             if (flag & Material.AttributesDirtyFlag) {
-                this._markAllSubMeshesAsAttributesDirty();
+                Material._DirtyCallbackArray.push(Material._AttributeDirtyCallBack);
             }
             if (flag & Material.MiscDirtyFlag) {
-                this._markAllSubMeshesAsMiscDirty();
+                Material._DirtyCallbackArray.push(Material._MiscDirtyCallBack);
+            }
+            if (Material._DirtyCallbackArray.length) {
+                this._markAllSubMeshesAsDirty(Material._RunDirtyCallBacks);
             }
             this.getScene().resetCachedMaterial();
         };
@@ -37317,13 +37266,17 @@ var BABYLON;
          * @param func defines a function which checks material defines against the submeshes
          */
         Material.prototype._markAllSubMeshesAsDirty = function (func) {
-            for (var _i = 0, _a = this.getScene().meshes; _i < _a.length; _i++) {
-                var mesh = _a[_i];
+            if (this.getScene().blockMaterialDirtyMechanism) {
+                return;
+            }
+            var meshes = this.getScene().meshes;
+            for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                var mesh = meshes_1[_i];
                 if (!mesh.subMeshes) {
                     continue;
                 }
-                for (var _b = 0, _c = mesh.subMeshes; _b < _c.length; _b++) {
-                    var subMesh = _c[_b];
+                for (var _a = 0, _b = mesh.subMeshes; _a < _b.length; _a++) {
+                    var subMesh = _b[_a];
                     if (subMesh.getMaterial() !== this) {
                         continue;
                     }
@@ -37338,55 +37291,49 @@ var BABYLON;
          * Indicates that image processing needs to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsImageProcessingDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsImageProcessingDirty(); });
+            this._markAllSubMeshesAsDirty(Material._ImageProcessingDirtyCallBack);
         };
         /**
          * Indicates that textures need to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsTexturesDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsTexturesDirty(); });
+            this._markAllSubMeshesAsDirty(Material._TextureDirtyCallBack);
         };
         /**
          * Indicates that fresnel needs to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsFresnelDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsFresnelDirty(); });
+            this._markAllSubMeshesAsDirty(Material._FresnelDirtyCallBack);
         };
         /**
          * Indicates that fresnel and misc need to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsFresnelAndMiscDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) {
-                defines.markAsFresnelDirty();
-                defines.markAsMiscDirty();
-            });
+            this._markAllSubMeshesAsDirty(Material._FresnelAndMiscDirtyCallBack);
         };
         /**
          * Indicates that lights need to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsLightsDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsLightDirty(); });
+            this._markAllSubMeshesAsDirty(Material._LightsDirtyCallBack);
         };
         /**
          * Indicates that attributes need to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsAttributesDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsAttributesDirty(); });
+            this._markAllSubMeshesAsDirty(Material._AttributeDirtyCallBack);
         };
         /**
          * Indicates that misc needs to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsMiscDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsMiscDirty(); });
+            this._markAllSubMeshesAsDirty(Material._MiscDirtyCallBack);
         };
         /**
          * Indicates that textures and misc need to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsTexturesAndMiscDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) {
-                defines.markAsTexturesDirty();
-                defines.markAsMiscDirty();
-            });
+            this._markAllSubMeshesAsDirty(Material._TextureAndMiscDirtyCallBack);
         };
         /**
          * Disposes the material
@@ -37414,8 +37361,8 @@ var BABYLON;
                 }
                 else {
                     var meshes = scene.meshes;
-                    for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
-                        var mesh = meshes_1[_i];
+                    for (var _i = 0, meshes_2 = meshes; _i < meshes_2.length; _i++) {
+                        var mesh = meshes_2[_i];
                         if (mesh.material === this) {
                             mesh.material = null;
                             this.releaseVertexArrayObject(mesh, forceDisposeEffect);
@@ -37554,6 +37501,27 @@ var BABYLON;
          * The all dirty flag value
          */
         Material.AllDirtyFlag = 31;
+        Material._ImageProcessingDirtyCallBack = function (defines) { return defines.markAsImageProcessingDirty(); };
+        Material._TextureDirtyCallBack = function (defines) { return defines.markAsTexturesDirty(); };
+        Material._FresnelDirtyCallBack = function (defines) { return defines.markAsFresnelDirty(); };
+        Material._MiscDirtyCallBack = function (defines) { return defines.markAsMiscDirty(); };
+        Material._LightsDirtyCallBack = function (defines) { return defines.markAsLightDirty(); };
+        Material._AttributeDirtyCallBack = function (defines) { return defines.markAsAttributesDirty(); };
+        Material._FresnelAndMiscDirtyCallBack = function (defines) {
+            Material._FresnelDirtyCallBack(defines);
+            Material._MiscDirtyCallBack(defines);
+        };
+        Material._TextureAndMiscDirtyCallBack = function (defines) {
+            Material._TextureDirtyCallBack(defines);
+            Material._MiscDirtyCallBack(defines);
+        };
+        Material._DirtyCallbackArray = [];
+        Material._RunDirtyCallBacks = function (defines) {
+            for (var _i = 0, _a = Material._DirtyCallbackArray; _i < _a.length; _i++) {
+                var cb = _a[_i];
+                cb(defines);
+            }
+        };
         __decorate([
             BABYLON.serialize()
         ], Material.prototype, "id", void 0);
@@ -58848,8 +58816,8 @@ var BABYLON;
          */
         Ray.prototype.intersectsBoxMinMax = function (minimum, maximum, intersectionTreshold) {
             if (intersectionTreshold === void 0) { intersectionTreshold = 0; }
-            var newMinimum = Ray._min.copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
-            var newMaximum = Ray._max.copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
+            var newMinimum = Ray.TmpVector3[0].copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
+            var newMaximum = Ray.TmpVector3[1].copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
             var d = 0.0;
             var maxValue = Number.MAX_VALUE;
             var inv;
@@ -58969,26 +58937,31 @@ var BABYLON;
          * @returns intersection information if hit
          */
         Ray.prototype.intersectsTriangle = function (vertex0, vertex1, vertex2) {
-            vertex1.subtractToRef(vertex0, Ray._edge1);
-            vertex2.subtractToRef(vertex0, Ray._edge2);
-            BABYLON.Vector3.CrossToRef(this.direction, Ray._edge2, Ray._pvec);
-            var det = BABYLON.Vector3.Dot(Ray._edge1, Ray._pvec);
+            var edge1 = Ray.TmpVector3[0];
+            var edge2 = Ray.TmpVector3[1];
+            var pvec = Ray.TmpVector3[2];
+            var tvec = Ray.TmpVector3[3];
+            var qvec = Ray.TmpVector3[4];
+            vertex1.subtractToRef(vertex0, edge1);
+            vertex2.subtractToRef(vertex0, edge2);
+            BABYLON.Vector3.CrossToRef(this.direction, edge2, pvec);
+            var det = BABYLON.Vector3.Dot(edge1, pvec);
             if (det === 0) {
                 return null;
             }
             var invdet = 1 / det;
-            this.origin.subtractToRef(vertex0, Ray._tvec);
-            var bu = BABYLON.Vector3.Dot(Ray._tvec, Ray._pvec) * invdet;
+            this.origin.subtractToRef(vertex0, tvec);
+            var bu = BABYLON.Vector3.Dot(tvec, pvec) * invdet;
             if (bu < 0 || bu > 1.0) {
                 return null;
             }
-            BABYLON.Vector3.CrossToRef(Ray._tvec, Ray._edge1, Ray._qvec);
-            var bv = BABYLON.Vector3.Dot(this.direction, Ray._qvec) * invdet;
+            BABYLON.Vector3.CrossToRef(tvec, edge1, qvec);
+            var bv = BABYLON.Vector3.Dot(this.direction, qvec) * invdet;
             if (bv < 0 || bu + bv > 1.0) {
                 return null;
             }
             //check if the distance is longer than the predefined length.
-            var distance = BABYLON.Vector3.Dot(Ray._edge2, Ray._qvec) * invdet;
+            var distance = BABYLON.Vector3.Dot(edge2, qvec) * invdet;
             if (distance > this.length) {
                 return null;
             }
@@ -59078,10 +59051,15 @@ var BABYLON;
          * @return the distance from the ray origin to the intersection point if there's intersection, or -1 if there's no intersection
          */
         Ray.prototype.intersectionSegment = function (sega, segb, threshold) {
-            var rsegb = this.origin.add(this.direction.multiplyByFloats(Ray.rayl, Ray.rayl, Ray.rayl));
-            var u = segb.subtract(sega);
-            var v = rsegb.subtract(this.origin);
-            var w = sega.subtract(this.origin);
+            var o = this.origin;
+            var u = BABYLON.Tmp.Vector3[0];
+            var rsegb = BABYLON.Tmp.Vector3[1];
+            var v = BABYLON.Tmp.Vector3[2];
+            var w = BABYLON.Tmp.Vector3[3];
+            segb.subtractToRef(sega, u);
+            this.direction.scaleToRef(Ray.rayl, v);
+            o.addToRef(v, rsegb);
+            sega.subtractToRef(o, w);
             var a = BABYLON.Vector3.Dot(u, u); // always >= 0
             var b = BABYLON.Vector3.Dot(u, v);
             var c = BABYLON.Vector3.Dot(v, v); // always >= 0
@@ -59143,8 +59121,11 @@ var BABYLON;
             sc = (Math.abs(sN) < Ray.smallnum ? 0.0 : sN / sD);
             tc = (Math.abs(tN) < Ray.smallnum ? 0.0 : tN / tD);
             // get the difference of the two closest points
-            var qtc = v.multiplyByFloats(tc, tc, tc);
-            var dP = w.add(u.multiplyByFloats(sc, sc, sc)).subtract(qtc); // = S1(sc) - S2(tc)
+            var qtc = BABYLON.Tmp.Vector3[4];
+            v.scaleToRef(tc, qtc);
+            var dP = BABYLON.Tmp.Vector3[5];
+            u.scaleToRef(sc, dP);
+            dP.addInPlace(w).subtractInPlace(qtc); // = S1(sc) - S2(tc)
             var isIntersected = (tc > 0) && (tc <= this.length) && (dP.lengthSquared() < (threshold * threshold)); // return intersection result
             if (isIntersected) {
                 return qtc.length();
@@ -59163,10 +59144,7 @@ var BABYLON;
          * @returns this ray updated
          */
         Ray.prototype.update = function (x, y, viewportWidth, viewportHeight, world, view, projection) {
-            BABYLON.Vector3.UnprojectFloatsToRef(x, y, 0, viewportWidth, viewportHeight, world, view, projection, this.origin);
-            BABYLON.Vector3.UnprojectFloatsToRef(x, y, 1, viewportWidth, viewportHeight, world, view, projection, BABYLON.Tmp.Vector3[0]);
-            BABYLON.Tmp.Vector3[0].subtractToRef(this.origin, this.direction);
-            this.direction.normalize();
+            BABYLON.Vector3.UnprojectRayToRef(x, y, viewportWidth, viewportHeight, world, view, projection, this);
             return this;
         };
         // Statics
@@ -59238,13 +59216,7 @@ var BABYLON;
                 result.length *= len;
             }
         };
-        Ray._edge1 = BABYLON.Vector3.Zero();
-        Ray._edge2 = BABYLON.Vector3.Zero();
-        Ray._pvec = BABYLON.Vector3.Zero();
-        Ray._tvec = BABYLON.Vector3.Zero();
-        Ray._qvec = BABYLON.Vector3.Zero();
-        Ray._min = BABYLON.Vector3.Zero();
-        Ray._max = BABYLON.Vector3.Zero();
+        Ray.TmpVector3 = BABYLON.Tools.BuildArray(6, BABYLON.Vector3.Zero);
         Ray.smallnum = 0.00000001;
         Ray.rayl = 10e8;
         return Ray;
@@ -66902,7 +66874,6 @@ var BABYLON;
             _this._started = false;
             _this._stopped = false;
             _this._timeDelta = 0;
-            _this._attributesStrideSize = 21;
             _this._actualFrame = 0;
             _this._rawTextureWidth = 256;
             /**
@@ -67518,6 +67489,8 @@ var BABYLON;
             }
             var engine = this._scene.getEngine();
             var data = new Array();
+            this._attributesStrideSize = 21;
+            this._targetIndex = 0;
             if (!this.isBillboardBased) {
                 this._attributesStrideSize += 3;
             }
@@ -76609,46 +76582,6 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
-        Object.defineProperty(ShadowGenerator.prototype, "useVarianceShadowMap", {
-            /**
-             * Gets if the current filter is set to VSM.
-             * DEPRECATED. Should use useExponentialShadowMap instead.
-             */
-            get: function () {
-                BABYLON.Tools.Warn("VSM are now replaced by ESM. Please use useExponentialShadowMap instead.");
-                return this.useExponentialShadowMap;
-            },
-            /**
-             * Sets the current filter is to VSM.
-             * DEPRECATED. Should use useExponentialShadowMap instead.
-             */
-            set: function (value) {
-                BABYLON.Tools.Warn("VSM are now replaced by ESM. Please use useExponentialShadowMap instead.");
-                this.useExponentialShadowMap = value;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(ShadowGenerator.prototype, "useBlurVarianceShadowMap", {
-            /**
-             * Gets if the current filter is set to blurred VSM.
-             * DEPRECATED. Should use useBlurExponentialShadowMap instead.
-             */
-            get: function () {
-                BABYLON.Tools.Warn("VSM are now replaced by ESM. Please use useBlurExponentialShadowMap instead.");
-                return this.useBlurExponentialShadowMap;
-            },
-            /**
-             * Sets the current filter is to blurred VSM.
-             * DEPRECATED. Should use useBlurExponentialShadowMap instead.
-             */
-            set: function (value) {
-                BABYLON.Tools.Warn("VSM are now replaced by ESM. Please use useBlurExponentialShadowMap instead.");
-                this.useBlurExponentialShadowMap = value;
-            },
-            enumerable: true,
-            configurable: true
-        });
         Object.defineProperty(ShadowGenerator.prototype, "useExponentialShadowMap", {
             /**
              * Gets if the current filter is set to ESM.
@@ -77037,7 +76970,7 @@ var BABYLON;
             var scene = this._scene;
             var engine = scene.getEngine();
             var material = subMesh.getMaterial();
-            if (!material) {
+            if (!material || subMesh.verticesCount === 0) {
                 return;
             }
             // Culling
@@ -77075,6 +77008,9 @@ var BABYLON;
                     var skeleton = mesh.skeleton;
                     if (skeleton.isUsingTextureForMatrices) {
                         var boneTexture = skeleton.getTransformMatrixTexture();
+                        if (!boneTexture) {
+                            return;
+                        }
                         this._effect.setTexture("boneSampler", boneTexture);
                         this._effect.setFloat("boneTextureWidth", 4.0 * (skeleton.bones.length + 1));
                     }
@@ -108609,7 +108545,7 @@ var BABYLON;
          * After initialization enterXR can be called to start an XR session
          * @returns Promise which resolves after it is initialized
          */
-        WebXRSessionManager.prototype.initialize = function () {
+        WebXRSessionManager.prototype.initializeAsync = function () {
             var _this = this;
             // Check if the browser supports webXR
             this._xrNavigator = navigator;
@@ -108628,7 +108564,7 @@ var BABYLON;
          * @param frameOfReferenceType option to configure how the xr pose is expressed
          * @returns Promise which resolves after it enters XR
          */
-        WebXRSessionManager.prototype.enterXR = function (sessionCreationOptions, frameOfReferenceType) {
+        WebXRSessionManager.prototype.enterXRAsync = function (sessionCreationOptions, frameOfReferenceType) {
             var _this = this;
             // initialize session
             return this._xrDevice.requestSession(sessionCreationOptions).then(function (session) {
@@ -108669,7 +108605,7 @@ var BABYLON;
          * Stops the xrSession and restores the renderloop
          * @returns Promise which resolves after it exits XR
          */
-        WebXRSessionManager.prototype.exitXR = function () {
+        WebXRSessionManager.prototype.exitXRAsync = function () {
             return this._xrSession.end();
         };
         /**
@@ -108677,7 +108613,7 @@ var BABYLON;
          * @param ray ray to cast into the environment
          * @returns Promise which resolves with a collision point in the environment if it exists
          */
-        WebXRSessionManager.prototype.environmentPointHitTest = function (ray) {
+        WebXRSessionManager.prototype.environmentPointHitTestAsync = function (ray) {
             var _this = this;
             return new Promise(function (res, rej) {
                 // Compute left handed inputs to request hit test
@@ -108711,7 +108647,7 @@ var BABYLON;
          * @param options creation options to check if they are supported
          * @returns true if supported
          */
-        WebXRSessionManager.prototype.supportsSession = function (options) {
+        WebXRSessionManager.prototype.supportsSessionAsync = function (options) {
             return this._xrDevice.supportsSession(options).then(function () {
                 return true;
             }).catch(function (e) {
@@ -108810,7 +108746,7 @@ var BABYLON;
          */
         WebXRExperienceHelper.CreateAsync = function (scene) {
             var helper = new WebXRExperienceHelper(scene);
-            return helper._sessionManager.initialize().then(function () {
+            return helper._sessionManager.initializeAsync().then(function () {
                 helper._supported = true;
                 return helper;
             }).catch(function () {
@@ -108821,9 +108757,9 @@ var BABYLON;
          * Exits XR mode and returns the scene to its original state
          * @returns promise that resolves after xr mode has exited
          */
-        WebXRExperienceHelper.prototype.exitXR = function () {
+        WebXRExperienceHelper.prototype.exitXRAsync = function () {
             this._setState(WebXRState.EXITING_XR);
-            return this._sessionManager.exitXR();
+            return this._sessionManager.exitXRAsync();
         };
         /**
          * Enters XR mode (This must be done within a user interaction in most browsers eg. button click)
@@ -108831,10 +108767,10 @@ var BABYLON;
          * @param frameOfReference frame of reference of the XR session
          * @returns promise that resolves after xr mode has entered
          */
-        WebXRExperienceHelper.prototype.enterXR = function (sessionCreationOptions, frameOfReference) {
+        WebXRExperienceHelper.prototype.enterXRAsync = function (sessionCreationOptions, frameOfReference) {
             var _this = this;
             this._setState(WebXRState.ENTERING_XR);
-            return this._sessionManager.enterXR(sessionCreationOptions, frameOfReference).then(function () {
+            return this._sessionManager.enterXRAsync(sessionCreationOptions, frameOfReference).then(function () {
                 // Cache pre xr scene settings
                 _this._originalSceneAutoClear = _this.scene.autoClear;
                 _this._nonVRCamera = _this.scene.activeCamera;
@@ -108859,15 +108795,23 @@ var BABYLON;
             });
         };
         /**
+         * Fires a ray and returns the closest hit in the xr sessions enviornment, useful to place objects in AR
+         * @param ray ray to cast into the environment
+         * @returns Promise which resolves with a collision point in the environment if it exists
+         */
+        WebXRExperienceHelper.prototype.environmentPointHitTestAsync = function (ray) {
+            return this._sessionManager.environmentPointHitTestAsync(ray);
+        };
+        /**
          * Checks if the creation options are supported by the xr session
          * @param options creation options
          * @returns true if supported
          */
-        WebXRExperienceHelper.prototype.supportsSession = function (options) {
+        WebXRExperienceHelper.prototype.supportsSessionAsync = function (options) {
             if (!this._supported) {
                 return Promise.resolve(false);
             }
-            return this._sessionManager.supportsSession(options);
+            return this._sessionManager.supportsSessionAsync(options);
         };
         /**
          * Disposes of the experience helper
@@ -108923,6 +108867,32 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
 var BABYLON;
 (function (BABYLON) {
     /**
+     * Button which can be used to enter a different mode of XR
+     */
+    var WebXREnterExitUIButton = /** @class */ (function () {
+        /**
+         * Creates a WebXREnterExitUIButton
+         * @param element button element
+         * @param initializationOptions XR initialization options for the button
+         */
+        function WebXREnterExitUIButton(
+        /** button element */
+        element, 
+        /** XR initialization options for the button */
+        initializationOptions) {
+            this.element = element;
+            this.initializationOptions = initializationOptions;
+        }
+        /**
+         * Overwritable function which can be used to update the button's visuals when the state changes
+         * @param activeButton the current active button in the UI
+         */
+        WebXREnterExitUIButton.prototype.update = function (activeButton) {
+        };
+        return WebXREnterExitUIButton;
+    }());
+    BABYLON.WebXREnterExitUIButton = WebXREnterExitUIButton;
+    /**
      * Options to create the webXR UI
      */
     var WebXREnterExitUIOptions = /** @class */ (function () {
@@ -108939,6 +108909,7 @@ var BABYLON;
             var _this = this;
             this.scene = scene;
             this._buttons = [];
+            this._activeButton = null;
             this._overlay = document.createElement("div");
             this._overlay.style.cssText = "z-index:11;position: absolute; right: 20px;bottom: 50px;";
             if (options.customButtons) {
@@ -108948,11 +108919,20 @@ var BABYLON;
                 var hmdBtn = document.createElement("button");
                 hmdBtn.style.cssText = "color: #868686; border-color: #868686; border-style: solid; margin-left: 10px; height: 50px; width: 80px; background-color: rgba(51,51,51,0.7); background-repeat:no-repeat; background-position: center; outline: none;";
                 hmdBtn.innerText = "HMD";
-                this._buttons.push({ element: hmdBtn, initializationOptions: { immersive: true } });
+                this._buttons.push(new WebXREnterExitUIButton(hmdBtn, { immersive: true, outputContext: options.outputCanvasContext }));
+                this._buttons[this._buttons.length - 1].update = function (activeButton) {
+                    this.element.style.display = (activeButton === null || activeButton === this) ? "" : "none";
+                    this.element.innerText = activeButton === this ? "EXIT" : "HMD";
+                };
                 var windowBtn = document.createElement("button");
                 windowBtn.style.cssText = hmdBtn.style.cssText;
                 windowBtn.innerText = "Window";
-                this._buttons.push({ element: windowBtn, initializationOptions: { immersive: false, environmentIntegration: true, outputContext: options.outputCanvasContext } });
+                this._buttons.push(new WebXREnterExitUIButton(windowBtn, { immersive: false, environmentIntegration: true, outputContext: options.outputCanvasContext }));
+                this._buttons[this._buttons.length - 1].update = function (activeButton) {
+                    this.element.style.display = (activeButton === null || activeButton === this) ? "" : "none";
+                    this.element.innerText = activeButton === this ? "EXIT" : "Window";
+                };
+                this._updateButtons(null);
             }
             var renderCanvas = scene.getEngine().getRenderingCanvas();
             if (renderCanvas && renderCanvas.parentNode) {
@@ -108973,7 +108953,12 @@ var BABYLON;
             var _this = this;
             var ui = new WebXREnterExitUI(scene, options);
             var supportedPromises = ui._buttons.map(function (btn) {
-                return helper.supportsSession(btn.initializationOptions);
+                return helper.supportsSessionAsync(btn.initializationOptions);
+            });
+            helper.onStateChangedObservable.add(function (state) {
+                if (state == BABYLON.WebXRState.NOT_IN_XR) {
+                    ui._updateButtons(null);
+                }
             });
             return Promise.all(supportedPromises).then(function (results) {
                 results.forEach(function (supported, i) {
@@ -108984,13 +108969,15 @@ var BABYLON;
                                 switch (_a.label) {
                                     case 0:
                                         if (!(helper.state == BABYLON.WebXRState.IN_XR)) return [3 /*break*/, 2];
-                                        return [4 /*yield*/, helper.exitXR()];
+                                        ui._updateButtons(null);
+                                        return [4 /*yield*/, helper.exitXRAsync()];
                                     case 1:
                                         _a.sent();
                                         return [2 /*return*/];
                                     case 2:
                                         if (!(helper.state == BABYLON.WebXRState.NOT_IN_XR)) return [3 /*break*/, 4];
-                                        return [4 /*yield*/, helper.enterXR(ui._buttons[i].initializationOptions, "eye-level")];
+                                        ui._updateButtons(ui._buttons[i]);
+                                        return [4 /*yield*/, helper.enterXRAsync(ui._buttons[i].initializationOptions, "eye-level")];
                                     case 3:
                                         _a.sent();
                                         _a.label = 4;
@@ -109002,6 +108989,13 @@ var BABYLON;
                 });
             });
         };
+        WebXREnterExitUI.prototype._updateButtons = function (activeButton) {
+            var _this = this;
+            this._activeButton = activeButton;
+            this._buttons.forEach(function (b) {
+                b.update(_this._activeButton);
+            });
+        };
         /**
          * Disposes of the object
          */
@@ -109038,7 +109032,7 @@ var BABYLON;
             this.canvasContext = null;
             if (!canvas) {
                 canvas = document.createElement('canvas');
-                canvas.style.cssText = "position:absolute; bottom:0px;right:0px;z-index:10;width:100%;height:100%;background-color: #48989e;";
+                canvas.style.cssText = "position:absolute; bottom:0px;right:0px;z-index:10;width:100%;height:100%;background-color: #000000;";
             }
             this._setManagedOutputCanvas(canvas);
             helper.onStateChangedObservable.add(function (stateInfo) {
@@ -109086,6 +109080,104 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.webXRManagedOutputCanvas.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    /**
+     * Represents an XR input
+     */
+    var WebXRController = /** @class */ (function () {
+        /**
+         * Creates the controller
+         * @see https://doc.babylonjs.com/how_to/webxr
+         * @param scene the scene which the controller should be associated to
+         */
+        function WebXRController(scene) {
+            this.pointer = new BABYLON.AbstractMesh("controllerPointer", scene);
+        }
+        /**
+         * Disposes of the object
+         */
+        WebXRController.prototype.dispose = function () {
+            if (this.grip) {
+                this.grip.dispose();
+            }
+            this.pointer.dispose();
+        };
+        return WebXRController;
+    }());
+    BABYLON.WebXRController = WebXRController;
+    /**
+     * XR input used to track XR inputs such as controllers/rays
+     */
+    var WebXRInput = /** @class */ (function () {
+        /**
+         * Initializes the WebXRInput
+         * @param helper experience helper which the input should be created for
+         */
+        function WebXRInput(helper) {
+            var _this = this;
+            this.helper = helper;
+            /**
+             * XR controllers being tracked
+             */
+            this.controllers = [];
+            this._tmpMatrix = new BABYLON.Matrix();
+            this._frameObserver = helper._sessionManager.onXRFrameObservable.add(function () {
+                if (!helper._sessionManager._currentXRFrame || !helper._sessionManager._currentXRFrame.getDevicePose) {
+                    return;
+                }
+                var xrFrame = helper._sessionManager._currentXRFrame;
+                var inputSources = helper._sessionManager._xrSession.getInputSources();
+                inputSources.forEach(function (input, i) {
+                    var inputPose = xrFrame.getInputPose(input, helper._sessionManager._frameOfReference);
+                    if (inputPose) {
+                        if (_this.controllers.length <= i) {
+                            _this.controllers.push(new WebXRController(helper.container.getScene()));
+                        }
+                        var controller = _this.controllers[i];
+                        // Manage the grip if it exists
+                        if (inputPose.gripMatrix) {
+                            if (!controller.grip) {
+                                controller.grip = new BABYLON.AbstractMesh("controllerGrip", helper.container.getScene());
+                            }
+                            BABYLON.Matrix.FromFloat32ArrayToRefScaled(inputPose.gripMatrix, 0, 1, _this._tmpMatrix);
+                            if (!controller.grip.getScene().useRightHandedSystem) {
+                                _this._tmpMatrix.toggleModelMatrixHandInPlace();
+                            }
+                            if (!controller.grip.rotationQuaternion) {
+                                controller.grip.rotationQuaternion = new BABYLON.Quaternion();
+                            }
+                            _this._tmpMatrix.decompose(controller.grip.scaling, controller.grip.rotationQuaternion, controller.grip.position);
+                        }
+                        // Manager pointer of controller
+                        BABYLON.Matrix.FromFloat32ArrayToRefScaled(inputPose.targetRay.transformMatrix, 0, 1, _this._tmpMatrix);
+                        if (!controller.pointer.getScene().useRightHandedSystem) {
+                            _this._tmpMatrix.toggleModelMatrixHandInPlace();
+                        }
+                        if (!controller.pointer.rotationQuaternion) {
+                            controller.pointer.rotationQuaternion = new BABYLON.Quaternion();
+                        }
+                        _this._tmpMatrix.decompose(controller.pointer.scaling, controller.pointer.rotationQuaternion, controller.pointer.position);
+                    }
+                });
+            });
+        }
+        /**
+         * Disposes of the object
+         */
+        WebXRInput.prototype.dispose = function () {
+            this.controllers.forEach(function (c) {
+                c.dispose();
+            });
+            this.helper._sessionManager.onXRFrameObservable.remove(this._frameObserver);
+        };
+        return WebXRInput;
+    }());
+    BABYLON.WebXRInput = WebXRInput;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.webXRInput.js.map
+
 // Mainly based on these 2 articles :
 // Creating an universal virtual touch joystick working for all Touch models thanks to Hand.JS : http://blogs.msdn.com/b/davrous/archive/2013/02/22/creating-an-universal-virtual-touch-joystick-working-for-all-touch-models-thanks-to-hand-js.aspx
 // & on Seb Lee-Delisle original work: http://seb.ly/2011/04/multi-touch-game-controller-in-javascripthtml5-for-ipad/
@@ -119986,7 +120078,9 @@ var BABYLON;
         var _this = this;
         return BABYLON.WebXRExperienceHelper.CreateAsync(this).then(function (helper) {
             var outputCanvas = new BABYLON.WebXRManagedOutputCanvas(helper);
-            return BABYLON.WebXREnterExitUI.CreateAsync(_this, helper, { outputCanvasContext: outputCanvas.canvasContext }).then(function (ui) {
+            return BABYLON.WebXREnterExitUI.CreateAsync(_this, helper, { outputCanvasContext: outputCanvas.canvasContext })
+                .then(function (ui) {
+                new BABYLON.WebXRInput(helper);
                 return helper;
             });
         });

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

@@ -5444,7 +5444,7 @@ var BABYLON;
         };
         /**
          * Returns a new Vector3 set from the index "offset" of the given Float32Array
-         * This function is deprecated.  Use FromArray instead
+         * This function is deprecated. Use FromArray instead
          * @param array defines the source array
          * @param offset defines the offset in the source array
          * @returns the new Vector3
@@ -5792,6 +5792,15 @@ var BABYLON;
             matrix.multiplyToRef(viewportMatrix, matrix);
             return Vector3.TransformCoordinates(vector, matrix);
         };
+        /** @hidden */
+        Vector3.UnprojectFromInvertedMatrixToRef = function (source, matrix, result) {
+            Vector3.TransformCoordinatesToRef(source, matrix, result);
+            var m = matrix.m;
+            var num = source.x * m[3] + source.y * m[7] + source.z * m[11] + m[15];
+            if (BABYLON.Scalar.WithinEpsilon(num, 1.0)) {
+                result.scaleInPlace(1.0 / num);
+            }
+        };
         /**
          * Unproject from screen space to object space
          * @param source defines the screen space Vector3 to use
@@ -5807,12 +5816,8 @@ var BABYLON;
             matrix.invert();
             source.x = source.x / viewportWidth * 2 - 1;
             source.y = -(source.y / viewportHeight * 2 - 1);
-            var vector = Vector3.TransformCoordinates(source, matrix);
-            var m = matrix.m;
-            var num = source.x * m[3] + source.y * m[7] + source.z * m[11] + m[15];
-            if (BABYLON.Scalar.WithinEpsilon(num, 1.0)) {
-                vector = vector.scale(1.0 / num);
-            }
+            var vector = new Vector3();
+            Vector3.UnprojectFromInvertedMatrixToRef(source, matrix, vector);
             return vector;
         };
         /**
@@ -5864,12 +5869,36 @@ var BABYLON;
             screenSource.x = sourceX / viewportWidth * 2 - 1;
             screenSource.y = -(sourceY / viewportHeight * 2 - 1);
             screenSource.z = 2 * sourceZ - 1.0;
-            Vector3.TransformCoordinatesToRef(screenSource, matrix, result);
-            var m = matrix.m;
-            var num = screenSource.x * m[3] + screenSource.y * m[7] + screenSource.z * m[11] + m[15];
-            if (BABYLON.Scalar.WithinEpsilon(num, 1.0)) {
-                result.scaleInPlace(1.0 / num);
-            }
+            Vector3.UnprojectFromInvertedMatrixToRef(screenSource, matrix, result);
+        };
+        /**
+          * Unproject a ray from screen space to object space
+          * @param sourceX defines the screen space x coordinate to use
+          * @param sourceY defines the screen space y coordinate to use
+          * @param viewportWidth defines the current width of the viewport
+          * @param viewportHeight defines the current height of the viewport
+          * @param world defines the world matrix to use (can be set to Identity to go to world space)
+          * @param view defines the view matrix to use
+          * @param projection defines the projection matrix to use
+          * @param ray defines the Ray where to store the result
+          */
+        Vector3.UnprojectRayToRef = function (sourceX, sourceY, viewportWidth, viewportHeight, world, view, projection, ray) {
+            var matrix = MathTmp.Matrix[0];
+            world.multiplyToRef(view, matrix);
+            matrix.multiplyToRef(projection, matrix);
+            matrix.invert();
+            var nearScreenSource = MathTmp.Vector3[0];
+            nearScreenSource.x = sourceX / viewportWidth * 2 - 1;
+            nearScreenSource.y = -(sourceY / viewportHeight * 2 - 1);
+            nearScreenSource.z = -1.0;
+            var farScreenSource = MathTmp.Vector3[1].copyFromFloats(nearScreenSource.x, nearScreenSource.y, 1.0);
+            var nearVec3 = MathTmp.Vector3[2];
+            var farVec3 = MathTmp.Vector3[3];
+            Vector3.UnprojectFromInvertedMatrixToRef(nearScreenSource, matrix, nearVec3);
+            Vector3.UnprojectFromInvertedMatrixToRef(farScreenSource, matrix, farVec3);
+            ray.origin.copyFrom(nearVec3);
+            farVec3.subtractToRef(nearVec3, ray.direction);
+            ray.direction.normalize();
         };
         /**
          * Gets the minimal coordinate values between two Vector3
@@ -13203,24 +13232,6 @@ var BABYLON;
         Engine.prototype.getCaps = function () {
             return this._caps;
         };
-        Object.defineProperty(Engine.prototype, "drawCalls", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("drawCalls is deprecated. Please use SceneInstrumentation class");
-                return 0;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(Engine.prototype, "drawCallsPerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("drawCallsPerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
         /**
          * Gets the current depth function
          * @returns a number defining the depth function
@@ -25581,6 +25592,10 @@ var BABYLON;
             */
             _this.onAfterStepObservable = new BABYLON.Observable();
             /**
+             * An event triggered when the activeCamera property is updated
+             */
+            _this.onActiveCameraChanged = new BABYLON.Observable();
+            /**
              * This Observable will be triggered before rendering each renderingGroup of each rendered camera.
              * The RenderinGroupInfo class contains all the information about the context in which the observable is called
              * If you wish to register an Observer only for a given set of renderingGroup, use the mask with a combination of the renderingGroup index elevated to the power of two (1 for renderingGroup 0, 2 for renderingrOup1, 4 for 2 and 8 for 3)
@@ -26219,6 +26234,21 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Scene.prototype, "activeCamera", {
+            /** Gets or sets the current active camera */
+            get: function () {
+                return this._activeCamera;
+            },
+            set: function (value) {
+                if (value === this._activeCamera) {
+                    return;
+                }
+                this._activeCamera = value;
+                this.onActiveCameraChanged.notifyObservers(this);
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Scene.prototype, "defaultMaterial", {
             /** The default material used on meshes when no material is affected */
             get: function () {
@@ -26520,48 +26550,6 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
-        /** @hidden */
-        Scene.prototype.getInterFramePerfCounter = function () {
-            BABYLON.Tools.Warn("getInterFramePerfCounter is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "interFramePerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("interFramePerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        /** @hidden */
-        Scene.prototype.getLastFrameDuration = function () {
-            BABYLON.Tools.Warn("getLastFrameDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "lastFramePerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("lastFramePerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        /** @hidden */
-        Scene.prototype.getEvaluateActiveMeshesDuration = function () {
-            BABYLON.Tools.Warn("getEvaluateActiveMeshesDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "evaluateActiveMeshesDurationPerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("evaluateActiveMeshesDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
         /**
          * Gets the array of active meshes
          * @returns an array of AbstractMesh
@@ -26569,53 +26557,6 @@ var BABYLON;
         Scene.prototype.getActiveMeshes = function () {
             return this._activeMeshes;
         };
-        /** @hidden */
-        Scene.prototype.getRenderTargetsDuration = function () {
-            BABYLON.Tools.Warn("getRenderTargetsDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        /** @hidden */
-        Scene.prototype.getRenderDuration = function () {
-            BABYLON.Tools.Warn("getRenderDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "renderDurationPerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("renderDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        /** @hidden */
-        Scene.prototype.getParticlesDuration = function () {
-            BABYLON.Tools.Warn("getParticlesDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "particlesDurationPerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("particlesDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        /** @hidden */
-        Scene.prototype.getSpritesDuration = function () {
-            BABYLON.Tools.Warn("getSpritesDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        };
-        Object.defineProperty(Scene.prototype, "spriteDuractionPerfCounter", {
-            /** @hidden */
-            get: function () {
-                BABYLON.Tools.Warn("spriteDuractionPerfCounter is deprecated. Please use SceneInstrumentation class");
-                return null;
-            },
-            enumerable: true,
-            configurable: true
-        });
         /**
          * Gets the animation ratio (which is 1.0 is the scene renders at 60fps and 2 if the scene renders at 30fps, etc.)
          * @returns a number
@@ -27102,6 +27043,7 @@ var BABYLON;
                     canvas.focus();
                 }
                 _this._initClickEvent(_this.onPrePointerObservable, _this.onPointerObservable, evt, function (clickInfo, pickResult) {
+                    _this._pointerCaptures[evt.pointerId] = false;
                     // PreObservable support
                     if (_this.onPrePointerObservable.hasObservers()) {
                         if (!clickInfo.ignore) {
@@ -27125,7 +27067,6 @@ var BABYLON;
                     if (!_this.cameraToUseForPointers && !_this.activeCamera) {
                         return;
                     }
-                    _this._pointerCaptures[evt.pointerId] = false;
                     if (!_this.pointerUpPredicate) {
                         _this.pointerUpPredicate = function (mesh) {
                             return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.isEnabled();
@@ -29497,6 +29438,7 @@ var BABYLON;
             this.onPointerObservable.clear();
             this.onPreKeyboardObservable.clear();
             this.onKeyboardObservable.clear();
+            this.onActiveCameraChanged.clear();
             this.detachControl();
             // Detach cameras
             var canvas = this._engine.getRenderingCanvas();
@@ -29670,7 +29612,7 @@ var BABYLON;
             // Moving coordinates to local viewport world
             x = x / this._engine.getHardwareScalingLevel() - viewport.x;
             y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
-            result.update(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), cameraViewSpace ? BABYLON.Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
+            result.update(x, y, viewport.width, viewport.height, world ? world : BABYLON.Matrix.IdentityReadOnly, cameraViewSpace ? BABYLON.Matrix.IdentityReadOnly : camera.getViewMatrix(), camera.getProjectionMatrix());
             return this;
         };
         /**
@@ -37262,20 +37204,27 @@ var BABYLON;
          * @param flag defines a flag used to determine which parts of the material have to be marked as dirty
          */
         Material.prototype.markAsDirty = function (flag) {
+            if (this.getScene().blockMaterialDirtyMechanism) {
+                return;
+            }
+            Material._DirtyCallbackArray.length = 0;
             if (flag & Material.TextureDirtyFlag) {
-                this._markAllSubMeshesAsTexturesDirty();
+                Material._DirtyCallbackArray.push(Material._TextureDirtyCallBack);
             }
             if (flag & Material.LightDirtyFlag) {
-                this._markAllSubMeshesAsLightsDirty();
+                Material._DirtyCallbackArray.push(Material._LightsDirtyCallBack);
             }
             if (flag & Material.FresnelDirtyFlag) {
-                this._markAllSubMeshesAsFresnelDirty();
+                Material._DirtyCallbackArray.push(Material._FresnelDirtyCallBack);
             }
             if (flag & Material.AttributesDirtyFlag) {
-                this._markAllSubMeshesAsAttributesDirty();
+                Material._DirtyCallbackArray.push(Material._AttributeDirtyCallBack);
             }
             if (flag & Material.MiscDirtyFlag) {
-                this._markAllSubMeshesAsMiscDirty();
+                Material._DirtyCallbackArray.push(Material._MiscDirtyCallBack);
+            }
+            if (Material._DirtyCallbackArray.length) {
+                this._markAllSubMeshesAsDirty(Material._RunDirtyCallBacks);
             }
             this.getScene().resetCachedMaterial();
         };
@@ -37284,13 +37233,17 @@ var BABYLON;
          * @param func defines a function which checks material defines against the submeshes
          */
         Material.prototype._markAllSubMeshesAsDirty = function (func) {
-            for (var _i = 0, _a = this.getScene().meshes; _i < _a.length; _i++) {
-                var mesh = _a[_i];
+            if (this.getScene().blockMaterialDirtyMechanism) {
+                return;
+            }
+            var meshes = this.getScene().meshes;
+            for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                var mesh = meshes_1[_i];
                 if (!mesh.subMeshes) {
                     continue;
                 }
-                for (var _b = 0, _c = mesh.subMeshes; _b < _c.length; _b++) {
-                    var subMesh = _c[_b];
+                for (var _a = 0, _b = mesh.subMeshes; _a < _b.length; _a++) {
+                    var subMesh = _b[_a];
                     if (subMesh.getMaterial() !== this) {
                         continue;
                     }
@@ -37305,55 +37258,49 @@ var BABYLON;
          * Indicates that image processing needs to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsImageProcessingDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsImageProcessingDirty(); });
+            this._markAllSubMeshesAsDirty(Material._ImageProcessingDirtyCallBack);
         };
         /**
          * Indicates that textures need to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsTexturesDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsTexturesDirty(); });
+            this._markAllSubMeshesAsDirty(Material._TextureDirtyCallBack);
         };
         /**
          * Indicates that fresnel needs to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsFresnelDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsFresnelDirty(); });
+            this._markAllSubMeshesAsDirty(Material._FresnelDirtyCallBack);
         };
         /**
          * Indicates that fresnel and misc need to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsFresnelAndMiscDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) {
-                defines.markAsFresnelDirty();
-                defines.markAsMiscDirty();
-            });
+            this._markAllSubMeshesAsDirty(Material._FresnelAndMiscDirtyCallBack);
         };
         /**
          * Indicates that lights need to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsLightsDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsLightDirty(); });
+            this._markAllSubMeshesAsDirty(Material._LightsDirtyCallBack);
         };
         /**
          * Indicates that attributes need to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsAttributesDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsAttributesDirty(); });
+            this._markAllSubMeshesAsDirty(Material._AttributeDirtyCallBack);
         };
         /**
          * Indicates that misc needs to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsMiscDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) { return defines.markAsMiscDirty(); });
+            this._markAllSubMeshesAsDirty(Material._MiscDirtyCallBack);
         };
         /**
          * Indicates that textures and misc need to be re-calculated for all submeshes
          */
         Material.prototype._markAllSubMeshesAsTexturesAndMiscDirty = function () {
-            this._markAllSubMeshesAsDirty(function (defines) {
-                defines.markAsTexturesDirty();
-                defines.markAsMiscDirty();
-            });
+            this._markAllSubMeshesAsDirty(Material._TextureAndMiscDirtyCallBack);
         };
         /**
          * Disposes the material
@@ -37381,8 +37328,8 @@ var BABYLON;
                 }
                 else {
                     var meshes = scene.meshes;
-                    for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
-                        var mesh = meshes_1[_i];
+                    for (var _i = 0, meshes_2 = meshes; _i < meshes_2.length; _i++) {
+                        var mesh = meshes_2[_i];
                         if (mesh.material === this) {
                             mesh.material = null;
                             this.releaseVertexArrayObject(mesh, forceDisposeEffect);
@@ -37521,6 +37468,27 @@ var BABYLON;
          * The all dirty flag value
          */
         Material.AllDirtyFlag = 31;
+        Material._ImageProcessingDirtyCallBack = function (defines) { return defines.markAsImageProcessingDirty(); };
+        Material._TextureDirtyCallBack = function (defines) { return defines.markAsTexturesDirty(); };
+        Material._FresnelDirtyCallBack = function (defines) { return defines.markAsFresnelDirty(); };
+        Material._MiscDirtyCallBack = function (defines) { return defines.markAsMiscDirty(); };
+        Material._LightsDirtyCallBack = function (defines) { return defines.markAsLightDirty(); };
+        Material._AttributeDirtyCallBack = function (defines) { return defines.markAsAttributesDirty(); };
+        Material._FresnelAndMiscDirtyCallBack = function (defines) {
+            Material._FresnelDirtyCallBack(defines);
+            Material._MiscDirtyCallBack(defines);
+        };
+        Material._TextureAndMiscDirtyCallBack = function (defines) {
+            Material._TextureDirtyCallBack(defines);
+            Material._MiscDirtyCallBack(defines);
+        };
+        Material._DirtyCallbackArray = [];
+        Material._RunDirtyCallBacks = function (defines) {
+            for (var _i = 0, _a = Material._DirtyCallbackArray; _i < _a.length; _i++) {
+                var cb = _a[_i];
+                cb(defines);
+            }
+        };
         __decorate([
             BABYLON.serialize()
         ], Material.prototype, "id", void 0);
@@ -58815,8 +58783,8 @@ var BABYLON;
          */
         Ray.prototype.intersectsBoxMinMax = function (minimum, maximum, intersectionTreshold) {
             if (intersectionTreshold === void 0) { intersectionTreshold = 0; }
-            var newMinimum = Ray._min.copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
-            var newMaximum = Ray._max.copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
+            var newMinimum = Ray.TmpVector3[0].copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
+            var newMaximum = Ray.TmpVector3[1].copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
             var d = 0.0;
             var maxValue = Number.MAX_VALUE;
             var inv;
@@ -58936,26 +58904,31 @@ var BABYLON;
          * @returns intersection information if hit
          */
         Ray.prototype.intersectsTriangle = function (vertex0, vertex1, vertex2) {
-            vertex1.subtractToRef(vertex0, Ray._edge1);
-            vertex2.subtractToRef(vertex0, Ray._edge2);
-            BABYLON.Vector3.CrossToRef(this.direction, Ray._edge2, Ray._pvec);
-            var det = BABYLON.Vector3.Dot(Ray._edge1, Ray._pvec);
+            var edge1 = Ray.TmpVector3[0];
+            var edge2 = Ray.TmpVector3[1];
+            var pvec = Ray.TmpVector3[2];
+            var tvec = Ray.TmpVector3[3];
+            var qvec = Ray.TmpVector3[4];
+            vertex1.subtractToRef(vertex0, edge1);
+            vertex2.subtractToRef(vertex0, edge2);
+            BABYLON.Vector3.CrossToRef(this.direction, edge2, pvec);
+            var det = BABYLON.Vector3.Dot(edge1, pvec);
             if (det === 0) {
                 return null;
             }
             var invdet = 1 / det;
-            this.origin.subtractToRef(vertex0, Ray._tvec);
-            var bu = BABYLON.Vector3.Dot(Ray._tvec, Ray._pvec) * invdet;
+            this.origin.subtractToRef(vertex0, tvec);
+            var bu = BABYLON.Vector3.Dot(tvec, pvec) * invdet;
             if (bu < 0 || bu > 1.0) {
                 return null;
             }
-            BABYLON.Vector3.CrossToRef(Ray._tvec, Ray._edge1, Ray._qvec);
-            var bv = BABYLON.Vector3.Dot(this.direction, Ray._qvec) * invdet;
+            BABYLON.Vector3.CrossToRef(tvec, edge1, qvec);
+            var bv = BABYLON.Vector3.Dot(this.direction, qvec) * invdet;
             if (bv < 0 || bu + bv > 1.0) {
                 return null;
             }
             //check if the distance is longer than the predefined length.
-            var distance = BABYLON.Vector3.Dot(Ray._edge2, Ray._qvec) * invdet;
+            var distance = BABYLON.Vector3.Dot(edge2, qvec) * invdet;
             if (distance > this.length) {
                 return null;
             }
@@ -59045,10 +59018,15 @@ var BABYLON;
          * @return the distance from the ray origin to the intersection point if there's intersection, or -1 if there's no intersection
          */
         Ray.prototype.intersectionSegment = function (sega, segb, threshold) {
-            var rsegb = this.origin.add(this.direction.multiplyByFloats(Ray.rayl, Ray.rayl, Ray.rayl));
-            var u = segb.subtract(sega);
-            var v = rsegb.subtract(this.origin);
-            var w = sega.subtract(this.origin);
+            var o = this.origin;
+            var u = BABYLON.Tmp.Vector3[0];
+            var rsegb = BABYLON.Tmp.Vector3[1];
+            var v = BABYLON.Tmp.Vector3[2];
+            var w = BABYLON.Tmp.Vector3[3];
+            segb.subtractToRef(sega, u);
+            this.direction.scaleToRef(Ray.rayl, v);
+            o.addToRef(v, rsegb);
+            sega.subtractToRef(o, w);
             var a = BABYLON.Vector3.Dot(u, u); // always >= 0
             var b = BABYLON.Vector3.Dot(u, v);
             var c = BABYLON.Vector3.Dot(v, v); // always >= 0
@@ -59110,8 +59088,11 @@ var BABYLON;
             sc = (Math.abs(sN) < Ray.smallnum ? 0.0 : sN / sD);
             tc = (Math.abs(tN) < Ray.smallnum ? 0.0 : tN / tD);
             // get the difference of the two closest points
-            var qtc = v.multiplyByFloats(tc, tc, tc);
-            var dP = w.add(u.multiplyByFloats(sc, sc, sc)).subtract(qtc); // = S1(sc) - S2(tc)
+            var qtc = BABYLON.Tmp.Vector3[4];
+            v.scaleToRef(tc, qtc);
+            var dP = BABYLON.Tmp.Vector3[5];
+            u.scaleToRef(sc, dP);
+            dP.addInPlace(w).subtractInPlace(qtc); // = S1(sc) - S2(tc)
             var isIntersected = (tc > 0) && (tc <= this.length) && (dP.lengthSquared() < (threshold * threshold)); // return intersection result
             if (isIntersected) {
                 return qtc.length();
@@ -59130,10 +59111,7 @@ var BABYLON;
          * @returns this ray updated
          */
         Ray.prototype.update = function (x, y, viewportWidth, viewportHeight, world, view, projection) {
-            BABYLON.Vector3.UnprojectFloatsToRef(x, y, 0, viewportWidth, viewportHeight, world, view, projection, this.origin);
-            BABYLON.Vector3.UnprojectFloatsToRef(x, y, 1, viewportWidth, viewportHeight, world, view, projection, BABYLON.Tmp.Vector3[0]);
-            BABYLON.Tmp.Vector3[0].subtractToRef(this.origin, this.direction);
-            this.direction.normalize();
+            BABYLON.Vector3.UnprojectRayToRef(x, y, viewportWidth, viewportHeight, world, view, projection, this);
             return this;
         };
         // Statics
@@ -59205,13 +59183,7 @@ var BABYLON;
                 result.length *= len;
             }
         };
-        Ray._edge1 = BABYLON.Vector3.Zero();
-        Ray._edge2 = BABYLON.Vector3.Zero();
-        Ray._pvec = BABYLON.Vector3.Zero();
-        Ray._tvec = BABYLON.Vector3.Zero();
-        Ray._qvec = BABYLON.Vector3.Zero();
-        Ray._min = BABYLON.Vector3.Zero();
-        Ray._max = BABYLON.Vector3.Zero();
+        Ray.TmpVector3 = BABYLON.Tools.BuildArray(6, BABYLON.Vector3.Zero);
         Ray.smallnum = 0.00000001;
         Ray.rayl = 10e8;
         return Ray;
@@ -66869,7 +66841,6 @@ var BABYLON;
             _this._started = false;
             _this._stopped = false;
             _this._timeDelta = 0;
-            _this._attributesStrideSize = 21;
             _this._actualFrame = 0;
             _this._rawTextureWidth = 256;
             /**
@@ -67485,6 +67456,8 @@ var BABYLON;
             }
             var engine = this._scene.getEngine();
             var data = new Array();
+            this._attributesStrideSize = 21;
+            this._targetIndex = 0;
             if (!this.isBillboardBased) {
                 this._attributesStrideSize += 3;
             }
@@ -76576,46 +76549,6 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
-        Object.defineProperty(ShadowGenerator.prototype, "useVarianceShadowMap", {
-            /**
-             * Gets if the current filter is set to VSM.
-             * DEPRECATED. Should use useExponentialShadowMap instead.
-             */
-            get: function () {
-                BABYLON.Tools.Warn("VSM are now replaced by ESM. Please use useExponentialShadowMap instead.");
-                return this.useExponentialShadowMap;
-            },
-            /**
-             * Sets the current filter is to VSM.
-             * DEPRECATED. Should use useExponentialShadowMap instead.
-             */
-            set: function (value) {
-                BABYLON.Tools.Warn("VSM are now replaced by ESM. Please use useExponentialShadowMap instead.");
-                this.useExponentialShadowMap = value;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(ShadowGenerator.prototype, "useBlurVarianceShadowMap", {
-            /**
-             * Gets if the current filter is set to blurred VSM.
-             * DEPRECATED. Should use useBlurExponentialShadowMap instead.
-             */
-            get: function () {
-                BABYLON.Tools.Warn("VSM are now replaced by ESM. Please use useBlurExponentialShadowMap instead.");
-                return this.useBlurExponentialShadowMap;
-            },
-            /**
-             * Sets the current filter is to blurred VSM.
-             * DEPRECATED. Should use useBlurExponentialShadowMap instead.
-             */
-            set: function (value) {
-                BABYLON.Tools.Warn("VSM are now replaced by ESM. Please use useBlurExponentialShadowMap instead.");
-                this.useBlurExponentialShadowMap = value;
-            },
-            enumerable: true,
-            configurable: true
-        });
         Object.defineProperty(ShadowGenerator.prototype, "useExponentialShadowMap", {
             /**
              * Gets if the current filter is set to ESM.
@@ -77004,7 +76937,7 @@ var BABYLON;
             var scene = this._scene;
             var engine = scene.getEngine();
             var material = subMesh.getMaterial();
-            if (!material) {
+            if (!material || subMesh.verticesCount === 0) {
                 return;
             }
             // Culling
@@ -77042,6 +76975,9 @@ var BABYLON;
                     var skeleton = mesh.skeleton;
                     if (skeleton.isUsingTextureForMatrices) {
                         var boneTexture = skeleton.getTransformMatrixTexture();
+                        if (!boneTexture) {
+                            return;
+                        }
                         this._effect.setTexture("boneSampler", boneTexture);
                         this._effect.setFloat("boneTextureWidth", 4.0 * (skeleton.bones.length + 1));
                     }
@@ -108576,7 +108512,7 @@ var BABYLON;
          * After initialization enterXR can be called to start an XR session
          * @returns Promise which resolves after it is initialized
          */
-        WebXRSessionManager.prototype.initialize = function () {
+        WebXRSessionManager.prototype.initializeAsync = function () {
             var _this = this;
             // Check if the browser supports webXR
             this._xrNavigator = navigator;
@@ -108595,7 +108531,7 @@ var BABYLON;
          * @param frameOfReferenceType option to configure how the xr pose is expressed
          * @returns Promise which resolves after it enters XR
          */
-        WebXRSessionManager.prototype.enterXR = function (sessionCreationOptions, frameOfReferenceType) {
+        WebXRSessionManager.prototype.enterXRAsync = function (sessionCreationOptions, frameOfReferenceType) {
             var _this = this;
             // initialize session
             return this._xrDevice.requestSession(sessionCreationOptions).then(function (session) {
@@ -108636,7 +108572,7 @@ var BABYLON;
          * Stops the xrSession and restores the renderloop
          * @returns Promise which resolves after it exits XR
          */
-        WebXRSessionManager.prototype.exitXR = function () {
+        WebXRSessionManager.prototype.exitXRAsync = function () {
             return this._xrSession.end();
         };
         /**
@@ -108644,7 +108580,7 @@ var BABYLON;
          * @param ray ray to cast into the environment
          * @returns Promise which resolves with a collision point in the environment if it exists
          */
-        WebXRSessionManager.prototype.environmentPointHitTest = function (ray) {
+        WebXRSessionManager.prototype.environmentPointHitTestAsync = function (ray) {
             var _this = this;
             return new Promise(function (res, rej) {
                 // Compute left handed inputs to request hit test
@@ -108678,7 +108614,7 @@ var BABYLON;
          * @param options creation options to check if they are supported
          * @returns true if supported
          */
-        WebXRSessionManager.prototype.supportsSession = function (options) {
+        WebXRSessionManager.prototype.supportsSessionAsync = function (options) {
             return this._xrDevice.supportsSession(options).then(function () {
                 return true;
             }).catch(function (e) {
@@ -108777,7 +108713,7 @@ var BABYLON;
          */
         WebXRExperienceHelper.CreateAsync = function (scene) {
             var helper = new WebXRExperienceHelper(scene);
-            return helper._sessionManager.initialize().then(function () {
+            return helper._sessionManager.initializeAsync().then(function () {
                 helper._supported = true;
                 return helper;
             }).catch(function () {
@@ -108788,9 +108724,9 @@ var BABYLON;
          * Exits XR mode and returns the scene to its original state
          * @returns promise that resolves after xr mode has exited
          */
-        WebXRExperienceHelper.prototype.exitXR = function () {
+        WebXRExperienceHelper.prototype.exitXRAsync = function () {
             this._setState(WebXRState.EXITING_XR);
-            return this._sessionManager.exitXR();
+            return this._sessionManager.exitXRAsync();
         };
         /**
          * Enters XR mode (This must be done within a user interaction in most browsers eg. button click)
@@ -108798,10 +108734,10 @@ var BABYLON;
          * @param frameOfReference frame of reference of the XR session
          * @returns promise that resolves after xr mode has entered
          */
-        WebXRExperienceHelper.prototype.enterXR = function (sessionCreationOptions, frameOfReference) {
+        WebXRExperienceHelper.prototype.enterXRAsync = function (sessionCreationOptions, frameOfReference) {
             var _this = this;
             this._setState(WebXRState.ENTERING_XR);
-            return this._sessionManager.enterXR(sessionCreationOptions, frameOfReference).then(function () {
+            return this._sessionManager.enterXRAsync(sessionCreationOptions, frameOfReference).then(function () {
                 // Cache pre xr scene settings
                 _this._originalSceneAutoClear = _this.scene.autoClear;
                 _this._nonVRCamera = _this.scene.activeCamera;
@@ -108826,15 +108762,23 @@ var BABYLON;
             });
         };
         /**
+         * Fires a ray and returns the closest hit in the xr sessions enviornment, useful to place objects in AR
+         * @param ray ray to cast into the environment
+         * @returns Promise which resolves with a collision point in the environment if it exists
+         */
+        WebXRExperienceHelper.prototype.environmentPointHitTestAsync = function (ray) {
+            return this._sessionManager.environmentPointHitTestAsync(ray);
+        };
+        /**
          * Checks if the creation options are supported by the xr session
          * @param options creation options
          * @returns true if supported
          */
-        WebXRExperienceHelper.prototype.supportsSession = function (options) {
+        WebXRExperienceHelper.prototype.supportsSessionAsync = function (options) {
             if (!this._supported) {
                 return Promise.resolve(false);
             }
-            return this._sessionManager.supportsSession(options);
+            return this._sessionManager.supportsSessionAsync(options);
         };
         /**
          * Disposes of the experience helper
@@ -108890,6 +108834,32 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
 var BABYLON;
 (function (BABYLON) {
     /**
+     * Button which can be used to enter a different mode of XR
+     */
+    var WebXREnterExitUIButton = /** @class */ (function () {
+        /**
+         * Creates a WebXREnterExitUIButton
+         * @param element button element
+         * @param initializationOptions XR initialization options for the button
+         */
+        function WebXREnterExitUIButton(
+        /** button element */
+        element, 
+        /** XR initialization options for the button */
+        initializationOptions) {
+            this.element = element;
+            this.initializationOptions = initializationOptions;
+        }
+        /**
+         * Overwritable function which can be used to update the button's visuals when the state changes
+         * @param activeButton the current active button in the UI
+         */
+        WebXREnterExitUIButton.prototype.update = function (activeButton) {
+        };
+        return WebXREnterExitUIButton;
+    }());
+    BABYLON.WebXREnterExitUIButton = WebXREnterExitUIButton;
+    /**
      * Options to create the webXR UI
      */
     var WebXREnterExitUIOptions = /** @class */ (function () {
@@ -108906,6 +108876,7 @@ var BABYLON;
             var _this = this;
             this.scene = scene;
             this._buttons = [];
+            this._activeButton = null;
             this._overlay = document.createElement("div");
             this._overlay.style.cssText = "z-index:11;position: absolute; right: 20px;bottom: 50px;";
             if (options.customButtons) {
@@ -108915,11 +108886,20 @@ var BABYLON;
                 var hmdBtn = document.createElement("button");
                 hmdBtn.style.cssText = "color: #868686; border-color: #868686; border-style: solid; margin-left: 10px; height: 50px; width: 80px; background-color: rgba(51,51,51,0.7); background-repeat:no-repeat; background-position: center; outline: none;";
                 hmdBtn.innerText = "HMD";
-                this._buttons.push({ element: hmdBtn, initializationOptions: { immersive: true } });
+                this._buttons.push(new WebXREnterExitUIButton(hmdBtn, { immersive: true, outputContext: options.outputCanvasContext }));
+                this._buttons[this._buttons.length - 1].update = function (activeButton) {
+                    this.element.style.display = (activeButton === null || activeButton === this) ? "" : "none";
+                    this.element.innerText = activeButton === this ? "EXIT" : "HMD";
+                };
                 var windowBtn = document.createElement("button");
                 windowBtn.style.cssText = hmdBtn.style.cssText;
                 windowBtn.innerText = "Window";
-                this._buttons.push({ element: windowBtn, initializationOptions: { immersive: false, environmentIntegration: true, outputContext: options.outputCanvasContext } });
+                this._buttons.push(new WebXREnterExitUIButton(windowBtn, { immersive: false, environmentIntegration: true, outputContext: options.outputCanvasContext }));
+                this._buttons[this._buttons.length - 1].update = function (activeButton) {
+                    this.element.style.display = (activeButton === null || activeButton === this) ? "" : "none";
+                    this.element.innerText = activeButton === this ? "EXIT" : "Window";
+                };
+                this._updateButtons(null);
             }
             var renderCanvas = scene.getEngine().getRenderingCanvas();
             if (renderCanvas && renderCanvas.parentNode) {
@@ -108940,7 +108920,12 @@ var BABYLON;
             var _this = this;
             var ui = new WebXREnterExitUI(scene, options);
             var supportedPromises = ui._buttons.map(function (btn) {
-                return helper.supportsSession(btn.initializationOptions);
+                return helper.supportsSessionAsync(btn.initializationOptions);
+            });
+            helper.onStateChangedObservable.add(function (state) {
+                if (state == BABYLON.WebXRState.NOT_IN_XR) {
+                    ui._updateButtons(null);
+                }
             });
             return Promise.all(supportedPromises).then(function (results) {
                 results.forEach(function (supported, i) {
@@ -108951,13 +108936,15 @@ var BABYLON;
                                 switch (_a.label) {
                                     case 0:
                                         if (!(helper.state == BABYLON.WebXRState.IN_XR)) return [3 /*break*/, 2];
-                                        return [4 /*yield*/, helper.exitXR()];
+                                        ui._updateButtons(null);
+                                        return [4 /*yield*/, helper.exitXRAsync()];
                                     case 1:
                                         _a.sent();
                                         return [2 /*return*/];
                                     case 2:
                                         if (!(helper.state == BABYLON.WebXRState.NOT_IN_XR)) return [3 /*break*/, 4];
-                                        return [4 /*yield*/, helper.enterXR(ui._buttons[i].initializationOptions, "eye-level")];
+                                        ui._updateButtons(ui._buttons[i]);
+                                        return [4 /*yield*/, helper.enterXRAsync(ui._buttons[i].initializationOptions, "eye-level")];
                                     case 3:
                                         _a.sent();
                                         _a.label = 4;
@@ -108969,6 +108956,13 @@ var BABYLON;
                 });
             });
         };
+        WebXREnterExitUI.prototype._updateButtons = function (activeButton) {
+            var _this = this;
+            this._activeButton = activeButton;
+            this._buttons.forEach(function (b) {
+                b.update(_this._activeButton);
+            });
+        };
         /**
          * Disposes of the object
          */
@@ -109005,7 +108999,7 @@ var BABYLON;
             this.canvasContext = null;
             if (!canvas) {
                 canvas = document.createElement('canvas');
-                canvas.style.cssText = "position:absolute; bottom:0px;right:0px;z-index:10;width:100%;height:100%;background-color: #48989e;";
+                canvas.style.cssText = "position:absolute; bottom:0px;right:0px;z-index:10;width:100%;height:100%;background-color: #000000;";
             }
             this._setManagedOutputCanvas(canvas);
             helper.onStateChangedObservable.add(function (stateInfo) {
@@ -109053,6 +109047,104 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.webXRManagedOutputCanvas.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    /**
+     * Represents an XR input
+     */
+    var WebXRController = /** @class */ (function () {
+        /**
+         * Creates the controller
+         * @see https://doc.babylonjs.com/how_to/webxr
+         * @param scene the scene which the controller should be associated to
+         */
+        function WebXRController(scene) {
+            this.pointer = new BABYLON.AbstractMesh("controllerPointer", scene);
+        }
+        /**
+         * Disposes of the object
+         */
+        WebXRController.prototype.dispose = function () {
+            if (this.grip) {
+                this.grip.dispose();
+            }
+            this.pointer.dispose();
+        };
+        return WebXRController;
+    }());
+    BABYLON.WebXRController = WebXRController;
+    /**
+     * XR input used to track XR inputs such as controllers/rays
+     */
+    var WebXRInput = /** @class */ (function () {
+        /**
+         * Initializes the WebXRInput
+         * @param helper experience helper which the input should be created for
+         */
+        function WebXRInput(helper) {
+            var _this = this;
+            this.helper = helper;
+            /**
+             * XR controllers being tracked
+             */
+            this.controllers = [];
+            this._tmpMatrix = new BABYLON.Matrix();
+            this._frameObserver = helper._sessionManager.onXRFrameObservable.add(function () {
+                if (!helper._sessionManager._currentXRFrame || !helper._sessionManager._currentXRFrame.getDevicePose) {
+                    return;
+                }
+                var xrFrame = helper._sessionManager._currentXRFrame;
+                var inputSources = helper._sessionManager._xrSession.getInputSources();
+                inputSources.forEach(function (input, i) {
+                    var inputPose = xrFrame.getInputPose(input, helper._sessionManager._frameOfReference);
+                    if (inputPose) {
+                        if (_this.controllers.length <= i) {
+                            _this.controllers.push(new WebXRController(helper.container.getScene()));
+                        }
+                        var controller = _this.controllers[i];
+                        // Manage the grip if it exists
+                        if (inputPose.gripMatrix) {
+                            if (!controller.grip) {
+                                controller.grip = new BABYLON.AbstractMesh("controllerGrip", helper.container.getScene());
+                            }
+                            BABYLON.Matrix.FromFloat32ArrayToRefScaled(inputPose.gripMatrix, 0, 1, _this._tmpMatrix);
+                            if (!controller.grip.getScene().useRightHandedSystem) {
+                                _this._tmpMatrix.toggleModelMatrixHandInPlace();
+                            }
+                            if (!controller.grip.rotationQuaternion) {
+                                controller.grip.rotationQuaternion = new BABYLON.Quaternion();
+                            }
+                            _this._tmpMatrix.decompose(controller.grip.scaling, controller.grip.rotationQuaternion, controller.grip.position);
+                        }
+                        // Manager pointer of controller
+                        BABYLON.Matrix.FromFloat32ArrayToRefScaled(inputPose.targetRay.transformMatrix, 0, 1, _this._tmpMatrix);
+                        if (!controller.pointer.getScene().useRightHandedSystem) {
+                            _this._tmpMatrix.toggleModelMatrixHandInPlace();
+                        }
+                        if (!controller.pointer.rotationQuaternion) {
+                            controller.pointer.rotationQuaternion = new BABYLON.Quaternion();
+                        }
+                        _this._tmpMatrix.decompose(controller.pointer.scaling, controller.pointer.rotationQuaternion, controller.pointer.position);
+                    }
+                });
+            });
+        }
+        /**
+         * Disposes of the object
+         */
+        WebXRInput.prototype.dispose = function () {
+            this.controllers.forEach(function (c) {
+                c.dispose();
+            });
+            this.helper._sessionManager.onXRFrameObservable.remove(this._frameObserver);
+        };
+        return WebXRInput;
+    }());
+    BABYLON.WebXRInput = WebXRInput;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.webXRInput.js.map
+
 // Mainly based on these 2 articles :
 // Creating an universal virtual touch joystick working for all Touch models thanks to Hand.JS : http://blogs.msdn.com/b/davrous/archive/2013/02/22/creating-an-universal-virtual-touch-joystick-working-for-all-touch-models-thanks-to-hand-js.aspx
 // & on Seb Lee-Delisle original work: http://seb.ly/2011/04/multi-touch-game-controller-in-javascripthtml5-for-ipad/
@@ -119953,7 +120045,9 @@ var BABYLON;
         var _this = this;
         return BABYLON.WebXRExperienceHelper.CreateAsync(this).then(function (helper) {
             var outputCanvas = new BABYLON.WebXRManagedOutputCanvas(helper);
-            return BABYLON.WebXREnterExitUI.CreateAsync(_this, helper, { outputCanvasContext: outputCanvas.canvasContext }).then(function (ui) {
+            return BABYLON.WebXREnterExitUI.CreateAsync(_this, helper, { outputCanvasContext: outputCanvas.canvasContext })
+                .then(function (ui) {
+                new BABYLON.WebXRInput(helper);
                 return helper;
             });
         });

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


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


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

@@ -1254,6 +1254,14 @@ declare module BABYLON.GUI {
         */
     export class Grid extends Container {
             name?: string | undefined;
+            /**
+                * Gets the number of columns
+                */
+            readonly columnCount: number;
+            /**
+                * Gets the number of rows
+                */
+            readonly rowCount: number;
             /** Gets the list of children */
             readonly children: Control[];
             /**
@@ -1287,6 +1295,13 @@ declare module BABYLON.GUI {
                 */
             setColumnDefinition(index: number, width: number, isPixel?: boolean): Grid;
             /**
+                * Gets the list of children stored in a specific cell
+                * @param row defines the row to check
+                * @param column defines the column to check
+                * @returns the list of controls
+                */
+            getChildrenAt(row: number, column: number): BABYLON.Nullable<Array<Control>>;
+            /**
                 * Remove a column definition at specified index
                 * @param index defines the index of the column to remove
                 * @returns the current grid
@@ -1469,7 +1484,7 @@ declare module BABYLON.GUI {
                 */
             keepsFocusWith(): BABYLON.Nullable<Control[]>;
             /** @hidden */
-            processKey(keyCode: number, key?: string): void;
+            processKey(keyCode: number, key?: string, evt?: KeyboardEvent): void;
             /** @hidden */
             processKeyboard(evt: KeyboardEvent): void;
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -2082,6 +2097,7 @@ declare module BABYLON.GUI {
             name?: string | undefined;
             protected _thumbWidth: ValueAndUnit;
             protected _barOffset: ValueAndUnit;
+            protected _displayThumb: boolean;
             protected _effectiveBarOffset: number;
             protected _renderLeft: number;
             protected _renderTop: number;
@@ -2092,6 +2108,8 @@ declare module BABYLON.GUI {
             protected _effectiveThumbThickness: number;
             /** BABYLON.Observable raised when the sldier value changes */
             onValueChangedObservable: BABYLON.Observable<number>;
+            /** Gets or sets a boolean indicating if the thumb must be rendered */
+            displayThumb: boolean;
             /** Gets or sets main bar offset (ie. the margin applied to the value bar) */
             barOffset: string | number;
             /** Gets main bar offset in pixels*/
@@ -2130,8 +2148,6 @@ declare module BABYLON.GUI {
         */
     export class Slider extends BaseSlider {
             name?: string | undefined;
-            /** Gets or sets a boolean indicating if the thumb must be rendered */
-            displayThumb: boolean;
             /** Gets or sets border color */
             borderColor: string;
             /** Gets or sets background color */
@@ -2153,6 +2169,7 @@ declare module BABYLON.GUI {
         */
     export class ImageBasedSlider extends BaseSlider {
             name?: string | undefined;
+            displayThumb: boolean;
             /**
                 * Gets or sets the image used to render the background
                 */

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


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


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


+ 41 - 6
dist/preview release/gui/babylon.gui.module.d.ts

@@ -1363,11 +1363,20 @@ declare module 'babylonjs-gui/2D/controls/grid' {
     import { Container } from "babylonjs-gui/2D/controls/container";
     import { Control } from "babylonjs-gui/2D/controls/control";
     import { Measure } from "babylonjs-gui/2D/measure";
+    import { Nullable } from "babylonjs";
     /**
         * Class used to create a 2D grid container
         */
     export class Grid extends Container {
             name?: string | undefined;
+            /**
+                * Gets the number of columns
+                */
+            readonly columnCount: number;
+            /**
+                * Gets the number of rows
+                */
+            readonly rowCount: number;
             /** Gets the list of children */
             readonly children: Control[];
             /**
@@ -1401,6 +1410,13 @@ declare module 'babylonjs-gui/2D/controls/grid' {
                 */
             setColumnDefinition(index: number, width: number, isPixel?: boolean): Grid;
             /**
+                * Gets the list of children stored in a specific cell
+                * @param row defines the row to check
+                * @param column defines the column to check
+                * @returns the list of controls
+                */
+            getChildrenAt(row: number, column: number): Nullable<Array<Control>>;
+            /**
                 * Remove a column definition at specified index
                 * @param index defines the index of the column to remove
                 * @returns the current grid
@@ -1593,7 +1609,7 @@ declare module 'babylonjs-gui/2D/controls/inputText' {
                 */
             keepsFocusWith(): Nullable<Control[]>;
             /** @hidden */
-            processKey(keyCode: number, key?: string): void;
+            processKey(keyCode: number, key?: string, evt?: KeyboardEvent): void;
             /** @hidden */
             processKeyboard(evt: KeyboardEvent): void;
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -2246,6 +2262,7 @@ declare module 'babylonjs-gui/2D/controls/baseSlider' {
             name?: string | undefined;
             protected _thumbWidth: ValueAndUnit;
             protected _barOffset: ValueAndUnit;
+            protected _displayThumb: boolean;
             protected _effectiveBarOffset: number;
             protected _renderLeft: number;
             protected _renderTop: number;
@@ -2256,6 +2273,8 @@ declare module 'babylonjs-gui/2D/controls/baseSlider' {
             protected _effectiveThumbThickness: number;
             /** Observable raised when the sldier value changes */
             onValueChangedObservable: Observable<number>;
+            /** Gets or sets a boolean indicating if the thumb must be rendered */
+            displayThumb: boolean;
             /** Gets or sets main bar offset (ie. the margin applied to the value bar) */
             barOffset: string | number;
             /** Gets main bar offset in pixels*/
@@ -2297,8 +2316,6 @@ declare module 'babylonjs-gui/2D/controls/slider' {
         */
     export class Slider extends BaseSlider {
             name?: string | undefined;
-            /** Gets or sets a boolean indicating if the thumb must be rendered */
-            displayThumb: boolean;
             /** Gets or sets border color */
             borderColor: string;
             /** Gets or sets background color */
@@ -2324,6 +2341,7 @@ declare module 'babylonjs-gui/2D/controls/imageBasedSlider' {
         */
     export class ImageBasedSlider extends BaseSlider {
             name?: string | undefined;
+            displayThumb: boolean;
             /**
                 * Gets or sets the image used to render the background
                 */
@@ -4180,6 +4198,14 @@ declare module BABYLON.GUI {
         */
     export class Grid extends Container {
             name?: string | undefined;
+            /**
+                * Gets the number of columns
+                */
+            readonly columnCount: number;
+            /**
+                * Gets the number of rows
+                */
+            readonly rowCount: number;
             /** Gets the list of children */
             readonly children: Control[];
             /**
@@ -4213,6 +4239,13 @@ declare module BABYLON.GUI {
                 */
             setColumnDefinition(index: number, width: number, isPixel?: boolean): Grid;
             /**
+                * Gets the list of children stored in a specific cell
+                * @param row defines the row to check
+                * @param column defines the column to check
+                * @returns the list of controls
+                */
+            getChildrenAt(row: number, column: number): BABYLON.Nullable<Array<Control>>;
+            /**
                 * Remove a column definition at specified index
                 * @param index defines the index of the column to remove
                 * @returns the current grid
@@ -4395,7 +4428,7 @@ declare module BABYLON.GUI {
                 */
             keepsFocusWith(): BABYLON.Nullable<Control[]>;
             /** @hidden */
-            processKey(keyCode: number, key?: string): void;
+            processKey(keyCode: number, key?: string, evt?: KeyboardEvent): void;
             /** @hidden */
             processKeyboard(evt: KeyboardEvent): void;
             _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -5008,6 +5041,7 @@ declare module BABYLON.GUI {
             name?: string | undefined;
             protected _thumbWidth: ValueAndUnit;
             protected _barOffset: ValueAndUnit;
+            protected _displayThumb: boolean;
             protected _effectiveBarOffset: number;
             protected _renderLeft: number;
             protected _renderTop: number;
@@ -5018,6 +5052,8 @@ declare module BABYLON.GUI {
             protected _effectiveThumbThickness: number;
             /** BABYLON.Observable raised when the sldier value changes */
             onValueChangedObservable: BABYLON.Observable<number>;
+            /** Gets or sets a boolean indicating if the thumb must be rendered */
+            displayThumb: boolean;
             /** Gets or sets main bar offset (ie. the margin applied to the value bar) */
             barOffset: string | number;
             /** Gets main bar offset in pixels*/
@@ -5056,8 +5092,6 @@ declare module BABYLON.GUI {
         */
     export class Slider extends BaseSlider {
             name?: string | undefined;
-            /** Gets or sets a boolean indicating if the thumb must be rendered */
-            displayThumb: boolean;
             /** Gets or sets border color */
             borderColor: string;
             /** Gets or sets background color */
@@ -5079,6 +5113,7 @@ declare module BABYLON.GUI {
         */
     export class ImageBasedSlider extends BaseSlider {
             name?: string | undefined;
+            displayThumb: boolean;
             /**
                 * Gets or sets the image used to render the background
                 */

+ 3 - 0
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -1637,6 +1637,9 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
                 var _this = this;
+                if (channel.target.node == undefined) {
+                    return Promise.resolve();
+                }
                 var targetNode = ArrayItem.Get(context + "/target/node", this.gltf.nodes, channel.target.node);
                 // Ignore animations that have no animation targets.
                 if ((channel.target.path === "weights" /* WEIGHTS */ && !targetNode._numMorphTargets) ||

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


+ 3 - 0
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -3845,6 +3845,9 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
                 var _this = this;
+                if (channel.target.node == undefined) {
+                    return Promise.resolve();
+                }
                 var targetNode = ArrayItem.Get(context + "/target/node", this.gltf.nodes, channel.target.node);
                 // Ignore animations that have no animation targets.
                 if ((channel.target.path === "weights" /* WEIGHTS */ && !targetNode._numMorphTargets) ||

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


+ 3 - 0
dist/preview release/loaders/babylonjs.loaders.js

@@ -4907,6 +4907,9 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
                 var _this = this;
+                if (channel.target.node == undefined) {
+                    return Promise.resolve();
+                }
                 var targetNode = ArrayItem.Get(context + "/target/node", this.gltf.nodes, channel.target.node);
                 // Ignore animations that have no animation targets.
                 if ((channel.target.path === "weights" /* WEIGHTS */ && !targetNode._numMorphTargets) ||

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


+ 1 - 22
dist/preview release/viewer/babylon.viewer.d.ts

@@ -924,7 +924,7 @@ declare module BabylonViewer {
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 declare module BabylonViewer {
@@ -1558,20 +1558,6 @@ declare module BabylonViewer {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 declare module BabylonViewer {
-    /**
-        * A custom upgrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedUpgrade(sceneManager: SceneManager): boolean;
-    /**
-        * A custom degrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedDegrade(sceneManager: SceneManager): boolean;
-}
-declare module BabylonViewer {
 }
 declare module BabylonViewer {
     export interface IEnvironmentMapConfiguration {
@@ -1724,13 +1710,6 @@ declare module BabylonViewer {
     }
 }
 declare module BabylonViewer {
-    /**
-      * Force-apply material configuration right after a material was loaded.
-      */
-    export class ApplyMaterialConfigPlugin implements ILoaderPlugin {
-        onInit(loader: BABYLON.ISceneLoaderPlugin | BABYLON.ISceneLoaderPluginAsync, model: ViewerModel): void;
-        onMaterialLoaded(material: BABYLON.Material): void;
-    }
 }
 declare module BabylonViewer {
     /**

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


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


+ 2 - 28
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -985,14 +985,13 @@ declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
 }
 
 declare module 'babylonjs-viewer/optimizer/custom' {
-    import { extendedUpgrade } from "babylonjs-viewer/optimizer/custom/extended";
     import { SceneManager } from "babylonjs-viewer/managers/sceneManager";
     /**
       *
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 
@@ -1663,22 +1662,6 @@ declare module 'babylonjs-viewer/loader/plugins' {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 
-declare module 'babylonjs-viewer/optimizer/custom/extended' {
-    import { SceneManager } from 'babylonjs-viewer/managers/sceneManager';
-    /**
-        * A custom upgrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedUpgrade(sceneManager: SceneManager): boolean;
-    /**
-        * A custom degrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedDegrade(sceneManager: SceneManager): boolean;
-}
-
 declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';
@@ -1864,16 +1847,7 @@ declare module 'babylonjs-viewer/loader/plugins/msftLodLoaderPlugin' {
 }
 
 declare module 'babylonjs-viewer/loader/plugins/applyMaterialConfig' {
-    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material } from 'babylonjs';
-    import { ViewerModel } from 'babylonjs-viewer/model/viewerModel';
-    import { ILoaderPlugin } from 'babylonjs-viewer/loader/plugins/loaderPlugin';
-    /**
-      * Force-apply material configuration right after a material was loaded.
-      */
-    export class ApplyMaterialConfigPlugin implements ILoaderPlugin {
-        onInit(loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync, model: ViewerModel): void;
-        onMaterialLoaded(material: Material): void;
-    }
+    
 }
 
 declare module 'babylonjs-viewer/loader/plugins/extendedMaterialLoaderPlugin' {

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

@@ -13,6 +13,8 @@
   - webXRExperienceHelper to setup a default XR experience ([TrevorDev](https://github.com/TrevorDev))
   - WebXREnterExitUI and WebXRManagedOutputCanvas classes to configure the XR experience ([TrevorDev](https://github.com/TrevorDev))
   - WebXRInput manage controllers for the XR experience ([TrevorDev](https://github.com/TrevorDev))
+- GUI:
+  - Added new [ImageBasedSlider](http://doc.babylonjs.com/how_to/gui#imagebasedslider) to let users customize sliders using images ([Deltakosh](https://github.com/deltakosh))
 
 ## Updates
 
@@ -20,6 +22,7 @@
 
 - Added `button.image` and `button.textBlock` to simplify access to button internal parts ([Deltakosh](https://github.com/deltakosh))
 - Added `sldier.displayThumb` to show/hide slider's thumb ([Deltakosh](https://github.com/deltakosh))
+- Added `grid.rowCount`, `grid.columnCount` and `grid.getChildrenAt()` ([Deltakosh](https://github.com/deltakosh))
 
 ### Core Engine
 
@@ -39,7 +42,10 @@
   - Added `blockfreeActiveMeshesAndRenderingGroups` property in the `Scene`, following the same model as `blockMaterialDirtyMechanism`. This is to avoid calling `Scene.freeActiveMeshes` and `Scene.freeRenderingGroups` for each disposed mesh when we dispose several meshes in a row. One have to set `blockfreeActiveMeshesAndRenderingGroups` to `true` just before disposing the meshes, and set it back to `false` just after
   - Prevented code from doing useless and possible time consuming computation when disposing the `ShaderMaterial` of a `LinesMesh`
   - Make a better use of the `isIdentity` cached value wihtin a `Matrix`
+  - Make sure we browse all the submeshes only once in `Material.markAsDirty` function
+  - Added an `Vector3.UnprojectRayToRef` static function to avoid computing and inverting the projection matrix twice when updating a Ray.
 - Align `BoundingBox` and `BoundingSphere` API and behavior for clarity and simplicity. As a consequence, the `BoundingBox`'s method `setWorldMatrix` has been removed and the underlying world matrix cannot be modified but by calling `reConstruct` or `update`. ([barroij](https://github.com/barroij))
+- Make sure that `Material.markAsDirty` and all the `markXXXDirty` methods early out when `scene.blockMaterialDirtyMechanism` is true. ([barroij](https://github.com/barroij))
 
 ### glTF Loader
 
@@ -50,6 +56,7 @@
 ### Materials Library
 
 ## Bug fixes
+- Refocusing on input gui with pointer events ([TrevorDev](https://github.com/TrevorDev))
 
 ### Core Engine
 - Fixed a bug with `mesh.alwaysSelectAsActiveMesh` preventing layerMask to be taken in account ([Deltakosh](https://github.com/deltakosh))
@@ -72,3 +79,21 @@
 - `scene.database` was renamed to `scene.offlineProvider` ([Deltakosh](https://github.com/deltakosh))
 - `BoundingBox.setWorldMatrix` was removed. `BoundingBox.getWorldMatrix` now returns a `Readonly<Matrix>` ([barroij](https://github.com/barroij))
 - `Matrix`'s accessor `m` and method `toArray` and `asArray` now returns a `Readonly<Float32Array>` as the matrix underlying array is not supposed to be modified manually from the outside of the class ([barroij](https://github.com/barroij))
+- Removed some deprecated (flagged since 3.0) properties and functions ([Deltakosh](https://github.com/deltakosh))
+  - `scene.getInterFramePerfCounter()`: use SceneInstrumentation class instead
+  - `scene.interFramePerfCounter`: use SceneInstrumentation class instead
+  - `scene.getLastFrameDuration()`: use SceneInstrumentation class instead
+  - `scene.lastFramePerfCounter`: use SceneInstrumentation class instead
+  - `scene.getEvaluateActiveMeshesDuration()`: use SceneInstrumentation class instead
+  - `scene.evaluateActiveMeshesDurationPerfCounter`: use SceneInstrumentation class instead
+  - `scene.getRenderTargetsDuration()`: use SceneInstrumentation class instead
+  - `scene.getRenderDuration()`: use SceneInstrumentation class instead
+  - `scene.renderDurationPerfCounter`: use SceneInstrumentation class instead
+  - `scene.getParticlesDuration()`: use SceneInstrumentation class instead
+  - `scene.particlesDurationPerfCounter`: use SceneInstrumentation class instead
+  - `scene.getSpritesDuration()`: use SceneInstrumentation class instead
+  - `scene.spriteDuractionPerfCounter`: use SceneInstrumentation class instead
+  - `engine.drawCalls`: use SceneInstrumentation class instead
+  - `engine.drawCallsPerfCounter`: use SceneInstrumentation class instead
+  - `shadowGenerator.useVarianceShadowMap`: use useExponentialShadowMap instead
+  - `shadowGenerator.useBlurVarianceShadowMap`: use useBlurExponentialShadowMap instead

+ 20 - 3
gui/src/2D/controls/baseSlider.ts

@@ -13,6 +13,7 @@ export class BaseSlider extends Control {
     private _isVertical = false;
     protected _barOffset = new ValueAndUnit(5, ValueAndUnit.UNITMODE_PIXEL, false);
     private _isThumbClamped = false;
+    protected _displayThumb = true;
 
     // Shared rendering info
     protected _effectiveBarOffset = 0;
@@ -27,6 +28,20 @@ export class BaseSlider extends Control {
     /** Observable raised when the sldier value changes */
     public onValueChangedObservable = new Observable<number>();
 
+    /** Gets or sets a boolean indicating if the thumb must be rendered */
+    public get displayThumb(): boolean {
+        return this._displayThumb;
+    }
+
+    public set displayThumb(value: boolean) {
+        if (this._displayThumb === value) {
+            return;
+        }
+
+        this._displayThumb = value;
+        this._markAsDirty();
+    }
+
     /** Gets or sets main bar offset (ie. the margin applied to the value bar) */
     public get barOffset(): string | number {
         return this._barOffset.toString(this._host);
@@ -200,7 +215,9 @@ export class BaseSlider extends Control {
         this._backgroundBoxThickness = Math.min(this._currentMeasure.width, this._currentMeasure.height);
         this._effectiveThumbThickness = this._getThumbThickness(type);
 
-        this._backgroundBoxLength -= this._effectiveThumbThickness;
+        if (this.displayThumb) {
+            this._backgroundBoxLength -= this._effectiveThumbThickness;
+        }
         //throw error when height is less than width for vertical slider
         if ((this.isVertical && this._currentMeasure.height < this._currentMeasure.width)) {
             console.error("Height should be greater than width");
@@ -217,7 +234,7 @@ export class BaseSlider extends Control {
 
         if (this.isVertical) {
             this._renderLeft += this._effectiveBarOffset;
-            if (!this.isThumbClamped) {
+            if (!this.isThumbClamped && this.displayThumb) {
                 this._renderTop += (this._effectiveThumbThickness / 2);
             }
 
@@ -227,7 +244,7 @@ export class BaseSlider extends Control {
         }
         else {
             this._renderTop += this._effectiveBarOffset;
-            if (!this.isThumbClamped) {
+            if (!this.isThumbClamped && this.displayThumb) {
                 this._renderLeft += (this._effectiveThumbThickness / 2);
             }
             this._renderHeight = this._backgroundBoxThickness;

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

@@ -2,6 +2,7 @@ import { Container } from "./container";
 import { ValueAndUnit } from "../valueAndUnit";
 import { Control } from "./control";
 import { Measure } from "../measure";
+import { Nullable } from "babylonjs";
 
 /**
  * Class used to create a 2D grid container
@@ -12,6 +13,20 @@ export class Grid extends Container {
     private _cells: { [key: string]: Container } = {};
     private _childControls = new Array<Control>();
 
+    /**
+     * Gets the number of columns
+     */
+    public get columnCount(): number {
+        return this._columnDefinitions.length;
+    }
+
+    /**
+     * Gets the number of rows
+     */
+    public get rowCount(): number {
+        return this._rowDefinitions.length;
+    }
+
     /** Gets the list of children */
     public get children(): Control[] {
         return this._childControls;
@@ -83,6 +98,22 @@ export class Grid extends Container {
         return this;
     }
 
+    /**
+     * Gets the list of children stored in a specific cell
+     * @param row defines the row to check
+     * @param column defines the column to check
+     * @returns the list of controls
+     */
+    public getChildrenAt(row: number, column: number): Nullable<Array<Control>> {
+        const cell = this._cells[`${row}:${column}`];
+
+        if (!cell) {
+            return null;
+        }
+
+        return cell.children;
+    }
+
     private _removeCell(cell: Container, key: string) {
         if (!cell) {
             return;

+ 23 - 7
gui/src/2D/controls/imageBasedSlider.ts

@@ -12,6 +12,19 @@ export class ImageBasedSlider extends BaseSlider {
 
     private _tempMeasure = new Measure(0, 0, 0, 0);
 
+    public get displayThumb(): boolean {
+        return this._displayThumb && this.thumbImage != null;
+    }
+
+    public set displayThumb(value: boolean) {
+        if (this._displayThumb === value) {
+            return;
+        }
+
+        this._displayThumb = value;
+        this._markAsDirty();
+    }
+
     /**
      * Gets or sets the image used to render the background
      */
@@ -103,13 +116,12 @@ export class ImageBasedSlider extends BaseSlider {
             // Background
             if (this._backgroundImage) {
                 this._tempMeasure.copyFromFloats(left, top, width, height);
-                if (this.isThumbClamped) {
+                if (this.isThumbClamped && this.displayThumb) {
                     if (this.isVertical) {
                         this._tempMeasure.height += this._effectiveThumbThickness;
                     } else {
                         this._tempMeasure.width += this._effectiveThumbThickness;
                     }
-
                 }
                 this._backgroundImage._draw(this._tempMeasure, context);
             }
@@ -117,20 +129,24 @@ export class ImageBasedSlider extends BaseSlider {
             // Bar
             if (this._valueBarImage) {
                 if (this.isVertical) {
-                    this._tempMeasure.copyFromFloats(left, top + thumbPosition, width, height - thumbPosition);
-                    if (this.isThumbClamped) {
-                        this._tempMeasure.copyFromFloats(left, top + thumbPosition, width, this._currentMeasure.height - thumbPosition);
+                    if (this.isThumbClamped && this.displayThumb) {
+                        this._tempMeasure.copyFromFloats(left, top + thumbPosition, width, height - thumbPosition + this._effectiveThumbThickness);
                     } else {
                         this._tempMeasure.copyFromFloats(left, top + thumbPosition, width, height - thumbPosition);
                     }
                 } else {
-                    this._tempMeasure.copyFromFloats(left, top, thumbPosition + this._effectiveThumbThickness / 2, height);
+                    if (this.isThumbClamped && this.displayThumb) {
+                        this._tempMeasure.copyFromFloats(left, top, thumbPosition + this._effectiveThumbThickness / 2, height);
+                    }
+                    else {
+                        this._tempMeasure.copyFromFloats(left, top, thumbPosition, height);
+                    }
                 }
                 this._valueBarImage._draw(this._tempMeasure, context);
             }
 
             // Thumb
-            if (this._thumbImage) {
+            if (this.displayThumb) {
                 if (this.isVertical) {
                     this._tempMeasure.copyFromFloats(left - this._effectiveBarOffset, this._currentMeasure.top + thumbPosition, this._currentMeasure.width, this._effectiveThumbThickness);
                 } else {

Разлика између датотеке није приказан због своје велике величине
+ 570 - 559
gui/src/2D/controls/inputText.ts


+ 1 - 16
gui/src/2D/controls/slider.ts

@@ -8,21 +8,6 @@ export class Slider extends BaseSlider {
     private _background = "black";
     private _borderColor = "white";
     private _isThumbCircle = false;
-    private _displayThumb = true;
-
-    /** Gets or sets a boolean indicating if the thumb must be rendered */
-    public get displayThumb(): boolean {
-        return this._displayThumb;
-    }
-
-    public set displayThumb(value: boolean) {
-        if (this._displayThumb === value) {
-            return;
-        }
-
-        this._displayThumb = value;
-        this._markAsDirty();
-    }
 
     /** Gets or sets border color */
     public get borderColor(): string {
@@ -166,7 +151,7 @@ export class Slider extends BaseSlider {
                         context.fillRect(left, top + thumbPosition, width, height - thumbPosition);
                     }
                     else {
-                        context.fillRect(left, top + thumbPosition, width, this._currentMeasure.height - thumbPosition);
+                        context.fillRect(left, top + thumbPosition, width, height - thumbPosition + this._effectiveThumbThickness);
                     }
                 }
                 else {

+ 1 - 1
src/Cameras/XR/babylon.webXRInput.ts

@@ -49,7 +49,7 @@ module BABYLON {
         public constructor(private helper: WebXRExperienceHelper) {
             this._frameObserver = helper._sessionManager.onXRFrameObservable.add(() => {
                 if (!helper._sessionManager._currentXRFrame || !helper._sessionManager._currentXRFrame.getDevicePose) {
-                    return false;
+                    return;
                 }
 
                 var xrFrame = helper._sessionManager._currentXRFrame;

+ 37 - 31
src/Culling/babylon.ray.ts

@@ -3,14 +3,7 @@ module BABYLON {
      * Class representing a ray with position and direction
      */
     export class Ray {
-        private static readonly _edge1 = Vector3.Zero();
-        private static readonly _edge2 = Vector3.Zero();
-        private static readonly _pvec = Vector3.Zero();
-        private static readonly _tvec = Vector3.Zero();
-        private static readonly _qvec = Vector3.Zero();
-        private static readonly _min = Vector3.Zero();
-        private static readonly _max = Vector3.Zero();
-
+        private static readonly TmpVector3 = Tools.BuildArray(6, Vector3.Zero);
         private _tmpRay: Ray;
 
         /**
@@ -37,8 +30,8 @@ module BABYLON {
          * @returns if the box was hit
          */
         public intersectsBoxMinMax(minimum: Vector3, maximum: Vector3, intersectionTreshold: number = 0): boolean {
-            const newMinimum = Ray._min.copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
-            const newMaximum = Ray._max.copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
+            const newMinimum = Ray.TmpVector3[0].copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
+            const newMaximum = Ray.TmpVector3[1].copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
             var d = 0.0;
             var maxValue = Number.MAX_VALUE;
             var inv: number;
@@ -176,10 +169,16 @@ module BABYLON {
          * @returns intersection information if hit
          */
         public intersectsTriangle(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3): Nullable<IntersectionInfo> {
-            vertex1.subtractToRef(vertex0, Ray._edge1);
-            vertex2.subtractToRef(vertex0, Ray._edge2);
-            Vector3.CrossToRef(this.direction, Ray._edge2, Ray._pvec);
-            var det = Vector3.Dot(Ray._edge1, Ray._pvec);
+            const edge1 = Ray.TmpVector3[0];
+            const edge2 = Ray.TmpVector3[1];
+            const pvec = Ray.TmpVector3[2];
+            const tvec = Ray.TmpVector3[3];
+            const qvec =  Ray.TmpVector3[4];
+
+            vertex1.subtractToRef(vertex0, edge1);
+            vertex2.subtractToRef(vertex0, edge2);
+            Vector3.CrossToRef(this.direction, edge2, pvec);
+            var det = Vector3.Dot(edge1, pvec);
 
             if (det === 0) {
                 return null;
@@ -187,24 +186,24 @@ module BABYLON {
 
             var invdet = 1 / det;
 
-            this.origin.subtractToRef(vertex0, Ray._tvec);
+            this.origin.subtractToRef(vertex0, tvec);
 
-            var bu = Vector3.Dot(Ray._tvec, Ray._pvec) * invdet;
+            var bu = Vector3.Dot(tvec, pvec) * invdet;
 
             if (bu < 0 || bu > 1.0) {
                 return null;
             }
 
-            Vector3.CrossToRef(Ray._tvec, Ray._edge1, Ray._qvec);
+            Vector3.CrossToRef(tvec, edge1, qvec);
 
-            var bv = Vector3.Dot(this.direction, Ray._qvec) * invdet;
+            var bv = Vector3.Dot(this.direction, qvec) * invdet;
 
             if (bv < 0 || bu + bv > 1.0) {
                 return null;
             }
 
             //check if the distance is longer than the predefined length.
-            var distance = Vector3.Dot(Ray._edge2, Ray._qvec) * invdet;
+            var distance = Vector3.Dot(edge2, qvec) * invdet;
             if (distance > this.length) {
                 return null;
             }
@@ -312,11 +311,19 @@ module BABYLON {
          * @return the distance from the ray origin to the intersection point if there's intersection, or -1 if there's no intersection
          */
         intersectionSegment(sega: Vector3, segb: Vector3, threshold: number): number {
-            var rsegb = this.origin.add(this.direction.multiplyByFloats(Ray.rayl, Ray.rayl, Ray.rayl));
+            const o = this.origin;
+            const u =  Tmp.Vector3[0];
+            const rsegb  = Tmp.Vector3[1];
+            const v =  Tmp.Vector3[2];
+            const w =  Tmp.Vector3[3];
+
+            segb.subtractToRef(sega, u);
+
+            this.direction.scaleToRef(Ray.rayl, v);
+            o.addToRef(v, rsegb);
+
+            sega.subtractToRef(o, w);
 
-            var u = segb.subtract(sega);
-            var v = rsegb.subtract(this.origin);
-            var w = sega.subtract(this.origin);
             var a = Vector3.Dot(u, u);                  // always >= 0
             var b = Vector3.Dot(u, v);
             var c = Vector3.Dot(v, v);                  // always >= 0
@@ -376,8 +383,11 @@ module BABYLON {
             tc = (Math.abs(tN) < Ray.smallnum ? 0.0 : tN / tD);
 
             // get the difference of the two closest points
-            let qtc = v.multiplyByFloats(tc, tc, tc);
-            var dP = w.add(u.multiplyByFloats(sc, sc, sc)).subtract(qtc);  // = S1(sc) - S2(tc)
+            const qtc = Tmp.Vector3[4];
+            v.scaleToRef(tc, qtc);
+            const dP = Tmp.Vector3[5];
+            u.scaleToRef(sc, dP);
+            dP.addInPlace(w).subtractInPlace(qtc);  // = S1(sc) - S2(tc)
 
             var isIntersected = (tc > 0) && (tc <= this.length) && (dP.lengthSquared() < (threshold * threshold));   // return intersection result
 
@@ -398,12 +408,8 @@ module BABYLON {
          * @param projection projection matrix
          * @returns this ray updated
          */
-        public update(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray {
-            Vector3.UnprojectFloatsToRef(x, y, 0, viewportWidth, viewportHeight, world, view, projection, this.origin);
-            Vector3.UnprojectFloatsToRef(x, y, 1, viewportWidth, viewportHeight, world, view, projection, Tmp.Vector3[0]);
-
-            Tmp.Vector3[0].subtractToRef(this.origin, this.direction);
-            this.direction.normalize();
+        public update(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Readonly<Matrix>, view: Readonly<Matrix>, projection: Readonly<Matrix>): Ray {
+            Vector3.UnprojectRayToRef(x, y, viewportWidth, viewportHeight, world, view, projection, this);
             return this;
         }
 

+ 0 - 12
src/Engine/babylon.engine.ts

@@ -1664,18 +1664,6 @@ module BABYLON {
             return this._caps;
         }
 
-        /** @hidden */
-        public get drawCalls(): number {
-            Tools.Warn("drawCalls is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        }
-
-        /** @hidden */
-        public get drawCallsPerfCounter(): Nullable<PerfCounter> {
-            Tools.Warn("drawCallsPerfCounter is deprecated. Please use SceneInstrumentation class");
-            return null;
-        }
-
         /**
          * Gets the current depth function
          * @returns a number defining the depth function

+ 6 - 35
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -346,40 +346,6 @@ module BABYLON {
         }
 
         /**
-         * Gets if the current filter is set to VSM.
-         * DEPRECATED. Should use useExponentialShadowMap instead.
-         */
-        public get useVarianceShadowMap(): boolean {
-            Tools.Warn("VSM are now replaced by ESM. Please use useExponentialShadowMap instead.");
-            return this.useExponentialShadowMap;
-        }
-        /**
-         * Sets the current filter is to VSM.
-         * DEPRECATED. Should use useExponentialShadowMap instead.
-         */
-        public set useVarianceShadowMap(value: boolean) {
-            Tools.Warn("VSM are now replaced by ESM. Please use useExponentialShadowMap instead.");
-            this.useExponentialShadowMap = value;
-        }
-
-        /**
-         * Gets if the current filter is set to blurred VSM.
-         * DEPRECATED. Should use useBlurExponentialShadowMap instead.
-         */
-        public get useBlurVarianceShadowMap(): boolean {
-            Tools.Warn("VSM are now replaced by ESM. Please use useBlurExponentialShadowMap instead.");
-            return this.useBlurExponentialShadowMap;
-        }
-        /**
-         * Sets the current filter is to blurred VSM.
-         * DEPRECATED. Should use useBlurExponentialShadowMap instead.
-         */
-        public set useBlurVarianceShadowMap(value: boolean) {
-            Tools.Warn("VSM are now replaced by ESM. Please use useBlurExponentialShadowMap instead.");
-            this.useBlurExponentialShadowMap = value;
-        }
-
-        /**
          * Gets if the current filter is set to ESM.
          */
         public get useExponentialShadowMap(): boolean {
@@ -865,7 +831,7 @@ module BABYLON {
             var engine = scene.getEngine();
             let material = subMesh.getMaterial();
 
-            if (!material) {
+            if (!material || subMesh.verticesCount === 0) {
                 return;
             }
 
@@ -912,6 +878,11 @@ module BABYLON {
 
                     if (skeleton.isUsingTextureForMatrices) {
                         const boneTexture = skeleton.getTransformMatrixTexture();
+
+                        if (!boneTexture) {
+                            return;
+                        }
+
                         this._effect.setTexture("boneSampler", boneTexture);
                         this._effect.setFloat("boneTextureWidth", 4.0 * (skeleton.bones.length + 1));
                     } else {

+ 53 - 20
src/Materials/babylon.material.ts

@@ -1154,29 +1154,63 @@ module BABYLON {
             });
         }
 
+        private static readonly _ImageProcessingDirtyCallBack = (defines: MaterialDefines) => defines.markAsImageProcessingDirty();
+        private static readonly _TextureDirtyCallBack = (defines: MaterialDefines) => defines.markAsTexturesDirty();
+        private static readonly _FresnelDirtyCallBack = (defines: MaterialDefines) => defines.markAsFresnelDirty();
+        private static readonly _MiscDirtyCallBack = (defines: MaterialDefines) => defines.markAsMiscDirty();
+        private static readonly _LightsDirtyCallBack = (defines: MaterialDefines) => defines.markAsLightDirty();
+        private static readonly _AttributeDirtyCallBack = (defines: MaterialDefines) => defines.markAsAttributesDirty();
+
+        private static _FresnelAndMiscDirtyCallBack = (defines: MaterialDefines) => {
+            Material._FresnelDirtyCallBack(defines);
+            Material._MiscDirtyCallBack(defines);
+        }
+
+        private static _TextureAndMiscDirtyCallBack = (defines: MaterialDefines) => {
+            Material._TextureDirtyCallBack(defines);
+            Material._MiscDirtyCallBack(defines);
+        }
+
+        private static readonly _DirtyCallbackArray: Array<(defines: MaterialDefines) => void> = [];
+        private static readonly _RunDirtyCallBacks = (defines: MaterialDefines) => {
+            for (const cb of Material._DirtyCallbackArray) {
+                cb(defines);
+            }
+        }
+
         /**
          * Marks a define in the material to indicate that it needs to be re-computed
          * @param flag defines a flag used to determine which parts of the material have to be marked as dirty
          */
         public markAsDirty(flag: number): void {
+            if (this.getScene().blockMaterialDirtyMechanism) {
+                return;
+            }
+
+            Material._DirtyCallbackArray.length = 0;
+
             if (flag & Material.TextureDirtyFlag) {
-                this._markAllSubMeshesAsTexturesDirty();
+                Material._DirtyCallbackArray.push(Material._TextureDirtyCallBack);
             }
 
             if (flag & Material.LightDirtyFlag) {
-                this._markAllSubMeshesAsLightsDirty();
+                Material._DirtyCallbackArray.push(Material._LightsDirtyCallBack);
             }
 
             if (flag & Material.FresnelDirtyFlag) {
-                this._markAllSubMeshesAsFresnelDirty();
+                Material._DirtyCallbackArray.push(Material._FresnelDirtyCallBack);
             }
 
             if (flag & Material.AttributesDirtyFlag) {
-                this._markAllSubMeshesAsAttributesDirty();
+                Material._DirtyCallbackArray.push(Material._AttributeDirtyCallBack);
             }
 
             if (flag & Material.MiscDirtyFlag) {
-                this._markAllSubMeshesAsMiscDirty();
+                Material._DirtyCallbackArray.push(Material._MiscDirtyCallBack);
+            }
+
+            if (Material._DirtyCallbackArray.length) {
+                this._markAllSubMeshesAsDirty(Material._RunDirtyCallBacks);
             }
 
             this.getScene().resetCachedMaterial();
@@ -1187,7 +1221,12 @@ module BABYLON {
          * @param func defines a function which checks material defines against the submeshes
          */
         protected _markAllSubMeshesAsDirty(func: (defines: MaterialDefines) => void) {
-            for (var mesh of this.getScene().meshes) {
+            if (this.getScene().blockMaterialDirtyMechanism) {
+                return;
+            }
+
+            const meshes = this.getScene().meshes;
+            for (var mesh of meshes) {
                 if (!mesh.subMeshes) {
                     continue;
                 }
@@ -1209,62 +1248,56 @@ module BABYLON {
          * Indicates that image processing needs to be re-calculated for all submeshes
          */
         protected _markAllSubMeshesAsImageProcessingDirty() {
-            this._markAllSubMeshesAsDirty((defines) => defines.markAsImageProcessingDirty());
+            this._markAllSubMeshesAsDirty(Material._ImageProcessingDirtyCallBack);
         }
 
         /**
          * Indicates that textures need to be re-calculated for all submeshes
          */
         protected _markAllSubMeshesAsTexturesDirty() {
-            this._markAllSubMeshesAsDirty((defines) => defines.markAsTexturesDirty());
+            this._markAllSubMeshesAsDirty(Material._TextureDirtyCallBack);
         }
 
         /**
          * Indicates that fresnel needs to be re-calculated for all submeshes
          */
         protected _markAllSubMeshesAsFresnelDirty() {
-            this._markAllSubMeshesAsDirty((defines) => defines.markAsFresnelDirty());
+            this._markAllSubMeshesAsDirty(Material._FresnelDirtyCallBack);
         }
 
         /**
          * Indicates that fresnel and misc need to be re-calculated for all submeshes
          */
         protected _markAllSubMeshesAsFresnelAndMiscDirty() {
-            this._markAllSubMeshesAsDirty((defines) => {
-                defines.markAsFresnelDirty();
-                defines.markAsMiscDirty();
-            });
+            this._markAllSubMeshesAsDirty(Material._FresnelAndMiscDirtyCallBack);
         }
 
         /**
          * Indicates that lights need to be re-calculated for all submeshes
          */
         protected _markAllSubMeshesAsLightsDirty() {
-            this._markAllSubMeshesAsDirty((defines) => defines.markAsLightDirty());
+            this._markAllSubMeshesAsDirty(Material._LightsDirtyCallBack);
         }
 
         /**
          * Indicates that attributes need to be re-calculated for all submeshes
          */
         protected _markAllSubMeshesAsAttributesDirty() {
-            this._markAllSubMeshesAsDirty((defines) => defines.markAsAttributesDirty());
+            this._markAllSubMeshesAsDirty(Material._AttributeDirtyCallBack);
         }
 
         /**
          * Indicates that misc needs to be re-calculated for all submeshes
          */
         protected _markAllSubMeshesAsMiscDirty() {
-            this._markAllSubMeshesAsDirty((defines) => defines.markAsMiscDirty());
+            this._markAllSubMeshesAsDirty(Material._MiscDirtyCallBack);
         }
 
         /**
          * Indicates that textures and misc need to be re-calculated for all submeshes
          */
         protected _markAllSubMeshesAsTexturesAndMiscDirty() {
-            this._markAllSubMeshesAsDirty((defines) => {
-                defines.markAsTexturesDirty();
-                defines.markAsMiscDirty();
-            });
+            this._markAllSubMeshesAsDirty(Material._TextureAndMiscDirtyCallBack);
         }
 
         /**

+ 44 - 15
src/Math/babylon.math.ts

@@ -2151,7 +2151,7 @@ module BABYLON {
 
         /**
          * Returns a new Vector3 set from the index "offset" of the given Float32Array
-         * This function is deprecated.  Use FromArray instead
+         * This function is deprecated. Use FromArray instead
          * @param array defines the source array
          * @param offset defines the offset in the source array
          * @returns the new Vector3
@@ -2538,6 +2538,16 @@ module BABYLON {
             return Vector3.TransformCoordinates(vector, matrix);
         }
 
+        /** @hidden */
+        private static UnprojectFromInvertedMatrixToRef(source: Vector3, matrix: Readonly<Matrix>, result: Vector3) {
+            Vector3.TransformCoordinatesToRef(source, matrix, result);
+            const m = matrix.m;
+            var num = source.x * m[3] + source.y * m[7] + source.z * m[11] + m[15];
+            if (Scalar.WithinEpsilon(num, 1.0)) {
+                result.scaleInPlace(1.0 / num);
+            }
+        }
+
         /**
          * Unproject from screen space to object space
          * @param source defines the screen space Vector3 to use
@@ -2553,14 +2563,8 @@ module BABYLON {
             matrix.invert();
             source.x = source.x / viewportWidth * 2 - 1;
             source.y = -(source.y / viewportHeight * 2 - 1);
-            var vector = Vector3.TransformCoordinates(source, matrix);
-            const m = matrix.m;
-            var num = source.x * m[3] + source.y * m[7] + source.z * m[11] + m[15];
-
-            if (Scalar.WithinEpsilon(num, 1.0)) {
-                vector = vector.scale(1.0 / num);
-            }
-
+            const vector = new Vector3();
+            Vector3.UnprojectFromInvertedMatrixToRef(source, matrix, vector);
             return vector;
         }
 
@@ -2617,13 +2621,38 @@ module BABYLON {
             screenSource.x = sourceX / viewportWidth * 2 - 1;
             screenSource.y = -(sourceY / viewportHeight * 2 - 1);
             screenSource.z = 2 * sourceZ - 1.0;
-            Vector3.TransformCoordinatesToRef(screenSource, matrix, result);
-            const m = matrix.m;
-            var num = screenSource.x * m[3] + screenSource.y * m[7] + screenSource.z * m[11] + m[15];
+            Vector3.UnprojectFromInvertedMatrixToRef(screenSource, matrix, result);
+        }
 
-            if (Scalar.WithinEpsilon(num, 1.0)) {
-                result.scaleInPlace(1.0 / num);
-            }
+       /**
+         * Unproject a ray from screen space to object space
+         * @param sourceX defines the screen space x coordinate to use
+         * @param sourceY defines the screen space y coordinate to use
+         * @param viewportWidth defines the current width of the viewport
+         * @param viewportHeight defines the current height of the viewport
+         * @param world defines the world matrix to use (can be set to Identity to go to world space)
+         * @param view defines the view matrix to use
+         * @param projection defines the projection matrix to use
+         * @param ray defines the Ray where to store the result
+         */
+        public static UnprojectRayToRef(sourceX: float, sourceY: float, viewportWidth: number, viewportHeight: number, world: Readonly<Matrix>, view: Readonly<Matrix>, projection: Readonly<Matrix>, ray: Ray): void {
+            var matrix = MathTmp.Matrix[0];
+            world.multiplyToRef(view, matrix);
+            matrix.multiplyToRef(projection, matrix);
+            matrix.invert();
+            var nearScreenSource = MathTmp.Vector3[0];
+            nearScreenSource.x = sourceX / viewportWidth * 2 - 1;
+            nearScreenSource.y = -(sourceY / viewportHeight * 2 - 1);
+            nearScreenSource.z = -1.0;
+            var farScreenSource = MathTmp.Vector3[1].copyFromFloats(nearScreenSource.x, nearScreenSource.y, 1.0);
+            const nearVec3 = MathTmp.Vector3[2];
+            const farVec3 = MathTmp.Vector3[3];
+            Vector3.UnprojectFromInvertedMatrixToRef(nearScreenSource, matrix, nearVec3);
+            Vector3.UnprojectFromInvertedMatrixToRef(farScreenSource, matrix, farVec3);
+
+            ray.origin.copyFrom(nearVec3);
+            farVec3.subtractToRef(nearVec3, ray.direction);
+            ray.direction.normalize();
         }
 
         /**

+ 4 - 1
src/Particles/babylon.gpuParticleSystem.ts

@@ -38,7 +38,7 @@ module BABYLON {
         private _randomTexture: RawTexture;
         private _randomTexture2: RawTexture;
 
-        private _attributesStrideSize = 21;
+        private _attributesStrideSize: number;
         private _updateEffectOptions: EffectCreationOptions;
 
         private _randomTextureSize: number;
@@ -788,6 +788,9 @@ module BABYLON {
             let engine = this._scene.getEngine();
             var data = new Array<float>();
 
+            this._attributesStrideSize = 21;
+            this._targetIndex = 0;
+
             if (!this.isBillboardBased) {
                 this._attributesStrideSize += 3;
             }

+ 28 - 87
src/babylon.scene.ts

@@ -507,6 +507,11 @@ module BABYLON {
         public onAfterStepObservable = new Observable<Scene>();
 
         /**
+         * An event triggered when the activeCamera property is updated
+         */
+        public onActiveCameraChanged = new Observable<Scene>();
+
+        /**
          * This Observable will be triggered before rendering each renderingGroup of each rendered camera.
          * The RenderinGroupInfo class contains all the information about the context in which the observable is called
          * If you wish to register an Observer only for a given set of renderingGroup, use the mask with a combination of the renderingGroup index elevated to the power of two (1 for renderingGroup 0, 2 for renderingrOup1, 4 for 2 and 8 for 3)
@@ -545,13 +550,13 @@ module BABYLON {
         private _onPointerDown: (evt: PointerEvent) => void;
         private _onPointerUp: (evt: PointerEvent) => void;
 
-        /** Deprecated. Use onPointerObservable instead */
+        /** Callback called when a pointer move is detected */
         public onPointerMove: (evt: PointerEvent, pickInfo: PickingInfo, type: PointerEventTypes) => void;
-        /** Deprecated. Use onPointerObservable instead */
+        /** Callback called when a pointer down is detected  */
         public onPointerDown: (evt: PointerEvent, pickInfo: PickingInfo, type: PointerEventTypes) => void;
-        /** Deprecated. Use onPointerObservable instead */
+        /** Callback called when a pointer up is detected  */
         public onPointerUp: (evt: PointerEvent, pickInfo: Nullable<PickingInfo>, type: PointerEventTypes) => void;
-        /** Deprecated. Use onPointerObservable instead */
+        /** Callback called when a pointer pick is detected */
         public onPointerPick: (evt: PointerEvent, pickInfo: PickingInfo) => void;
 
         /**
@@ -776,8 +781,21 @@ module BABYLON {
 
         /** All of the active cameras added to this scene. */
         public activeCameras = new Array<Camera>();
-        /** The current active camera */
-        public activeCamera: Nullable<Camera>;
+
+        private _activeCamera: Nullable<Camera>;
+        /** Gets or sets the current active camera */
+        public get activeCamera(): Nullable<Camera> {
+            return this._activeCamera;
+        }
+
+        public set activeCamera(value: Nullable<Camera>) {
+            if (value === this._activeCamera) {
+                return;
+            }
+
+            this._activeCamera = value;
+            this.onActiveCameraChanged.notifyObservers(this);
+        }
 
         private _defaultMaterial: Material;
 
@@ -1439,42 +1457,6 @@ module BABYLON {
             return this._activeBones;
         }
 
-        /** @hidden */
-        public getInterFramePerfCounter(): number {
-            Tools.Warn("getInterFramePerfCounter is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        }
-
-        /** @hidden */
-        public get interFramePerfCounter(): Nullable<PerfCounter> {
-            Tools.Warn("interFramePerfCounter is deprecated. Please use SceneInstrumentation class");
-            return null;
-        }
-
-        /** @hidden */
-        public getLastFrameDuration(): number {
-            Tools.Warn("getLastFrameDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        }
-
-        /** @hidden */
-        public get lastFramePerfCounter(): Nullable<PerfCounter> {
-            Tools.Warn("lastFramePerfCounter is deprecated. Please use SceneInstrumentation class");
-            return null;
-        }
-
-        /** @hidden */
-        public getEvaluateActiveMeshesDuration(): number {
-            Tools.Warn("getEvaluateActiveMeshesDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        }
-
-        /** @hidden */
-        public get evaluateActiveMeshesDurationPerfCounter(): Nullable<PerfCounter> {
-            Tools.Warn("evaluateActiveMeshesDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
-            return null;
-        }
-
         /**
          * Gets the array of active meshes
          * @returns an array of AbstractMesh
@@ -1483,48 +1465,6 @@ module BABYLON {
             return this._activeMeshes;
         }
 
-        /** @hidden */
-        public getRenderTargetsDuration(): number {
-            Tools.Warn("getRenderTargetsDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        }
-
-        /** @hidden */
-        public getRenderDuration(): number {
-            Tools.Warn("getRenderDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        }
-
-        /** @hidden */
-        public get renderDurationPerfCounter(): Nullable<PerfCounter> {
-            Tools.Warn("renderDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
-            return null;
-        }
-
-        /** @hidden */
-        public getParticlesDuration(): number {
-            Tools.Warn("getParticlesDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        }
-
-        /** @hidden */
-        public get particlesDurationPerfCounter(): Nullable<PerfCounter> {
-            Tools.Warn("particlesDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
-            return null;
-        }
-
-        /** @hidden */
-        public getSpritesDuration(): number {
-            Tools.Warn("getSpritesDuration is deprecated. Please use SceneInstrumentation class");
-            return 0;
-        }
-
-        /** @hidden */
-        public get spriteDuractionPerfCounter(): Nullable<PerfCounter> {
-            Tools.Warn("spriteDuractionPerfCounter is deprecated. Please use SceneInstrumentation class");
-            return null;
-        }
-
         /**
          * Gets the animation ratio (which is 1.0 is the scene renders at 60fps and 2 if the scene renders at 30fps, etc.)
          * @returns a number
@@ -2083,6 +2023,8 @@ module BABYLON {
                 }
 
                 this._initClickEvent(this.onPrePointerObservable, this.onPointerObservable, evt, (clickInfo: ClickInfo, pickResult: Nullable<PickingInfo>) => {
+                    this._pointerCaptures[evt.pointerId] = false;
+
                     // PreObservable support
                     if (this.onPrePointerObservable.hasObservers()) {
                         if (!clickInfo.ignore) {
@@ -2108,8 +2050,6 @@ module BABYLON {
                         return;
                     }
 
-                    this._pointerCaptures[evt.pointerId] = false;
-
                     if (!this.pointerUpPredicate) {
                         this.pointerUpPredicate = (mesh: AbstractMesh): boolean => {
                             return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.isEnabled();
@@ -4874,6 +4814,7 @@ module BABYLON {
             this.onPointerObservable.clear();
             this.onPreKeyboardObservable.clear();
             this.onKeyboardObservable.clear();
+            this.onActiveCameraChanged.clear();
 
             this.detachControl();
 
@@ -5079,7 +5020,7 @@ module BABYLON {
             x = x / this._engine.getHardwareScalingLevel() - viewport.x;
             y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
 
-            result.update(x, y, viewport.width, viewport.height, world ? world : Matrix.Identity(), cameraViewSpace ? Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
+            result.update(x, y, viewport.width, viewport.height, world ? world : Matrix.IdentityReadOnly, cameraViewSpace ? Matrix.IdentityReadOnly : camera.getViewMatrix(), camera.getProjectionMatrix());
             return this;
         }
 

BIN
tests/validation/ReferenceImages/Sliders.png


Разлика између датотеке није приказан због своје велике величине
+ 589 - 583
tests/validation/config.json