浏览代码

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

David Catuhe 7 年之前
父节点
当前提交
8f4fc4ffb9

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

@@ -33,7 +33,7 @@
 - Get a root mesh from an asset container, load a mesh from a file with a single string url ([TrevorDev](https://github.com/TrevorDev))
 - UtilityLayer class to render another scene as a layer on top of an existing scene ([TrevorDev](https://github.com/TrevorDev))
 - AnimationGroup has now onAnimationGroupEnd observable ([RaananW](https://github.com/RaananW))
-- PointerDragBehavior, SixDofDragBehavior and MultiPointerScaleBehavior to enable drag and drop/scaling with mouse or 6dof controller on a mesh ([TrevorDev](https://github.com/TrevorDev))
+- PointerDragBehavior, SixDofDragBehavior and MultiPointerScaleBehavior to enable smooth drag and drop/scaling with mouse or 6dof controller on a mesh ([TrevorDev](https://github.com/TrevorDev))
 - Gizmo and GizmoManager classes used to manipulate meshes in a scene. Gizmo types include position, rotation, scale, and bounding box ([TrevorDev](https://github.com/TrevorDev))
 - Added a new `mesh.ignoreNonUniformScaling` to turn off non uniform scaling compensation ([Deltakosh](https://github.com/deltakosh))
 - AssetsManager tasks will only run when their state is INIT. It is now possible to remove a task from the assets manager ([RaananW](https://github.com/RaananW))

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

@@ -20,10 +20,13 @@ module BABYLON {
          * If the behavior is currently in a dragging state
          */
         public dragging = false;
+        /**
+         * The distance towards the target drag position to move each frame. This can be useful to avoid jitter. Set this to 1 for no delay. (Default: 0.2)
+         */
+        public dragDeltaRatio = 0.2;
         // Debug mode will display drag planes to help visualize behavior
         private _debugMode = false;
-        private _maxDragAngle = Math.PI/5;
-        
+        private _moving = false;
         /**
          *  Fires each time the attached mesh is dragged with the pointer
          *  * delta between last drag position and current drag position in world space
@@ -44,10 +47,6 @@ module BABYLON {
          *  If the attached mesh should be moved when dragged
          */
         public moveAttached = true;
-        /**
-         *  Mesh with the position where the drag plane should be placed
-         */
-        public _dragPlaneParent:Nullable<Mesh>=null;
 
         /**
          *  If the drag behavior will react to drag events (Default: true)
@@ -116,6 +115,7 @@ module BABYLON {
             this.lastDragPosition = new BABYLON.Vector3(0,0,0);
             var delta = new BABYLON.Vector3(0,0,0);
             var dragLength = 0;
+            var targetPosition = new BABYLON.Vector3(0,0,0);
 
             var pickPredicate = (m:AbstractMesh)=>{
                 return this._attachedNode == m || m.isDescendantOf(this._attachedNode)
@@ -128,14 +128,15 @@ module BABYLON {
                 
                 if (pointerInfo.type == BABYLON.PointerEventTypes.POINTERDOWN) {
                     
-                    if(!this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)){
-                        this._updateDragPlanePosition(pointerInfo.pickInfo.ray);
+                    if(!this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.pickedPoint && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)){
+                        this._updateDragPlanePosition(pointerInfo.pickInfo.ray, pointerInfo.pickInfo.pickedPoint);
                         var pickedPoint = this._pickWithRayOnDragPlane(pointerInfo.pickInfo.ray);
                         if(pickedPoint){
                             this.dragging = true;
                             this.currentDraggingPointerID = (<PointerEvent>pointerInfo.event).pointerId;
                             this.lastDragPosition.copyFrom(pickedPoint);
                             this.onDragStartObservable.notifyObservers({dragPlanePoint: pickedPoint, pointerId: this.currentDraggingPointerID});
+                            targetPosition.copyFrom((<Mesh>this._attachedNode).absolutePosition)
                         }
                     }
                 }else if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERUP){
@@ -144,15 +145,12 @@ module BABYLON {
                     }
                 }else if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERMOVE){
                     if(this.currentDraggingPointerID == (<PointerEvent>pointerInfo.event).pointerId && this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.ray){
+                        this._moving = true;
                         var pickedPoint = this._pickWithRayOnDragPlane(pointerInfo.pickInfo.ray);
                         
-                         // Get angle between drag plane and ray. Only update the drag plane at non steep angles to avoid jumps in delta position
-                        var angle = Math.acos(Vector3.Dot(this._dragPlane.forward, pointerInfo.pickInfo.ray.direction));
-                        if(angle < this._maxDragAngle){
-                            this._updateDragPlanePosition(pointerInfo.pickInfo.ray);
-                        }
-                        
                         if (pickedPoint) {
+                            this._updateDragPlanePosition(pointerInfo.pickInfo.ray, pickedPoint);
+
                             // depending on the drag mode option drag accordingly
                             if(this.options.dragAxis){
                                 // Convert local drag axis to world
@@ -166,22 +164,30 @@ module BABYLON {
                                 dragLength = delta.length();
                                 pickedPoint.subtractToRef(this.lastDragPosition, delta);
                             }
-                            if(this.moveAttached){
-                                (<Mesh>this._attachedNode).absolutePosition.addToRef(delta, this._tmpVector);
-                                (<Mesh>this._attachedNode).setAbsolutePosition(this._tmpVector);
-                            }
+                            targetPosition.addInPlace(delta);
                             this.onDragObservable.notifyObservers({dragDistance: dragLength, delta: delta, dragPlanePoint: pickedPoint, dragPlaneNormal: this._dragPlane.forward, pointerId: this.currentDraggingPointerID});
                             this.lastDragPosition.copyFrom(pickedPoint);
                         }
                     }
                 }
             });
+
+            this._scene.onBeforeRenderObservable.add(()=>{
+                if(this._moving && this.moveAttached){
+                    // Slowly move mesh to avoid jitter
+                    targetPosition.subtractToRef((<Mesh>this._attachedNode).absolutePosition, this._tmpVector);
+                    this._tmpVector.scaleInPlace(0.2);
+                    (<Mesh>this._attachedNode).getAbsolutePosition().addToRef(this._tmpVector, this._tmpVector);
+                    (<Mesh>this._attachedNode).setAbsolutePosition(this._tmpVector);
+                }
+            });
         }
 
         public releaseDrag(){
             this.dragging = false;
             this.onDragEndObservable.notifyObservers({dragPlanePoint: this.lastDragPosition, pointerId: this.currentDraggingPointerID});
             this.currentDraggingPointerID = -1;
+            this._moving = false;
         }
 
         private _pickWithRayOnDragPlane(ray:Nullable<Ray>){
@@ -205,8 +211,8 @@ module BABYLON {
         private _localAxis = new Vector3(0,0,0);
         private _lookAt = new Vector3(0,0,0); 
         // Position the drag plane based on the attached mesh position, for single axis rotate the plane along the axis to face the camera
-        private _updateDragPlanePosition(ray:Ray){
-            this._pointA.copyFrom(this._dragPlaneParent ? this._dragPlaneParent.absolutePosition : (<Mesh>this._attachedNode).absolutePosition);
+        private _updateDragPlanePosition(ray:Ray, dragPlanePosition:Vector3){
+            this._pointA.copyFrom(dragPlanePosition);
             if(this.options.dragAxis){
                 this.useObjectOrienationForDragging ? Vector3.TransformCoordinatesToRef(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix(), this._localAxis) : this._localAxis.copyFrom(this.options.dragAxis);
 

+ 10 - 4
src/Behaviors/Mesh/babylon.sixDofDragBehavior.ts

@@ -11,13 +11,19 @@ module BABYLON {
         private _virtualOriginMesh:AbstractMesh;
         private _virtualDragMesh:AbstractMesh;
         private _pointerObserver:Nullable<Observer<PointerInfo>>;
-        // How much faster the object should move when its further away
-        private _sixDofZDragFactor = 5;
+        /**
+         * How much faster the object should move when the controller is moving towards it. This is useful to bring objects that are far away from the user to them faster. Set this to 0 to avoid any speed increase. (Default: 5)
+         */
+         private zDragFactor = 5;
         /**
          * If the behavior is currently in a dragging state
          */
         public dragging = false;
         /**
+         * The distance towards the target drag position to move each frame. This can be useful to avoid jitter. Set this to 1 for no delay. (Default: 0.2)
+         */
+        public dragDeltaRatio = 0.2;
+        /**
          * The id of the pointer that is currently interacting with the behavior (-1 when no pointer is active)
          */
         public currentDraggingPointerID = -1;
@@ -103,7 +109,7 @@ module BABYLON {
                         this._virtualOriginMesh.addChild(this._virtualDragMesh);
                         // Determine how much the controller moved to/away towards the dragged object and use this to move the object further when its further away
                         var zDragDistance = Vector3.Dot(localOriginDragDifference, this._virtualOriginMesh.position.normalizeToNew());
-                        this._virtualDragMesh.position.z -= this._virtualDragMesh.position.z < 1 ? zDragDistance*this._sixDofZDragFactor : zDragDistance*this._sixDofZDragFactor*this._virtualDragMesh.position.z;
+                        this._virtualDragMesh.position.z -= this._virtualDragMesh.position.z < 1 ? zDragDistance*this.zDragFactor : zDragDistance*this.zDragFactor*this._virtualDragMesh.position.z;
                         if(this._virtualDragMesh.position.z < 0){
                             this._virtualDragMesh.position.z = 0;
                         }
@@ -126,7 +132,7 @@ module BABYLON {
             this._sceneRenderObserver = ownerNode.getScene().onBeforeRenderObservable.add(()=>{
                 if(this.dragging && pickedMesh){
                     // Slowly move mesh to avoid jitter
-                    pickedMesh.position.addInPlace(this._targetPosition.subtract(pickedMesh.position).scale(0.2));
+                    pickedMesh.position.addInPlace(this._targetPosition.subtract(pickedMesh.position).scale(this.dragDeltaRatio));
                 }
             });
         }

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

@@ -12,7 +12,8 @@ module BABYLON {
          */
         constructor(gizmoLayer:UtilityLayerRenderer, dragAxis:Vector3, color:Color3){
             super(gizmoLayer);
-
+            this.updateGizmoRotationToMatchAttachedMesh = false;
+            
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;

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

@@ -12,7 +12,8 @@ module BABYLON {
          */
         constructor(gizmoLayer:UtilityLayerRenderer, dragAxis:Vector3, color:Color3){
             super(gizmoLayer);
-
+            this.updateGizmoRotationToMatchAttachedMesh=false;
+            
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;

+ 2 - 6
src/Gizmos/babylon.boundingBoxGizmo.ts

@@ -9,6 +9,7 @@ module BABYLON {
         private _boundingDimensions = new BABYLON.Vector3(1,1,1);
         private _renderObserver:Nullable<Observer<Scene>> = null;
         private _pointerObserver:Nullable<Observer<PointerInfo>> = null;
+        private _scaleDragSpeed = 0.2;
 
         /**
          * Creates an BoundingBoxGizmo
@@ -121,6 +122,7 @@ module BABYLON {
                                 
                                 // Get the change in bounding box size/2 and add this to the mesh's position to offset from scaling with center pivot point
                                 var deltaScale = new Vector3(event.dragDistance,event.dragDistance,event.dragDistance);
+                                deltaScale.scaleInPlace(this._scaleDragSpeed);
                                 var scaleRatio = deltaScale.divide(this.attachedMesh.scaling).scaleInPlace(0.5);
                                 var moveDirection = boundBoxDimensions.multiply(scaleRatio).multiplyInPlace(dragAxis);
                                 var worldMoveDirection = Vector3.TransformCoordinates(moveDirection, this.attachedMesh.getWorldMatrix().getRotationMatrix());
@@ -184,12 +186,6 @@ module BABYLON {
                 var boundBoxDimensions = boundingInfo.maximum.subtract(boundingInfo.minimum).multiplyInPlace(this.attachedMesh.scaling);
                 this._boundingDimensions.copyFrom(boundBoxDimensions);
                 this._lineBoundingBox.scaling.copyFrom(this._boundingDimensions);
-                if(!this.attachedMesh.rotationQuaternion){
-                    this.attachedMesh.rotationQuaternion = new BABYLON.Quaternion();
-                }
-                this._lineBoundingBox.rotationQuaternion!.copyFrom(this.attachedMesh.rotationQuaternion);
-                this._rotateSpheresParent.rotationQuaternion!.copyFrom(this.attachedMesh.rotationQuaternion);
-                this._scaleBoxesParent.rotationQuaternion!.copyFrom(this.attachedMesh.rotationQuaternion);
             }
 
             // Update rotation sphere locations

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

@@ -12,6 +12,14 @@ module BABYLON {
          */
         public attachedMesh:Nullable<AbstractMesh>;
         /**
+         * If set the gizmo's rotation will be updated to match the attached mesh each frame (Default: true)
+         */
+        public updateGizmoRotationToMatchAttachedMesh = true;
+        /**
+         * If set the gizmo's position will be updated to match the attached mesh each frame (Default: true)
+         */
+        public updateGizmoPositionToMatchAttachedMesh = true;
+        /**
          * When set, the gizmo will always appear the same size no matter where the camera is (default: false)
          */
         protected _updateScale = true;
@@ -44,7 +52,15 @@ module BABYLON {
                     this._rootMesh.scaling.set(dist, dist, dist);
                 }
                 if(this.attachedMesh){
-                    this._rootMesh.position.copyFrom(this.attachedMesh.position);
+                    if(this.updateGizmoRotationToMatchAttachedMesh){
+                        if(!this._rootMesh.rotationQuaternion){
+                            this._rootMesh.rotationQuaternion = new BABYLON.Quaternion();
+                        }
+                        Quaternion.FromRotationMatrixToRef(this.attachedMesh.getWorldMatrix().getRotationMatrix(), this._rootMesh.rotationQuaternion);
+                    }
+                    if(this.updateGizmoPositionToMatchAttachedMesh){
+                        this._rootMesh.position.copyFrom(this.attachedMesh.absolutePosition);
+                    }
                 }
             })
         }

+ 2 - 1
src/Gizmos/babylon.planeRotationGizmo.ts

@@ -12,7 +12,8 @@ module BABYLON {
          */
         constructor(gizmoLayer:UtilityLayerRenderer, planeNormal:Vector3, color:Color3){
             super(gizmoLayer);
-
+            this.updateGizmoRotationToMatchAttachedMesh=false;
+            
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;