David Catuhe 7 years ago
parent
commit
47f14f92f2

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


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


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


+ 78 - 14
dist/preview release/babylon.max.js

@@ -28588,7 +28588,7 @@ var BABYLON;
          */
         Scene.prototype.pickWithRay = function (ray, predicate, fastCheck) {
             var _this = this;
-            return this._internalPick(function (world) {
+            var result = this._internalPick(function (world) {
                 if (!_this._pickWithRayInverseMatrix) {
                     _this._pickWithRayInverseMatrix = BABYLON.Matrix.Identity();
                 }
@@ -28599,6 +28599,10 @@ var BABYLON;
                 BABYLON.Ray.TransformToRef(ray, _this._pickWithRayInverseMatrix, _this._cachedRayForTransform);
                 return _this._cachedRayForTransform;
             }, predicate, fastCheck);
+            if (result) {
+                result.ray = ray;
+            }
+            return result;
         };
         /**
          * Launch a ray to try to pick a mesh in the scene
@@ -51830,6 +51834,10 @@ var BABYLON;
             this._to = -Number.MAX_VALUE;
             this._speedRatio = 1;
             this.onAnimationEndObservable = new BABYLON.Observable();
+            /**
+             * This observable will notify when all animations have ended.
+             */
+            this.onAnimationGroupEndObservable = new BABYLON.Observable();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.animationGroups.push(this);
         }
@@ -51986,9 +51994,12 @@ var BABYLON;
                 return this;
             }
             var _loop_1 = function (targetedAnimation) {
-                this_1._animatables.push(this_1._scene.beginDirectAnimation(targetedAnimation.target, [targetedAnimation.animation], from !== undefined ? from : this_1._from, to !== undefined ? to : this_1._to, loop, speedRatio, function () {
+                var animatable = this_1._scene.beginDirectAnimation(targetedAnimation.target, [targetedAnimation.animation], from !== undefined ? from : this_1._from, to !== undefined ? to : this_1._to, loop, speedRatio);
+                animatable.onAnimationEnd = function () {
                     _this.onAnimationEndObservable.notifyObservers(targetedAnimation);
-                }));
+                    _this._checkAnimationGroupEnded(animatable);
+                };
+                this_1._animatables.push(animatable);
             };
             var this_1 = this;
             for (var _i = 0, _a = this._targetedAnimations; _i < _a.length; _i++) {
@@ -52018,7 +52029,8 @@ var BABYLON;
          * @param loop defines if animations must loop
          */
         AnimationGroup.prototype.play = function (loop) {
-            if (this.isStarted) {
+            // only if all animatables are ready and exist
+            if (this.isStarted && this._animatables.length === this._targetedAnimations.length) {
                 if (loop !== undefined) {
                     for (var index = 0; index < this._animatables.length; index++) {
                         var animatable = this._animatables[index];
@@ -52028,6 +52040,7 @@ var BABYLON;
                 this.restart();
             }
             else {
+                this.stop();
                 this.start(loop, this._speedRatio);
             }
             return this;
@@ -52124,6 +52137,18 @@ var BABYLON;
                 this._scene.animationGroups.splice(index, 1);
             }
         };
+        AnimationGroup.prototype._checkAnimationGroupEnded = function (animatable) {
+            // animatable should be taken out of the array
+            var idx = this._animatables.indexOf(animatable);
+            if (idx > -1) {
+                this._animatables.splice(idx, 1);
+            }
+            // all animatables were removed? animation group ended!
+            if (this._animatables.length === 0) {
+                this._isStarted = false;
+                this.onAnimationGroupEndObservable.notifyObservers(this);
+            }
+        };
         return AnimationGroup;
     }());
     BABYLON.AnimationGroup = AnimationGroup;
@@ -52903,8 +52928,6 @@ var BABYLON;
                 for (index = 0; index < runtimeAnimations.length; index++) {
                     runtimeAnimations[index].dispose();
                 }
-            }
-            if (!running) {
                 this._raiseOnAnimationEnd();
                 this.onAnimationEnd = null;
                 this.onAnimationEndObservable.clear();
@@ -55142,19 +55165,53 @@ var BABYLON;
         return IntersectionInfo;
     }());
     BABYLON.IntersectionInfo = IntersectionInfo;
