|
@@ -8,7 +8,18 @@ module BABYLON {
|
|
|
private _scene:Scene;
|
|
|
private _pointerObserver:Nullable<Observer<PointerInfo>>;
|
|
|
private static _planeScene:Scene;
|
|
|
- private _draggingID = -1;
|
|
|
+ /**
|
|
|
+ * The id of the pointer that is currently interacting with the behavior (-1 when no pointer is active)
|
|
|
+ */
|
|
|
+ public currentDraggingPointerID = -1;
|
|
|
+ /**
|
|
|
+ * The last position where the pointer hit the drag plane in world space
|
|
|
+ */
|
|
|
+ public lastDragPosition:Vector3;
|
|
|
+ /**
|
|
|
+ * If the behavior is currently in a dragging state
|
|
|
+ */
|
|
|
+ public dragging = false;
|
|
|
// Debug mode will display drag planes to help visualize behavior
|
|
|
private _debugMode = false;
|
|
|
private _maxDragAngle = Math.PI/5;
|
|
@@ -20,15 +31,15 @@ module BABYLON {
|
|
|
* * dragPlaneNormal normal of the current drag plane used during the drag
|
|
|
* * dragPlanePoint in world space where the drag intersects the drag plane
|
|
|
*/
|
|
|
- public onDragObservable = new Observable<{delta:Vector3, dragPlanePoint:Vector3, dragPlaneNormal:Vector3, dragDistance:number}>()
|
|
|
+ public onDragObservable = new Observable<{delta:Vector3, dragPlanePoint:Vector3, dragPlaneNormal:Vector3, dragDistance:number, pointerId:number}>()
|
|
|
/**
|
|
|
* Fires each time a drag begins (eg. mouse down on mesh)
|
|
|
*/
|
|
|
- public onDragStartObservable = new Observable<{dragPlanePoint:Vector3}>()
|
|
|
+ public onDragStartObservable = new Observable<{dragPlanePoint:Vector3, pointerId:number}>()
|
|
|
/**
|
|
|
* Fires each time a drag ends (eg. mouse release after drag)
|
|
|
*/
|
|
|
- public onDragEndObservable = new Observable<{dragPlanePoint:Vector3}>()
|
|
|
+ public onDragEndObservable = new Observable<{dragPlanePoint:Vector3, pointerId:number}>()
|
|
|
/**
|
|
|
* If the attached mesh should be moved when dragged
|
|
|
*/
|
|
@@ -95,8 +106,7 @@ module BABYLON {
|
|
|
this._dragPlane = BABYLON.Mesh.CreatePlane("pointerDragPlane", this._debugMode ? 1 : 10000, PointerDragBehavior._planeScene, false, BABYLON.Mesh.DOUBLESIDE);
|
|
|
|
|
|
// State of the drag
|
|
|
- var dragging = false;
|
|
|
- var lastPosition = new BABYLON.Vector3(0,0,0);
|
|
|
+ this.lastDragPosition = new BABYLON.Vector3(0,0,0);
|
|
|
var delta = new BABYLON.Vector3(0,0,0);
|
|
|
var dragLength = 0;
|
|
|
|
|
@@ -110,24 +120,23 @@ module BABYLON {
|
|
|
}
|
|
|
|
|
|
if (pointerInfo.type == BABYLON.PointerEventTypes.POINTERDOWN) {
|
|
|
- if(!dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)){
|
|
|
+
|
|
|
+ if(!this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)){
|
|
|
this._updateDragPlanePosition(pointerInfo.pickInfo.ray);
|
|
|
var pickedPoint = this._pickWithRayOnDragPlane(pointerInfo.pickInfo.ray);
|
|
|
if(pickedPoint){
|
|
|
- dragging = true;
|
|
|
- this._draggingID = (<PointerEvent>pointerInfo.event).pointerId;
|
|
|
- lastPosition.copyFrom(pickedPoint);
|
|
|
- this.onDragStartObservable.notifyObservers({dragPlanePoint: pickedPoint});
|
|
|
+ this.dragging = true;
|
|
|
+ this.currentDraggingPointerID = (<PointerEvent>pointerInfo.event).pointerId;
|
|
|
+ this.lastDragPosition.copyFrom(pickedPoint);
|
|
|
+ this.onDragStartObservable.notifyObservers({dragPlanePoint: pickedPoint, pointerId: this.currentDraggingPointerID});
|
|
|
}
|
|
|
}
|
|
|
}else if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERUP){
|
|
|
- if(this._draggingID == (<PointerEvent>pointerInfo.event).pointerId){
|
|
|
- dragging = false;
|
|
|
- this._draggingID = -1;
|
|
|
- this.onDragEndObservable.notifyObservers({dragPlanePoint: lastPosition});
|
|
|
+ if(this.currentDraggingPointerID == (<PointerEvent>pointerInfo.event).pointerId){
|
|
|
+ this.releaseDrag();
|
|
|
}
|
|
|
}else if(pointerInfo.type == BABYLON.PointerEventTypes.POINTERMOVE){
|
|
|
- if(this._draggingID == (<PointerEvent>pointerInfo.event).pointerId && dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.ray){
|
|
|
+ if(this.currentDraggingPointerID == (<PointerEvent>pointerInfo.event).pointerId && this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.ray){
|
|
|
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
|
|
@@ -143,23 +152,29 @@ module BABYLON {
|
|
|
var worldDragAxis = Vector3.TransformCoordinates(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix());
|
|
|
|
|
|
// Project delta drag from the drag plane onto the drag axis
|
|
|
- dragLength = BABYLON.Vector3.Dot(pickedPoint.subtract(lastPosition), worldDragAxis)
|
|
|
+ dragLength = BABYLON.Vector3.Dot(pickedPoint.subtract(this.lastDragPosition), worldDragAxis)
|
|
|
worldDragAxis.scaleToRef(dragLength, delta);
|
|
|
}else{
|
|
|
dragLength = delta.length();
|
|
|
- pickedPoint.subtractToRef(lastPosition, delta);
|
|
|
+ pickedPoint.subtractToRef(this.lastDragPosition, delta);
|
|
|
}
|
|
|
if(this.moveAttached){
|
|
|
(<Mesh>this._attachedNode).position.addInPlace(delta);
|
|
|
}
|
|
|
- this.onDragObservable.notifyObservers({dragDistance: dragLength, delta: delta, dragPlanePoint: pickedPoint, dragPlaneNormal: this._dragPlane.forward});
|
|
|
- lastPosition.copyFrom(pickedPoint);
|
|
|
+ this.onDragObservable.notifyObservers({dragDistance: dragLength, delta: delta, dragPlanePoint: pickedPoint, dragPlaneNormal: this._dragPlane.forward, pointerId: this.currentDraggingPointerID});
|
|
|
+ this.lastDragPosition.copyFrom(pickedPoint);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ public releaseDrag(){
|
|
|
+ this.dragging = false;
|
|
|
+ this.onDragEndObservable.notifyObservers({dragPlanePoint: this.lastDragPosition, pointerId: this.currentDraggingPointerID});
|
|
|
+ this.currentDraggingPointerID = -1;
|
|
|
+ }
|
|
|
+
|
|
|
private _pickWithRayOnDragPlane(ray:Nullable<Ray>){
|
|
|
if(!ray){
|
|
|
return null;
|