|
@@ -13,6 +13,7 @@
|
|
|
public upperRadiusLimit = null;
|
|
|
public angularSensibility = 1000.0;
|
|
|
public wheelPrecision = 3.0;
|
|
|
+ public pinchPrecision = 2.0;
|
|
|
public keysUp = [38];
|
|
|
public keysDown = [40];
|
|
|
public keysLeft = [37];
|
|
@@ -20,7 +21,7 @@
|
|
|
public zoomOnFactor = 1;
|
|
|
public targetScreenOffset = Vector2.Zero();
|
|
|
|
|
|
-
|
|
|
+
|
|
|
private _keys = [];
|
|
|
private _viewMatrix = new BABYLON.Matrix();
|
|
|
private _attachedElement: HTMLElement;
|
|
@@ -50,19 +51,6 @@
|
|
|
private _previousBeta: number;
|
|
|
private _previousRadius: number;
|
|
|
|
|
|
- // Pinch
|
|
|
- // value for pinch step scaling
|
|
|
- // set to 20 by default
|
|
|
- public pinchPrecision = 20;
|
|
|
- // Event for pinch
|
|
|
- private _touchStart: (e: any) => void;
|
|
|
- private _touchMove: (e: any) => void;
|
|
|
- private _touchEnd: (e: any) => void;
|
|
|
- // Method for pinch
|
|
|
- private _pinchStart: (e: any) => void;
|
|
|
- private _pinchMove: (e: any) => void;
|
|
|
- private _pinchEnd: (e: any) => void;
|
|
|
-
|
|
|
constructor(name: string, public alpha: number, public beta: number, public radius: number, public target: any, scene: Scene) {
|
|
|
super(name, BABYLON.Vector3.Zero(), scene);
|
|
|
|
|
@@ -109,14 +97,10 @@
|
|
|
|
|
|
// Methods
|
|
|
public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
|
|
|
- var previousPosition;
|
|
|
- var pointerId;
|
|
|
- // to know if pinch started
|
|
|
- var pinchStarted = false;
|
|
|
- // two pinch point on X
|
|
|
- // that will use for find if user action is pinch open or pinch close
|
|
|
- var pinchPointX1, pinchPointX2;
|
|
|
-
|
|
|
+ var cacheSoloPointer; // cache pointer object for better perf on camera rotation
|
|
|
+ var previousPinchDistance = 0;
|
|
|
+ var pointers = new BABYLON.SmartCollection();
|
|
|
+
|
|
|
if (this._attachedElement) {
|
|
|
return;
|
|
|
}
|
|
@@ -126,59 +110,69 @@
|
|
|
|
|
|
if (this._onPointerDown === undefined) {
|
|
|
this._onPointerDown = evt => {
|
|
|
-
|
|
|
- if (pointerId) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- pointerId = evt.pointerId;
|
|
|
-
|
|
|
- previousPosition = {
|
|
|
- x: evt.clientX,
|
|
|
- y: evt.clientY
|
|
|
- };
|
|
|
-
|
|
|
+ pointers.add(evt.pointerId, { x: evt.clientX, y: evt.clientY, type: evt.pointerType });
|
|
|
+ cacheSoloPointer = pointers.item(evt.pointerId);
|
|
|
if (!noPreventDefault) {
|
|
|
evt.preventDefault();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
this._onPointerUp = evt => {
|
|
|
- previousPosition = null;
|
|
|
- pointerId = null;
|
|
|
+ cacheSoloPointer = null;
|
|
|
+ previousPinchDistance = 0;
|
|
|
+ pointers.remove(evt.pointerId);
|
|
|
if (!noPreventDefault) {
|
|
|
evt.preventDefault();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-
|
|
|
this._onPointerMove = evt => {
|
|
|
- if (!previousPosition) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (pointerId !== evt.pointerId) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // return pinch is started
|
|
|
- if (pinchStarted) {
|
|
|
- return;
|
|
|
+ if (!noPreventDefault) {
|
|
|
+ evt.preventDefault();
|
|
|
}
|
|
|
|
|
|
- var offsetX = evt.clientX - previousPosition.x;
|
|
|
- var offsetY = evt.clientY - previousPosition.y;
|
|
|
-
|
|
|
- this.inertialAlphaOffset -= offsetX / this.angularSensibility;
|
|
|
- this.inertialBetaOffset -= offsetY / this.angularSensibility;
|
|
|
-
|
|
|
- previousPosition = {
|
|
|
- x: evt.clientX,
|
|
|
- y: evt.clientY
|
|
|
- };
|
|
|
+ switch (pointers.count) {
|
|
|
+
|
|
|
+ case 1: //normal camera rotation
|
|
|
+ //var offsetX = evt.clientX - pointers.item(evt.pointerId).x;
|
|
|
+ //var offsetY = evt.clientY - pointers.item(evt.pointerId).y;
|
|
|
+ var offsetX = evt.clientX - cacheSoloPointer.x;
|
|
|
+ var offsetY = evt.clientY - cacheSoloPointer.y;
|
|
|
+ this.inertialAlphaOffset -= offsetX / this.angularSensibility;
|
|
|
+ this.inertialBetaOffset -= offsetY / this.angularSensibility;
|
|
|
+ //pointers.item(evt.pointerId).x = evt.clientX;
|
|
|
+ //pointers.item(evt.pointerId).y = evt.clientY;
|
|
|
+ cacheSoloPointer.x = evt.clientX;
|
|
|
+ cacheSoloPointer.y = evt.clientY;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 2: //pinch
|
|
|
+ //if (noPreventDefault) { evt.preventDefault(); } //if pinch gesture, could be usefull to force preventDefault to avoid html page scroll/zoom in some mobile browsers
|
|
|
+ pointers.item(evt.pointerId).x = evt.clientX;
|
|
|
+ pointers.item(evt.pointerId).y = evt.clientY;
|
|
|
+ var direction = 1;
|
|
|
+ var distX = pointers.getItemByIndex(0).x - pointers.getItemByIndex(1).x;
|
|
|
+ var distY = pointers.getItemByIndex(0).y - pointers.getItemByIndex(1).y;
|
|
|
+ var pinchSquaredDistance = (distX * distX) + (distY * distY);
|
|
|
+ if (previousPinchDistance === 0) {
|
|
|
+ previousPinchDistance = pinchSquaredDistance;
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- if (!noPreventDefault) {
|
|
|
- evt.preventDefault();
|
|
|
+ if (pinchSquaredDistance != previousPinchDistance) {
|
|
|
+ if (pinchSquaredDistance > previousPinchDistance) {
|
|
|
+ direction = -1;
|
|
|
+ }
|
|
|
+ this.inertialRadiusOffset += (pinchSquaredDistance - previousPinchDistance) / (this.pinchPrecision * this.wheelPrecision * this.angularSensibility);
|
|
|
+ previousPinchDistance = pinchSquaredDistance;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ if (pointers.item(evt.pointerId)) {
|
|
|
+ pointers.item(evt.pointerId).x = evt.clientX;
|
|
|
+ pointers.item(evt.pointerId).y = evt.clientY;
|
|
|
+ }
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -187,11 +181,6 @@
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // return pinch is started
|
|
|
- if (pinchStarted) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
|
|
|
var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
|
|
|
|
|
@@ -261,7 +250,9 @@
|
|
|
|
|
|
this._onLostFocus = () => {
|
|
|
this._keys = [];
|
|
|
- pointerId = null;
|
|
|
+ pointers.empty();
|
|
|
+ previousPinchDistance = 0;
|
|
|
+ cacheSoloPointer = null;
|
|
|
};
|
|
|
|
|
|
this._onGestureStart = e => {
|
|
@@ -294,67 +285,12 @@
|
|
|
this.inertialAlphaOffset = 0;
|
|
|
this.inertialBetaOffset = 0;
|
|
|
this.inertialRadiusOffset = 0;
|
|
|
- previousPosition = null;
|
|
|
- pointerId = null;
|
|
|
- };
|
|
|
-
|
|
|
- this._touchStart = event => {
|
|
|
- if (event.touches.length === 2) {
|
|
|
- //-- start pinch if two fingers on the screen
|
|
|
- pinchStarted = true;
|
|
|
- this._pinchStart(event);
|
|
|
- }
|
|
|
- };
|
|
|
- this._touchMove = event => {
|
|
|
- if (pinchStarted) {
|
|
|
- //-- make scaling
|
|
|
- this._pinchMove(event);
|
|
|
- }
|
|
|
- };
|
|
|
- this._touchEnd = event => {
|
|
|
- if (pinchStarted) {
|
|
|
- //-- end of pinch
|
|
|
- this._pinchEnd(event);
|
|
|
- }
|
|
|
+ pointers.empty();
|
|
|
+ previousPinchDistance = 0;
|
|
|
+ cacheSoloPointer = null;
|
|
|
};
|
|
|
|
|
|
- this._pinchStart = event => {
|
|
|
- // save origin touch point
|
|
|
- pinchPointX1 = event.touches[0].clientX;
|
|
|
- pinchPointX2 = event.touches[1].clientX;
|
|
|
- // block the camera
|
|
|
- // if not it rotate around target during pinch
|
|
|
- pinchStarted = true;
|
|
|
- };
|
|
|
- this._pinchMove = event => {
|
|
|
- // variable for new camera's radius
|
|
|
- var delta = 0;
|
|
|
- // variables to know if pinch open or pinch close
|
|
|
- var direction = 1;
|
|
|
- var distanceXOrigine, distanceXNow;
|
|
|
-
|
|
|
- if (event.touches.length !== 2)
|
|
|
- return;
|
|
|
- // calculate absolute distances of the two fingers
|
|
|
- distanceXOrigine = Math.abs(pinchPointX1 - pinchPointX2);
|
|
|
- distanceXNow = Math.abs(event.touches[0].clientX - event.touches[1].clientX);
|
|
|
-
|
|
|
- // if distanceXNow < distanceXOrigine -> pinch close so direction = -1
|
|
|
- if (distanceXNow < distanceXOrigine) {
|
|
|
- direction = -1;
|
|
|
- }
|
|
|
- // calculate new radius
|
|
|
- delta = (this.pinchPrecision / (this.wheelPrecision * 40)) * direction;
|
|
|
- // set new radius
|
|
|
- this.inertialRadiusOffset -= delta;
|
|
|
- // save origin touch point
|
|
|
- pinchPointX1 = event.touches[0].clientX;
|
|
|
- pinchPointX2 = event.touches[1].clientX;
|
|
|
- };
|
|
|
- this._pinchEnd = event => {
|
|
|
- // cancel pinch and deblock camera rotation
|
|
|
- pinchStarted = false;
|
|
|
- };
|
|
|
+
|
|
|
}
|
|
|
|
|
|
element.addEventListener(eventPrefix + "down", this._onPointerDown, false);
|
|
@@ -366,10 +302,6 @@
|
|
|
element.addEventListener("MSGestureChange", this._onGesture, false);
|
|
|
element.addEventListener('mousewheel', this._wheel, false);
|
|
|
element.addEventListener('DOMMouseScroll', this._wheel, false);
|
|
|
- // pinch
|
|
|
- element.addEventListener('touchstart', this._touchStart, false);
|
|
|
- element.addEventListener('touchmove', this._touchMove, false);
|
|
|
- element.addEventListener('touchend', this._touchEnd, false);
|
|
|
|
|
|
Tools.RegisterTopRootEvents([
|
|
|
{ name: "keydown", handler: this._onKeyDown },
|
|
@@ -392,10 +324,6 @@
|
|
|
element.removeEventListener("MSGestureChange", this._onGesture);
|
|
|
element.removeEventListener('mousewheel', this._wheel);
|
|
|
element.removeEventListener('DOMMouseScroll', this._wheel);
|
|
|
- // pinch
|
|
|
- element.removeEventListener('touchstart', this._touchStart);
|
|
|
- element.removeEventListener('touchmove', this._touchMove);
|
|
|
- element.removeEventListener('touchend', this._touchEnd);
|
|
|
|
|
|
Tools.UnregisterTopRootEvents([
|
|
|
{ name: "keydown", handler: this._onKeyDown },
|