+    /**
+     * Information about the result of picking within a scene
+     * See https://doc.babylonjs.com/babylon101/picking_collisions
+     */
     var PickingInfo = /** @class */ (function () {
         function PickingInfo() {
+            /**
+             * If the pick collided with an object
+             */
             this.hit = false;
+            /**
+             * Distance away where the pick collided
+             */
             this.distance = 0;
+            /**
+             * The location of pick collision
+             */
             this.pickedPoint = null;
+            /**
+             * The mesh corrisponding the the pick collision
+             */
             this.pickedMesh = null;
+            /** (See getTextureCoordinates) The barycentric U coordinate that is used when calulating the texture coordinates of the collision.*/
             this.bu = 0;
+            /** (See getTextureCoordinates) The barycentric V coordinate that is used when calulating the texture coordinates of the collision.*/
             this.bv = 0;
+            /** The id of the face on the mesh that was picked  */
             this.faceId = -1;
+            /** Id of the the submesh that was picked */
             this.subMeshId = 0;
+            /** If a sprite was picked, this will be the sprite the pick collided with */
             this.pickedSprite = null;
+            /**
+             * If a mesh was used to do the picking (eg. 6dof controller) this will be populated.
+             */
+            this.originMesh = null;
+            /**
+             * The ray that was used to perform the picking.
+             */
+            this.ray = null;
         }
-        // Methods
+        /**
+         * Gets the normal corrispodning to the face the pick collided with
+         * @param useWorldCoordinates If the resulting normal should be relative to the world (default: false)
+         * @param useVerticesNormals If the vertices normals should be used to calculate the normal instead of the normal map
+         * @returns The normal corrispodning to the face the pick collided with
+         */
         PickingInfo.prototype.getNormal = function (useWorldCoordinates, useVerticesNormals) {
             if (useWorldCoordinates === void 0) { useWorldCoordinates = false; }
             if (useVerticesNormals === void 0) { useVerticesNormals = true; }
@@ -55190,6 +55247,10 @@ var BABYLON;
             }
             return BABYLON.Vector3.Normalize(result);
         };
+        /**
+         * Gets the texture coordinates of where the pick occured
+         * @returns the vector containing the coordnates of the texture
+         */
         PickingInfo.prototype.getTextureCoordinates = function () {
             if (!this.pickedMesh || !this.pickedMesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
                 return null;
@@ -88678,12 +88739,12 @@ var BABYLON;
         };
         VRExperienceHelperGazer.prototype._selectionPointerDown = function () {
             this._pointerDownOnMeshAsked = true;
-            if (this._currentMeshSelected && this._currentHit) {
+            if (this._currentHit) {
                 this.scene.simulatePointerDown(this._currentHit, { pointerId: this._id });
             }
         };
         VRExperienceHelperGazer.prototype._selectionPointerUp = function () {
-            if (this._currentMeshSelected && this._currentHit) {
+            if (this._currentHit) {
                 this.scene.simulatePointerUp(this._currentHit, { pointerId: this._id });
             }
             this._pointerDownOnMeshAsked = false;
@@ -90030,6 +90091,14 @@ var BABYLON;
             }
             var ray = gazer._getForwardRay(this._rayLength);
             var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate);
+            if (hit) {
+                // Populate the contrllers mesh that can be used for drag/drop
+                if (gazer._laserPointer) {
+                    hit.originMesh = gazer._laserPointer.parent;
+                }
+                this._scene.simulatePointerMove(hit, { pointerId: gazer._id });
+            }
+            gazer._currentHit = hit;
             // Moving the gazeTracker on the mesh face targetted
             if (hit && hit.pickedPoint) {
                 if (this._displayGaze) {
@@ -90077,10 +90146,6 @@ var BABYLON;
                 gazer._gazeTracker.isVisible = false;
             }
             if (hit && hit.pickedMesh) {
-                gazer._currentHit = hit;
-                if (gazer._pointerDownOnMeshAsked) {
-                    this._scene.simulatePointerMove(gazer._currentHit, { pointerId: gazer._id });
-                }
                 // The object selected is the floor, we're in a teleportation scenario
                 if (this._teleportationInitialized && this._isTeleportationFloor(hit.pickedMesh) && hit.pickedPoint) {
                     // Moving the teleportation area to this targetted point
@@ -90126,7 +90191,6 @@ var BABYLON;
                 }
             }
             else {
-                gazer._currentHit = null;
                 this._notifySelectedMeshUnselected(gazer._currentMeshSelected);
                 gazer._currentMeshSelected = null;
                 //this._teleportationAllowed = false;

+ 78 - 14
dist/preview release/babylon.no-module.max.js

@@ -28555,7 +28555,7 @@ var BABYLON;
          */
         Scene.prototype.pickWithRay = function (ray, predicate, fastCheck) {
             var _this = this;
-            return this._internalPick(function (world) {
+            var result = this._internalPick(function (world) {
                 if (!_this._pickWithRayInverseMatrix) {
                     _this._pickWithRayInverseMatrix = BABYLON.Matrix.Identity();
                 }
@@ -28566,6 +28566,10 @@ var BABYLON;
                 BABYLON.Ray.TransformToRef(ray, _this._pickWithRayInverseMatrix, _this._cachedRayForTransform);
                 return _this._cachedRayForTransform;
             }, predicate, fastCheck);
+            if (result) {
+                result.ray = ray;
+            }
+            return result;
         };
         /**
          * Launch a ray to try to pick a mesh in the scene
@@ -51797,6 +51801,10 @@ var BABYLON;
             this._to = -Number.MAX_VALUE;
             this._speedRatio = 1;
             this.onAnimationEndObservable = new BABYLON.Observable();
+            /**
+             * This observable will notify when all animations have ended.
+             */
+            this.onAnimationGroupEndObservable = new BABYLON.Observable();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.animationGroups.push(this);
         }
@@ -51953,9 +51961,12 @@ var BABYLON;
                 return this;
             }
             var _loop_1 = function (targetedAnimation) {
-                this_1._animatables.push(this_1._scene.beginDirectAnimation(targetedAnimation.target, [targetedAnimation.animation], from !== undefined ? from : this_1._from, to !== undefined ? to : this_1._to, loop, speedRatio, function () {
+                var animatable = this_1._scene.beginDirectAnimation(targetedAnimation.target, [targetedAnimation.animation], from !== undefined ? from : this_1._from, to !== undefined ? to : this_1._to, loop, speedRatio);
+                animatable.onAnimationEnd = function () {
                     _this.onAnimationEndObservable.notifyObservers(targetedAnimation);
-                }));
+                    _this._checkAnimationGroupEnded(animatable);
+                };
+                this_1._animatables.push(animatable);
             };
             var this_1 = this;
             for (var _i = 0, _a = this._targetedAnimations; _i < _a.length; _i++) {
@@ -51985,7 +51996,8 @@ var BABYLON;
          * @param loop defines if animations must loop
          */
         AnimationGroup.prototype.play = function (loop) {
-            if (this.isStarted) {
+            // only if all animatables are ready and exist
+            if (this.isStarted && this._animatables.length === this._targetedAnimations.length) {
                 if (loop !== undefined) {
                     for (var index = 0; index < this._animatables.length; index++) {
                         var animatable = this._animatables[index];
@@ -51995,6 +52007,7 @@ var BABYLON;
                 this.restart();
             }
             else {
+                this.stop();
                 this.start(loop, this._speedRatio);
             }
             return this;
@@ -52091,6 +52104,18 @@ var BABYLON;
                 this._scene.animationGroups.splice(index, 1);
             }
         };
+        AnimationGroup.prototype._checkAnimationGroupEnded = function (animatable) {
+            // animatable should be taken out of the array
+            var idx = this._animatables.indexOf(animatable);
+            if (idx > -1) {
+                this._animatables.splice(idx, 1);
+            }
+            // all animatables were removed? animation group ended!
+            if (this._animatables.length === 0) {
+                this._isStarted = false;
+                this.onAnimationGroupEndObservable.notifyObservers(this);
+            }
+        };
         return AnimationGroup;
     }());
     BABYLON.AnimationGroup = AnimationGroup;
@@ -52870,8 +52895,6 @@ var BABYLON;
                 for (index = 0; index < runtimeAnimations.length; index++) {
                     runtimeAnimations[index].dispose();
                 }
-            }
-            if (!running) {
                 this._raiseOnAnimationEnd();
                 this.onAnimationEnd = null;
                 this.onAnimationEndObservable.clear();
@@ -55109,19 +55132,53 @@ var BABYLON;
         return IntersectionInfo;
     }());
     BABYLON.IntersectionInfo = IntersectionInfo;
+    /**
+     * Information about the result of picking within a scene
+     * See https://doc.babylonjs.com/babylon101/picking_collisions
+     */
     var PickingInfo = /** @class */ (function () {
         function PickingInfo() {
+            /**
+             * If the pick collided with an object
+             */
             this.hit = false;
+            /**
+             * Distance away where the pick collided
+             */
             this.distance = 0;
+            /**
+             * The location of pick collision
+             */
             this.pickedPoint = null;
+            /**
+             * The mesh corrisponding the the pick collision
+             */
             this.pickedMesh = null;
+            /** (See getTextureCoordinates) The barycentric U coordinate that is used when calulating the texture coordinates of the collision.*/
             this.bu = 0;
+            /** (See getTextureCoordinates) The barycentric V coordinate that is used when calulating the texture coordinates of the collision.*/
             this.bv = 0;
+            /** The id of the face on the mesh that was picked  */
             this.faceId = -1;
+            /** Id of the the submesh that was picked */
             this.subMeshId = 0;
+            /** If a sprite was picked, this will be the sprite the pick collided with */
             this.pickedSprite = null;
+            /**
+             * If a mesh was used to do the picking (eg. 6dof controller) this will be populated.
+             */
+            this.originMesh = null;
+            /**
+             * The ray that was used to perform the picking.
+             */
+            this.ray = null;
         }
-        // Methods
+        /**
+         * Gets the normal corrispodning to the face the pick collided with
+         * @param useWorldCoordinates If the resulting normal should be relative to the world (default: false)
+         * @param useVerticesNormals If the vertices normals should be used to calculate the normal instead of the normal map
+         * @returns The normal corrispodning to the face the pick collided with
+         */
         PickingInfo.prototype.getNormal = function (useWorldCoordinates, useVerticesNormals) {
             if (useWorldCoordinates === void 0) { useWorldCoordinates = false; }
             if (useVerticesNormals === void 0) { useVerticesNormals = true; }
@@ -55157,6 +55214,10 @@ var BABYLON;
             }
             return BABYLON.Vector3.Normalize(result);
         };
+        /**
+         * Gets the texture coordinates of where the pick occured
+         * @returns the vector containing the coordnates of the texture
+         */
         PickingInfo.prototype.getTextureCoordinates = function () {
             if (!this.pickedMesh || !this.pickedMesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
                 return null;
@@ -88645,12 +88706,12 @@ var BABYLON;
         };
         VRExperienceHelperGazer.prototype._selectionPointerDown = function () {
             this._pointerDownOnMeshAsked = true;
-            if (this._currentMeshSelected && this._currentHit) {
+            if (this._currentHit) {
                 this.scene.simulatePointerDown(this._currentHit, { pointerId: this._id });
             }
         };
         VRExperienceHelperGazer.prototype._selectionPointerUp = function () {
-            if (this._currentMeshSelected && this._currentHit) {
+            if (this._currentHit) {
                 this.scene.simulatePointerUp(this._currentHit, { pointerId: this._id });
             }
             this._pointerDownOnMeshAsked = false;
@@ -89997,6 +90058,14 @@ var BABYLON;
             }
             var ray = gazer._getForwardRay(this._rayLength);
             var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate);
+            if (hit) {
+                // Populate the contrllers mesh that can be used for drag/drop
+                if (gazer._laserPointer) {
+                    hit.originMesh = gazer._laserPointer.parent;
+                }
+                this._scene.simulatePointerMove(hit, { pointerId: gazer._id });
+            }
+            gazer._currentHit = hit;
             // Moving the gazeTracker on the mesh face targetted
             if (hit && hit.pickedPoint) {
                 if (this._displayGaze) {
@@ -90044,10 +90113,6 @@ var BABYLON;
                 gazer._gazeTracker.isVisible = false;
             }
             if (hit && hit.pickedMesh) {
-                gazer._currentHit = hit;
-                if (gazer._pointerDownOnMeshAsked) {
-                    this._scene.simulatePointerMove(gazer._currentHit, { pointerId: gazer._id });
-                }
                 // The object selected is the floor, we're in a teleportation scenario
                 if (this._teleportationInitialized && this._isTeleportationFloor(hit.pickedMesh) && hit.pickedPoint) {
                     // Moving the teleportation area to this targetted point
@@ -90093,7 +90158,6 @@ var BABYLON;
                 }
             }
             else {
-                gazer._currentHit = null;
                 this._notifySelectedMeshUnselected(gazer._currentMeshSelected);
                 gazer._currentMeshSelected = null;
                 //this._teleportationAllowed = false;

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


+ 78 - 14
dist/preview release/es6.js

@@ -28555,7 +28555,7 @@ var BABYLON;
          */
         Scene.prototype.pickWithRay = function (ray, predicate, fastCheck) {
             var _this = this;
-            return this._internalPick(function (world) {
+            var result = this._internalPick(function (world) {
                 if (!_this._pickWithRayInverseMatrix) {
                     _this._pickWithRayInverseMatrix = BABYLON.Matrix.Identity();
                 }
@@ -28566,6 +28566,10 @@ var BABYLON;
                 BABYLON.Ray.TransformToRef(ray, _this._pickWithRayInverseMatrix, _this._cachedRayForTransform);
                 return _this._cachedRayForTransform;
             }, predicate, fastCheck);
+            if (result) {
+                result.ray = ray;
+            }
+            return result;
         };
         /**
          * Launch a ray to try to pick a mesh in the scene
@@ -51797,6 +51801,10 @@ var BABYLON;
             this._to = -Number.MAX_VALUE;
             this._speedRatio = 1;
             this.onAnimationEndObservable = new BABYLON.Observable();
+            /**
+             * This observable will notify when all animations have ended.
+             */
+            this.onAnimationGroupEndObservable = new BABYLON.Observable();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.animationGroups.push(this);
         }
@@ -51953,9 +51961,12 @@ var BABYLON;
                 return this;
             }
             var _loop_1 = function (targetedAnimation) {
-                this_1._animatables.push(this_1._scene.beginDirectAnimation(targetedAnimation.target, [targetedAnimation.animation], from !== undefined ? from : this_1._from, to !== undefined ? to : this_1._to, loop, speedRatio, function () {
+                var animatable = this_1._scene.beginDirectAnimation(targetedAnimation.target, [targetedAnimation.animation], from !== undefined ? from : this_1._from, to !== undefined ? to : this_1._to, loop, speedRatio);
+                animatable.onAnimationEnd = function () {
                     _this.onAnimationEndObservable.notifyObservers(targetedAnimation);
-                }));
+                    _this._checkAnimationGroupEnded(animatable);
+                };
+                this_1._animatables.push(animatable);
             };
             var this_1 = this;
             for (var _i = 0, _a = this._targetedAnimations; _i < _a.length; _i++) {
@@ -51985,7 +51996,8 @@ var BABYLON;
          * @param loop defines if animations must loop
          */
         AnimationGroup.prototype.play = function (loop) {
-            if (this.isStarted) {
+            // only if all animatables are ready and exist
+            if (this.isStarted && this._animatables.length === this._targetedAnimations.length) {
                 if (loop !== undefined) {
                     for (var index = 0; index < this._animatables.length; index++) {
                         var animatable = this._animatables[index];
@@ -51995,6 +52007,7 @@ var BABYLON;
                 this.restart();
             }
             else {
+                this.stop();
                 this.start(loop, this._speedRatio);
             }
             return this;
@@ -52091,6 +52104,18 @@ var BABYLON;
                 this._scene.animationGroups.splice(index, 1);
             }
         };
+        AnimationGroup.prototype._checkAnimationGroupEnded = function (animatable) {
+            // animatable should be taken out of the array
+            var idx = this._animatables.indexOf(animatable);
+            if (idx > -1) {
+                this._animatables.splice(idx, 1);
+            }
+            // all animatables were removed? animation group ended!
+            if (this._animatables.length === 0) {
+                this._isStarted = false;
+                this.onAnimationGroupEndObservable.notifyObservers(this);
+            }
+        };
         return AnimationGroup;
     }());
     BABYLON.AnimationGroup = AnimationGroup;
@@ -52870,8 +52895,6 @@ var BABYLON;
                 for (index = 0; index < runtimeAnimations.length; index++) {
                     runtimeAnimations[index].dispose();
                 }
-            }
-            if (!running) {
                 this._raiseOnAnimationEnd();
                 this.onAnimationEnd = null;
                 this.onAnimationEndObservable.clear();
@@ -55109,19 +55132,53 @@ var BABYLON;
         return IntersectionInfo;
     }());
     BABYLON.IntersectionInfo = IntersectionInfo;
+    /**
+     * Information about the result of picking within a scene
+     * See https://doc.babylonjs.com/babylon101/picking_collisions
+     */
     var PickingInfo = /** @class */ (function () {
         function PickingInfo() {
+            /**
+             * If the pick collided with an object
+             */
             this.hit = false;
+            /**
+             * Distance away where the pick collided
+             */
             this.distance = 0;
+            /**
+             * The location of pick collision
+             */
             this.pickedPoint = null;
+            /**
+             * The mesh corrisponding the the pick collision
+             */
             this.pickedMesh = null;
+            /** (See getTextureCoordinates) The barycentric U coordinate that is used when calulating the texture coordinates of the collision.*/
             this.bu = 0;
+            /** (See getTextureCoordinates) The barycentric V coordinate that is used when calulating the texture coordinates of the collision.*/
             this.bv = 0;
+            /** The id of the face on the mesh that was picked  */
             this.faceId = -1;
+            /** Id of the the submesh that was picked */
             this.subMeshId = 0;
+            /** If a sprite was picked, this will be the sprite the pick collided with */
             this.pickedSprite = null;
+            /**
+             * If a mesh was used to do the picking (eg. 6dof controller) this will be populated.
+             */
+            this.originMesh = null;
+            /**
+             * The ray that was used to perform the picking.
+             */
+            this.ray = null;
         }
-        // Methods
+        /**
+         * Gets the normal corrispodning to the face the pick collided with
+         * @param useWorldCoordinates If the resulting normal should be relative to the world (default: false)
+         * @param useVerticesNormals If the vertices normals should be used to calculate the normal instead of the normal map
+         * @returns The normal corrispodning to the face the pick collided with
+         */
         PickingInfo.prototype.getNormal = function (useWorldCoordinates, useVerticesNormals) {
             if (useWorldCoordinates === void 0) { useWorldCoordinates = false; }
             if (useVerticesNormals === void 0) { useVerticesNormals = true; }
@@ -55157,6 +55214,10 @@ var BABYLON;
             }
             return BABYLON.Vector3.Normalize(result);
         };
+        /**
+         * Gets the texture coordinates of where the pick occured
+         * @returns the vector containing the coordnates of the texture
+         */
         PickingInfo.prototype.getTextureCoordinates = function () {
             if (!this.pickedMesh || !this.pickedMesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
                 return null;
@@ -88645,12 +88706,12 @@ var BABYLON;
         };
         VRExperienceHelperGazer.prototype._selectionPointerDown = function () {
             this._pointerDownOnMeshAsked = true;
-            if (this._currentMeshSelected && this._currentHit) {
+            if (this._currentHit) {
                 this.scene.simulatePointerDown(this._currentHit, { pointerId: this._id });
             }
         };
         VRExperienceHelperGazer.prototype._selectionPointerUp = function () {
-            if (this._currentMeshSelected && this._currentHit) {
+            if (this._currentHit) {
                 this.scene.simulatePointerUp(this._currentHit, { pointerId: this._id });
             }
             this._pointerDownOnMeshAsked = false;
@@ -89997,6 +90058,14 @@ var BABYLON;
             }
             var ray = gazer._getForwardRay(this._rayLength);
             var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate);
+            if (hit) {
+                // Populate the contrllers mesh that can be used for drag/drop
+                if (gazer._laserPointer) {
+                    hit.originMesh = gazer._laserPointer.parent;
+                }
+                this._scene.simulatePointerMove(hit, { pointerId: gazer._id });
+            }
+            gazer._currentHit = hit;
             // Moving the gazeTracker on the mesh face targetted
             if (hit && hit.pickedPoint) {
                 if (this._displayGaze) {
@@ -90044,10 +90113,6 @@ var BABYLON;
                 gazer._gazeTracker.isVisible = false;
             }
             if (hit && hit.pickedMesh) {
-                gazer._currentHit = hit;
-                if (gazer._pointerDownOnMeshAsked) {
-                    this._scene.simulatePointerMove(gazer._currentHit, { pointerId: gazer._id });
-                }
                 // The object selected is the floor, we're in a teleportation scenario
                 if (this._teleportationInitialized && this._isTeleportationFloor(hit.pickedMesh) && hit.pickedPoint) {
                     // Moving the teleportation area to this targetted point
@@ -90093,7 +90158,6 @@ var BABYLON;
                 }
             }
             else {
-                gazer._currentHit = null;
                 this._notifySelectedMeshUnselected(gazer._currentMeshSelected);
                 gazer._currentMeshSelected = null;
                 //this._teleportationAllowed = false;

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

@@ -1034,6 +1034,11 @@ declare module BABYLON.GUI {
         private _emissiveTexture;
         emissiveTexture: BaseTexture;
         private _renderId;
+        /**
+         * Creates a new Fluent material
+         * @param name defines the name of the material
+         * @param scene defines the hosting scene
+         */
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
@@ -1068,11 +1073,15 @@ declare module BABYLON.GUI {
         name: string | undefined;
         /** @hidden */
         _host: GUI3DManager;
-        private _mesh;
+        private _node;
         private _downCount;
         private _enterCount;
         private _downPointerIds;
         private _isVisible;
+        /** Gets or sets the control position */
+        position: Vector3;
+        /** Gets or sets the control scaling */
+        scaling: Vector3;
         /** Callback used to start pointer enter animation */
         pointerEnterAnimation: () => void;
         /** Callback used to start pointer out animation */
@@ -1138,8 +1147,6 @@ declare module BABYLON.GUI {
         getBehaviorByName(name: string): Nullable<Behavior<Control3D>>;
         /** Gets or sets a boolean indicating if the control is visible */
         isVisible: boolean;
-        /** Gets or sets the control position */
-        position: Vector3;
         /**
          * Creates a new control
          * @param name defines the control name
@@ -1155,26 +1162,26 @@ declare module BABYLON.GUI {
         /**
          * Gets the mesh used to render this control
          */
-        readonly mesh: Nullable<Mesh>;
+        readonly node: Nullable<TransformNode>;
         /**
-         * Link the control as child of the given mesh
-         * @param mesh defines the mesh to link to. Use null to unlink the control
-         * @returns the current control
+         * Gets the mesh used to render this control
          */
-        linkToMesh(mesh: Nullable<AbstractMesh>): Control3D;
+        readonly mesh: Nullable<Mesh>;
         /**
-         * Get the attached mesh used to render the control
-         * @param scene defines the scene where the mesh must be attached
-         * @returns the attached mesh or null if none
+         * Link the control as child of the given node
+         * @param node defines the node to link to. Use null to unlink the control
+         * @returns the current control
          */
-        prepareMesh(scene: Scene): Nullable<Mesh>;
+        linkToTransformNode(node: Nullable<TransformNode>): Control3D;
+        /** @hidden **/
+        _prepareNode(scene: Scene): void;
         /**
-         * Mesh creation.
+         * Node creation.
          * Can be overriden by children
-         * @param scene defines the scene where the mesh must be attached
-         * @returns the attached mesh or null if none
+         * @param scene defines the scene where the node must be attached
+         * @returns the attached node or null if none
          */
-        protected _createMesh(scene: Scene): Nullable<Mesh>;
+        protected _createNode(scene: Scene): Nullable<TransformNode>;
         /**
          * Affect a material to the given mesh
          * @param mesh defines the mesh which will represent the control
@@ -1207,7 +1214,10 @@ declare module BABYLON.GUI {
      * Class used to create containers for controls
      */
     class Container3D extends Control3D {
-        private _children;
+        /**
+         * Gets the list of child controls
+         */
+        protected _children: Control3D[];
         /**
          * Creates a new container
          * @param name defines the container name
@@ -1226,6 +1236,11 @@ declare module BABYLON.GUI {
          */
         addControl(control: Control3D): Container3D;
         /**
+         * This function will be called everytime a new control is added
+         */
+        protected _arrangeChildren(): void;
+        protected _createNode(scene: Scene): Nullable<TransformNode>;
+        /**
          * Removes the control from the children of this control
          * @param control defines the control to remove
          * @returns the current container
@@ -1259,7 +1274,7 @@ declare module BABYLON.GUI {
          */
         content: Control;
         protected _getTypeName(): string;
-        protected _createMesh(scene: Scene): Mesh;
+        protected _createNode(scene: Scene): TransformNode;
         protected _affectMaterial(mesh: Mesh): void;
     }
 }
@@ -1267,16 +1282,41 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     /**
-     * Class used to create a button in 3D
+     * Class used to create a holographic button in 3D
      */
     class HolographicButton extends Button3D {
+        private _frontPlate;
         /**
          * Creates a new button
          * @param name defines the control name
          */
         constructor(name?: string);
         protected _getTypeName(): string;
-        protected _createMesh(scene: Scene): Mesh;
+        protected _createNode(scene: Scene): TransformNode;
         protected _affectMaterial(mesh: Mesh): void;
     }
 }
+
+
+declare module BABYLON.GUI {
+    /**
+     * Class used to create a stack panel in 3D on XY plane
+     */
+    class StackPanel3D extends Container3D {
+        private _isVertical;
+        /**
+         * Gets or sets a boolean indicating if the stack panel is vertical or horizontal (horizontal by default)
+         */
+        isVertical: boolean;
+        /**
+         * Gets or sets the distance between elements
+         */
+        margin: number;
+        /**
+         * Creates new StackPanel
+         * @param isVertical
+         */
+        constructor();
+        protected _arrangeChildren(): void;
+    }
+}

+ 189 - 55
dist/preview release/gui/babylon.gui.js

@@ -5777,6 +5777,11 @@ var BABYLON;
          */
         var FluentMaterial = /** @class */ (function (_super) {
             __extends(FluentMaterial, _super);
+            /**
+             * Creates a new Fluent material
+             * @param name defines the name of the material
+             * @param scene defines the hosting scene
+             */
             function FluentMaterial(name, scene) {
                 return _super.call(this, name, scene) || this;
             }
@@ -5946,6 +5951,10 @@ var BABYLON;
                 this._enterCount = 0;
                 this._downPointerIds = {};
                 this._isVisible = true;
+                /** Gets or sets the control position */
+                this.position = new BABYLON.Vector3(0, 0, 0);
+                /** Gets or sets the control scaling */
+                this.scaling = new BABYLON.Vector3(1, 1, 1);
                 /**
                 * An event triggered when the pointer move over the control.
                 */
@@ -6050,24 +6059,9 @@ var BABYLON;
                         return;
                     }
                     this._isVisible = value;
-                    if (this._mesh) {
-                        this._mesh.isVisible = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(Control3D.prototype, "position", {
-                /** Gets or sets the control position */
-                get: function () {
-                    if (this._mesh) {
-                        return this._mesh.position;
-                    }
-                    return BABYLON.Vector3.Zero();
-                },
-                set: function (value) {
-                    if (this._mesh) {
-                        this._mesh.position = value;
+                    var mesh = this.mesh;
+                    if (mesh) {
+                        mesh.isVisible = value;
                     }
                 },
                 enumerable: true,
@@ -6086,48 +6080,61 @@ var BABYLON;
             Control3D.prototype._getTypeName = function () {
                 return "Control3D";
             };
+            Object.defineProperty(Control3D.prototype, "node", {
+                /**
+                 * Gets the mesh used to render this control
+                 */
+                get: function () {
+                    return this._node;
+                },
+                enumerable: true,
+                configurable: true
+            });
             Object.defineProperty(Control3D.prototype, "mesh", {
                 /**
                  * Gets the mesh used to render this control
                  */
                 get: function () {
-                    return this._mesh;
+                    return this._node;
                 },
                 enumerable: true,
                 configurable: true
             });
             /**
-             * Link the control as child of the given mesh
-             * @param mesh defines the mesh to link to. Use null to unlink the control
+             * Link the control as child of the given node
+             * @param node defines the node to link to. Use null to unlink the control
              * @returns the current control
              */
-            Control3D.prototype.linkToMesh = function (mesh) {
-                if (this._mesh) {
-                    this._mesh.parent = mesh;
+            Control3D.prototype.linkToTransformNode = function (node) {
+                if (this._node) {
+                    this._node.parent = node;
                 }
                 return this;
             };
-            /**
-             * Get the attached mesh used to render the control
-             * @param scene defines the scene where the mesh must be attached
-             * @returns the attached mesh or null if none
-             */
-            Control3D.prototype.prepareMesh = function (scene) {
-                if (!this._mesh) {
-                    this._mesh = this._createMesh(scene);
-                    this._mesh.isPickable = true;
-                    this._mesh.metadata = this; // Store the control on the metadata field in order to get it when picking
-                    this._affectMaterial(this._mesh);
+            /** @hidden **/
+            Control3D.prototype._prepareNode = function (scene) {
+                if (!this._node) {
+                    this._node = this._createNode(scene);
+                    if (!this.node) {
+                        return;
+                    }
+                    this._node.metadata = this; // Store the control on the metadata field in order to get it when picking
+                    this._node.position = this.position;
+                    this._node.scaling = this.scaling;
+                    var mesh = this.mesh;
+                    if (mesh) {
+                        mesh.isPickable = true;
+                        this._affectMaterial(mesh);
+                    }
                 }
-                return this._mesh;
             };
             /**
-             * Mesh creation.
+             * Node creation.
              * Can be overriden by children
-             * @param scene defines the scene where the mesh must be attached
-             * @returns the attached mesh or null if none
+             * @param scene defines the scene where the node must be attached
+             * @returns the attached node or null if none
              */
-            Control3D.prototype._createMesh = function (scene) {
+            Control3D.prototype._createNode = function (scene) {
                 // Do nothing by default
                 return null;
             };
@@ -6239,9 +6246,9 @@ var BABYLON;
                 this.onPointerOutObservable.clear();
                 this.onPointerUpObservable.clear();
                 this.onPointerClickObservable.clear();
-                if (this._mesh) {
-                    this._mesh.dispose(false, true);
-                    this._mesh = null;
+                if (this._node) {
+                    this._node.dispose(false, true);
+                    this._node = null;
                 }
                 // Behaviors
                 for (var _i = 0, _a = this._behaviors; _i < _a.length; _i++) {
@@ -6272,6 +6279,9 @@ var BABYLON;
              */
             function Container3D(name) {
                 var _this = _super.call(this, name) || this;
+                /**
+                 * Gets the list of child controls
+                 */
                 _this._children = new Array();
                 return _this;
             }
@@ -6295,12 +6305,25 @@ var BABYLON;
                 }
                 control.parent = this;
                 control._host = this._host;
+                this._children.push(control);
                 if (this._host.utilityLayer) {
-                    control.prepareMesh(this._host.utilityLayer.utilityLayerScene);
+                    control._prepareNode(this._host.utilityLayer.utilityLayerScene);
+                    if (control.node) {
+                        control.node.parent = this.node;
+                    }
+                    this._arrangeChildren();
                 }
                 return this;
             };
             /**
+             * This function will be called everytime a new control is added
+             */
+            Container3D.prototype._arrangeChildren = function () {
+            };
+            Container3D.prototype._createNode = function (scene) {
+                return new BABYLON.TransformNode("ContainerNode", scene);
+            };
+            /**
              * Removes the control from the children of this control
              * @param control defines the control to remove
              * @returns the current container
@@ -6401,7 +6424,7 @@ var BABYLON;
                 return "Button3D";
             };
             // Mesh association
-            Button3D.prototype._createMesh = function (scene) {
+            Button3D.prototype._createNode = function (scene) {
                 var faceUV = new Array(6);
                 for (var i = 0; i < 6; i++) {
                     faceUV[i] = new BABYLON.Vector4(0, 0, 0, 0);
@@ -6410,7 +6433,7 @@ var BABYLON;
                 var mesh = BABYLON.MeshBuilder.CreateBox(this.name + "Mesh", {
                     width: 1.0,
                     height: 1.0,
-                    depth: 0.1,
+                    depth: 0.05,
                     faceUV: faceUV
                 }, scene);
                 return mesh;
@@ -6434,7 +6457,7 @@ var BABYLON;
     var GUI;
     (function (GUI) {
         /**
-         * Class used to create a button in 3D
+         * Class used to create a holographic button in 3D
          */
         var HolographicButton = /** @class */ (function (_super) {
             __extends(HolographicButton, _super);
@@ -6449,13 +6472,13 @@ var BABYLON;
                     if (!_this.mesh) {
                         return;
                     }
-                    _this.mesh.edgesRenderer.isEnabled = true;
+                    _this._frontPlate.setEnabled(true);
                 };
                 _this.pointerOutAnimation = function () {
                     if (!_this.mesh) {
                         return;
                     }
-                    _this.mesh.edgesRenderer.isEnabled = false;
+                    _this._frontPlate.setEnabled(false);
                 };
                 return _this;
             }
@@ -6463,12 +6486,17 @@ var BABYLON;
                 return "HolographicButton";
             };
             // Mesh association
-            HolographicButton.prototype._createMesh = function (scene) {
-                var mesh = _super.prototype._createMesh.call(this, scene);
-                mesh.edgesWidth = 0.5;
-                mesh.edgesColor = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
-                mesh.enableEdgesRendering();
-                mesh.edgesRenderer.isEnabled = false;
+            HolographicButton.prototype._createNode = function (scene) {
+                var mesh = _super.prototype._createNode.call(this, scene);
+                this._frontPlate = _super.prototype._createNode.call(this, scene);
+                this._frontPlate.parent = mesh;
+                this._frontPlate.position.z = -0.05;
+                this._frontPlate.setEnabled(false);
+                this._frontPlate.isPickable = false;
+                this._frontPlate.visibility = 0.001;
+                this._frontPlate.edgesWidth = 1.0;
+                this._frontPlate.edgesColor = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
+                this._frontPlate.enableEdgesRendering();
                 return mesh;
             };
             HolographicButton.prototype._affectMaterial = function (mesh) {
@@ -6481,6 +6509,112 @@ var BABYLON;
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
 })(BABYLON || (BABYLON = {}));
 
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
+        /**
+         * Class used to create a stack panel in 3D on XY plane
+         */
+        var StackPanel3D = /** @class */ (function (_super) {
+            __extends(StackPanel3D, _super);
+            /**
+             * Creates new StackPanel
+             * @param isVertical
+             */
+            function StackPanel3D() {
+                var _this = _super.call(this) || this;
+                _this._isVertical = false;
+                /**
+                 * Gets or sets the distance between elements
+                 */
+                _this.margin = 0.1;
+                return _this;
+            }
+            Object.defineProperty(StackPanel3D.prototype, "isVertical", {
+                /**
+                 * Gets or sets a boolean indicating if the stack panel is vertical or horizontal (horizontal by default)
+                 */
+                get: function () {
+                    return this._isVertical;
+                },
+                set: function (value) {
+                    if (this._isVertical === value) {
+                        return;
+                    }
+                    this._isVertical = value;
+                    this._arrangeChildren();
+                },
+                enumerable: true,
+                configurable: true
+            });
+            StackPanel3D.prototype._arrangeChildren = function () {
+                var width = 0;
+                var height = 0;
+                var controlCount = 0;
+                var extendSizes = [];
+                var currentInverseWorld = BABYLON.Matrix.Invert(this.node.computeWorldMatrix(true));
+                // Measure
+                for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
+                    var child = _a[_i];
+                    if (!child.mesh) {
+                        continue;
+                    }
+                    controlCount++;
+                    child.mesh.computeWorldMatrix(true);
+                    var boundingBox = child.mesh.getBoundingInfo().boundingBox;
+                    var extendSize = BABYLON.Vector3.TransformNormal(boundingBox.extendSizeWorld, currentInverseWorld);
+                    extendSizes.push(extendSize);
+                    if (this._isVertical) {
+                        height += extendSize.y;
+                    }
+                    else {
+                        width += extendSize.x;
+                    }
+                }
+                if (this._isVertical) {
+                    height += (controlCount - 1) * this.margin / 2;
+                }
+                else {
+                    width += (controlCount - 1) * this.margin / 2;
+                }
+                // Arrange
+                var offset;
+                if (this._isVertical) {
+                    offset = -height;
+                }
+                else {
+                    offset = -width;
+                }
+                var index = 0;
+                for (var _b = 0, _c = this._children; _b < _c.length; _b++) {
+                    var child = _c[_b];
+                    if (!child.mesh) {
+                        continue;
+                    }
+                    controlCount--;
+                    var extendSize = extendSizes[index++];
+                    if (this._isVertical) {
+                        child.position.y = offset + extendSize.y;
+                        child.position.x = 0;
+                        offset += extendSize.y * 2;
+                    }
+                    else {
+                        child.position.x = offset + extendSize.x;
+                        child.position.y = 0;
+                        offset += extendSize.x * 2;
+                    }
+                    offset += (controlCount > 0 ? this.margin : 0);
+                }
+            };
+            return StackPanel3D;
+        }(GUI.Container3D));
+        GUI.StackPanel3D = StackPanel3D;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));
+
     
 
     return BABYLON.GUI;

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


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

@@ -1039,6 +1039,11 @@ declare module BABYLON.GUI {
         private _emissiveTexture;
         emissiveTexture: BaseTexture;
         private _renderId;
+        /**
+         * Creates a new Fluent material
+         * @param name defines the name of the material
+         * @param scene defines the hosting scene
+         */
         constructor(name: string, scene: Scene);
         needAlphaBlending(): boolean;
         needAlphaTesting(): boolean;
@@ -1073,11 +1078,15 @@ declare module BABYLON.GUI {
         name: string | undefined;
         /** @hidden */
         _host: GUI3DManager;
-        private _mesh;
+        private _node;
         private _downCount;
         private _enterCount;
         private _downPointerIds;
         private _isVisible;
+        /** Gets or sets the control position */
+        position: Vector3;
+        /** Gets or sets the control scaling */
+        scaling: Vector3;
         /** Callback used to start pointer enter animation */
         pointerEnterAnimation: () => void;
         /** Callback used to start pointer out animation */
@@ -1143,8 +1152,6 @@ declare module BABYLON.GUI {
         getBehaviorByName(name: string): Nullable<Behavior<Control3D>>;
         /** Gets or sets a boolean indicating if the control is visible */
         isVisible: boolean;
-        /** Gets or sets the control position */
-        position: Vector3;
         /**
          * Creates a new control
          * @param name defines the control name
@@ -1160,26 +1167,26 @@ declare module BABYLON.GUI {
         /**
          * Gets the mesh used to render this control
          */
-        readonly mesh: Nullable<Mesh>;
+        readonly node: Nullable<TransformNode>;
         /**
-         * Link the control as child of the given mesh
-         * @param mesh defines the mesh to link to. Use null to unlink the control
-         * @returns the current control
+         * Gets the mesh used to render this control
          */
-        linkToMesh(mesh: Nullable<AbstractMesh>): Control3D;
+        readonly mesh: Nullable<Mesh>;
         /**
-         * Get the attached mesh used to render the control
-         * @param scene defines the scene where the mesh must be attached
-         * @returns the attached mesh or null if none
+         * Link the control as child of the given node
+         * @param node defines the node to link to. Use null to unlink the control
+         * @returns the current control
          */
-        prepareMesh(scene: Scene): Nullable<Mesh>;
+        linkToTransformNode(node: Nullable<TransformNode>): Control3D;
+        /** @hidden **/
+        _prepareNode(scene: Scene): void;
         /**
-         * Mesh creation.
+         * Node creation.
          * Can be overriden by children
-         * @param scene defines the scene where the mesh must be attached
-         * @returns the attached mesh or null if none
+         * @param scene defines the scene where the node must be attached
+         * @returns the attached node or null if none
          */
-        protected _createMesh(scene: Scene): Nullable<Mesh>;
+        protected _createNode(scene: Scene): Nullable<TransformNode>;
         /**
          * Affect a material to the given mesh
          * @param mesh defines the mesh which will represent the control
@@ -1212,7 +1219,10 @@ declare module BABYLON.GUI {
      * Class used to create containers for controls
      */
     class Container3D extends Control3D {
-        private _children;
+        /**
+         * Gets the list of child controls
+         */
+        protected _children: Control3D[];
         /**
          * Creates a new container
          * @param name defines the container name
@@ -1231,6 +1241,11 @@ declare module BABYLON.GUI {
          */
         addControl(control: Control3D): Container3D;
         /**
+         * This function will be called everytime a new control is added
+         */
+        protected _arrangeChildren(): void;
+        protected _createNode(scene: Scene): Nullable<TransformNode>;
+        /**
          * Removes the control from the children of this control
          * @param control defines the control to remove
          * @returns the current container
@@ -1264,7 +1279,7 @@ declare module BABYLON.GUI {
          */
         content: Control;
         protected _getTypeName(): string;
-        protected _createMesh(scene: Scene): Mesh;
+        protected _createNode(scene: Scene): TransformNode;
         protected _affectMaterial(mesh: Mesh): void;
     }
 }
@@ -1272,16 +1287,41 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     /**
-     * Class used to create a button in 3D
+     * Class used to create a holographic button in 3D
      */
     class HolographicButton extends Button3D {
+        private _frontPlate;
         /**
          * Creates a new button
          * @param name defines the control name
          */
         constructor(name?: string);
         protected _getTypeName(): string;
-        protected _createMesh(scene: Scene): Mesh;
+        protected _createNode(scene: Scene): TransformNode;
         protected _affectMaterial(mesh: Mesh): void;
     }
 }
+
+
+declare module BABYLON.GUI {
+    /**
+     * Class used to create a stack panel in 3D on XY plane
+     */
+    class StackPanel3D extends Container3D {
+        private _isVertical;
+        /**
+         * Gets or sets a boolean indicating if the stack panel is vertical or horizontal (horizontal by default)
+         */
+        isVertical: boolean;
+        /**
+         * Gets or sets the distance between elements
+         */
+        margin: number;
+        /**
+         * Creates new StackPanel
+         * @param isVertical
+         */
+        constructor();
+        protected _arrangeChildren(): void;
+    }
+}

+ 2 - 80
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 4301,
+  "errors": 4287,
   "babylon.typedoc.json": {
-    "errors": 4301,
+    "errors": 4287,
     "Animatable": {
       "Class": {
         "Comments": {
@@ -12027,84 +12027,6 @@
         }
       }
     },
-    "PickingInfo": {
-      "Class": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
-      "Property": {
-        "bu": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "bv": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "distance": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "faceId": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "hit": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "pickedMesh": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "pickedPoint": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "pickedSprite": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "subMeshId": {
-          "Comments": {
-            "MissingText": true
-          }
-        }
-      },
-      "Method": {
-        "getNormal": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "useWorldCoordinates": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "useVerticesNormals": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getTextureCoordinates": {
-          "Comments": {
-            "MissingText": true
-          }
-        }
-      }
-    },
     "Plane": {
       "Class": {
         "Comments": {

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


+ 78 - 14
dist/preview release/viewer/babylon.viewer.max.js

@@ -28676,7 +28676,7 @@ var BABYLON;
          */
         Scene.prototype.pickWithRay = function (ray, predicate, fastCheck) {
             var _this = this;
-            return this._internalPick(function (world) {
+            var result = this._internalPick(function (world) {
                 if (!_this._pickWithRayInverseMatrix) {
                     _this._pickWithRayInverseMatrix = BABYLON.Matrix.Identity();
                 }
@@ -28687,6 +28687,10 @@ var BABYLON;
                 BABYLON.Ray.TransformToRef(ray, _this._pickWithRayInverseMatrix, _this._cachedRayForTransform);
                 return _this._cachedRayForTransform;
             }, predicate, fastCheck);
+            if (result) {
+                result.ray = ray;
+            }
+            return result;
         };
         /**
          * Launch a ray to try to pick a mesh in the scene
@@ -51918,6 +51922,10 @@ var BABYLON;
             this._to = -Number.MAX_VALUE;
             this._speedRatio = 1;
             this.onAnimationEndObservable = new BABYLON.Observable();
+            /**
+             * This observable will notify when all animations have ended.
+             */
+            this.onAnimationGroupEndObservable = new BABYLON.Observable();
             this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this._scene.animationGroups.push(this);
         }
@@ -52074,9 +52082,12 @@ var BABYLON;
                 return this;
             }
             var _loop_1 = function (targetedAnimation) {
-                this_1._animatables.push(this_1._scene.beginDirectAnimation(targetedAnimation.target, [targetedAnimation.animation], from !== undefined ? from : this_1._from, to !== undefined ? to : this_1._to, loop, speedRatio, function () {
+                var animatable = this_1._scene.beginDirectAnimation(targetedAnimation.target, [targetedAnimation.animation], from !== undefined ? from : this_1._from, to !== undefined ? to : this_1._to, loop, speedRatio);
+                animatable.onAnimationEnd = function () {
                     _this.onAnimationEndObservable.notifyObservers(targetedAnimation);
-                }));
+                    _this._checkAnimationGroupEnded(animatable);
+                };
+                this_1._animatables.push(animatable);
             };
             var this_1 = this;
             for (var _i = 0, _a = this._targetedAnimations; _i < _a.length; _i++) {
@@ -52106,7 +52117,8 @@ var BABYLON;
          * @param loop defines if animations must loop
          */
         AnimationGroup.prototype.play = function (loop) {
-            if (this.isStarted) {
+            // only if all animatables are ready and exist
+            if (this.isStarted && this._animatables.length === this._targetedAnimations.length) {
                 if (loop !== undefined) {
                     for (var index = 0; index < this._animatables.length; index++) {
                         var animatable = this._animatables[index];
@@ -52116,6 +52128,7 @@ var BABYLON;
                 this.restart();
             }
             else {
+                this.stop();
                 this.start(loop, this._speedRatio);
             }
             return this;
@@ -52212,6 +52225,18 @@ var BABYLON;
                 this._scene.animationGroups.splice(index, 1);
             }
         };
+        AnimationGroup.prototype._checkAnimationGroupEnded = function (animatable) {
+            // animatable should be taken out of the array
+            var idx = this._animatables.indexOf(animatable);
+            if (idx > -1) {
+                this._animatables.splice(idx, 1);
+            }
+            // all animatables were removed? animation group ended!
+            if (this._animatables.length === 0) {
+                this._isStarted = false;
+                this.onAnimationGroupEndObservable.notifyObservers(this);
+            }
+        };
         return AnimationGroup;
     }());
     BABYLON.AnimationGroup = AnimationGroup;
@@ -52991,8 +53016,6 @@ var BABYLON;
                 for (index = 0; index < runtimeAnimations.length; index++) {
                     runtimeAnimations[index].dispose();
                 }
-            }
-            if (!running) {
                 this._raiseOnAnimationEnd();
                 this.onAnimationEnd = null;
                 this.onAnimationEndObservable.clear();
@@ -55230,19 +55253,53 @@ var BABYLON;
         return IntersectionInfo;
     }());
     BABYLON.IntersectionInfo = IntersectionInfo;
+    /**
+     * Information about the result of picking within a scene
+     * See https://doc.babylonjs.com/babylon101/picking_collisions
+     */
     var PickingInfo = /** @class */ (function () {
         function PickingInfo() {
+            /**
+             * If the pick collided with an object
+             */
             this.hit = false;
+            /**
+             * Distance away where the pick collided
+             */
             this.distance = 0;
+            /**
+             * The location of pick collision
+             */
             this.pickedPoint = null;
+            /**
+             * The mesh corrisponding the the pick collision
+             */
             this.pickedMesh = null;
+            /** (See getTextureCoordinates) The barycentric U coordinate that is used when calulating the texture coordinates of the collision.*/
             this.bu = 0;
+            /** (See getTextureCoordinates) The barycentric V coordinate that is used when calulating the texture coordinates of the collision.*/
             this.bv = 0;
+            /** The id of the face on the mesh that was picked  */
             this.faceId = -1;
+            /** Id of the the submesh that was picked */
             this.subMeshId = 0;
+            /** If a sprite was picked, this will be the sprite the pick collided with */
             this.pickedSprite = null;
+            /**
+             * If a mesh was used to do the picking (eg. 6dof controller) this will be populated.
+             */
+            this.originMesh = null;
+            /**
+             * The ray that was used to perform the picking.
+             */
+            this.ray = null;
         }
-        // Methods
+        /**
+         * Gets the normal corrispodning to the face the pick collided with
+         * @param useWorldCoordinates If the resulting normal should be relative to the world (default: false)
+         * @param useVerticesNormals If the vertices normals should be used to calculate the normal instead of the normal map
+         * @returns The normal corrispodning to the face the pick collided with
+         */
         PickingInfo.prototype.getNormal = function (useWorldCoordinates, useVerticesNormals) {
             if (useWorldCoordinates === void 0) { useWorldCoordinates = false; }
             if (useVerticesNormals === void 0) { useVerticesNormals = true; }
@@ -55278,6 +55335,10 @@ var BABYLON;
             }
             return BABYLON.Vector3.Normalize(result);
         };
+        /**
+         * Gets the texture coordinates of where the pick occured
+         * @returns the vector containing the coordnates of the texture
+         */
         PickingInfo.prototype.getTextureCoordinates = function () {
             if (!this.pickedMesh || !this.pickedMesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
                 return null;
@@ -88766,12 +88827,12 @@ var BABYLON;
         };
         VRExperienceHelperGazer.prototype._selectionPointerDown = function () {
             this._pointerDownOnMeshAsked = true;
-            if (this._currentMeshSelected && this._currentHit) {
+            if (this._currentHit) {
                 this.scene.simulatePointerDown(this._currentHit, { pointerId: this._id });
             }
         };
         VRExperienceHelperGazer.prototype._selectionPointerUp = function () {
-            if (this._currentMeshSelected && this._currentHit) {
+            if (this._currentHit) {
                 this.scene.simulatePointerUp(this._currentHit, { pointerId: this._id });
             }
             this._pointerDownOnMeshAsked = false;
@@ -90118,6 +90179,14 @@ var BABYLON;
             }
             var ray = gazer._getForwardRay(this._rayLength);
             var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate);
+            if (hit) {
+                // Populate the contrllers mesh that can be used for drag/drop
+                if (gazer._laserPointer) {
+                    hit.originMesh = gazer._laserPointer.parent;
+                }
+                this._scene.simulatePointerMove(hit, { pointerId: gazer._id });
+            }
+            gazer._currentHit = hit;
             // Moving the gazeTracker on the mesh face targetted
             if (hit && hit.pickedPoint) {
                 if (this._displayGaze) {
@@ -90165,10 +90234,6 @@ var BABYLON;
                 gazer._gazeTracker.isVisible = false;
             }
             if (hit && hit.pickedMesh) {
-                gazer._currentHit = hit;
-                if (gazer._pointerDownOnMeshAsked) {
-                    this._scene.simulatePointerMove(gazer._currentHit, { pointerId: gazer._id });
-                }
                 // The object selected is the floor, we're in a teleportation scenario
                 if (this._teleportationInitialized && this._isTeleportationFloor(hit.pickedMesh) && hit.pickedPoint) {
                     // Moving the teleportation area to this targetted point
@@ -90214,7 +90279,6 @@ var BABYLON;
                 }
             }
             else {
-                gazer._currentHit = null;
                 this._notifySelectedMeshUnselected(gazer._currentMeshSelected);
                 gazer._currentMeshSelected = null;
                 //this._teleportationAllowed = false;