// @ts-nocheck /* tslint-disable */ /** * @author qiao / https://github.com/qiao * @author mrdoob / http://mrdoob.com * @author alteredq / http://alteredqualia.com/ * @author WestLangley / http://github.com/WestLangley */ /** * Edited from THREE.EditorControls * Changes to this.rotate function to take spherical wrt z as vertical axis * */ import { Box3, EventDispatcher, Matrix3, Sphere, Spherical, Vector2, Vector3 } from 'three'; const EditorControls = function(object, domElement) { domElement = domElement !== undefined ? domElement : document; // API this.enabled = true; this.center = new Vector3(); this.panSpeed = 0.002; this.zoomSpeed = 0.1; this.rotationSpeed = 0.005; // internals const scope = this; const vector = new Vector3(); const delta = new Vector3(); const box = new Box3(); const STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 }; let state = STATE.NONE; const { center } = this; const normalMatrix = new Matrix3(); const pointer = new Vector2(); const pointerOld = new Vector2(); const spherical = new Spherical(); const sphere = new Sphere(); // events const changeEvent = { type: 'change' }; this.focus = function(target) { let distance; box.setFromObject(target); if (box.isEmpty() === false) { box.getCenter(center); distance = box.getBoundingSphere(sphere).radius; } else { // Focusing on an Group, AmbientLight, etc center.setFromMatrixPosition(target.matrixWorld); distance = 0.1; } delta.set(0, 0, 1); delta.applyQuaternion(object.quaternion); delta.multiplyScalar(distance * 4); object.position.copy(center).add(delta); scope.dispatchEvent(changeEvent); }; this.pan = function(delta) { const distance = object.position.distanceTo(center); delta.multiplyScalar(distance * scope.panSpeed); delta.applyMatrix3(normalMatrix.getNormalMatrix(object.matrix)); object.position.add(delta); center.add(delta); scope.dispatchEvent(changeEvent); }; this.zoom = function(delta) { const distance = object.position.distanceTo(center); delta.multiplyScalar(distance * scope.zoomSpeed); if (delta.length() > distance) return; delta.applyMatrix3(normalMatrix.getNormalMatrix(object.matrix)); object.position.add(delta); scope.dispatchEvent(changeEvent); }; this.rotate = function(delta) { vector.copy(object.position).sub(center); // spherical.setFromVector3( vector ); spherical.setFromCartesianCoords(-1 * vector.x, vector.z, vector.y); spherical.theta += delta.x * scope.rotationSpeed; spherical.phi += delta.y * scope.rotationSpeed; spherical.makeSafe(); const tempRelPosition = vector.setFromSpherical(spherical); vector.set(-1 * tempRelPosition.x, tempRelPosition.z, tempRelPosition.y); object.position.copy(center).add(vector); object.lookAt(center); scope.dispatchEvent(changeEvent); }; // mouse function onMouseDown(event) { if (scope.enabled === false) return; if (event.button === 0) { state = STATE.ROTATE; } else if (event.button === 1) { state = STATE.ZOOM; } else if (event.button === 2) { state = STATE.PAN; } pointerOld.set(event.clientX, event.clientY); domElement.addEventListener('mousemove', onMouseMove, false); domElement.addEventListener('mouseup', onMouseUp, false); domElement.addEventListener('mouseout', onMouseUp, false); domElement.addEventListener('dblclick', onMouseUp, false); } function onMouseMove(event) { if (scope.enabled === false) return; pointer.set(event.clientX, event.clientY); const movementX = pointer.x - pointerOld.x; const movementY = pointer.y - pointerOld.y; if (state === STATE.ROTATE) { scope.rotate(delta.set(-movementX, -movementY, 0)); } else if (state === STATE.ZOOM) { scope.zoom(delta.set(0, 0, movementY)); } else if (state === STATE.PAN) { scope.pan(delta.set(-movementX, movementY, 0)); } pointerOld.set(event.clientX, event.clientY); } function onMouseUp(event) { domElement.removeEventListener('mousemove', onMouseMove, false); domElement.removeEventListener('mouseup', onMouseUp, false); domElement.removeEventListener('mouseout', onMouseUp, false); domElement.removeEventListener('dblclick', onMouseUp, false); state = STATE.NONE; } function onMouseWheel(event) { event.preventDefault(); // Normalize deltaY due to https://bugzilla.mozilla.org/show_bug.cgi?id=1392460 scope.zoom(delta.set(0, 0, event.deltaY > 0 ? 1 : -1)); } function contextmenu(event) { event.preventDefault(); } this.dispose = function() { domElement.removeEventListener('contextmenu', contextmenu, false); domElement.removeEventListener('mousedown', onMouseDown, false); domElement.removeEventListener('wheel', onMouseWheel, false); domElement.removeEventListener('mousemove', onMouseMove, false); domElement.removeEventListener('mouseup', onMouseUp, false); domElement.removeEventListener('mouseout', onMouseUp, false); domElement.removeEventListener('dblclick', onMouseUp, false); domElement.removeEventListener('touchstart', touchStart, false); domElement.removeEventListener('touchmove', touchMove, false); }; domElement.addEventListener('contextmenu', contextmenu, false); domElement.addEventListener('mousedown', onMouseDown, false); domElement.addEventListener('wheel', onMouseWheel, false); // touch const touches = [new Vector3(), new Vector3(), new Vector3()]; const prevTouches = [new Vector3(), new Vector3(), new Vector3()]; let prevDistance = null; function touchStart(event) { if (scope.enabled === false) return; switch (event.touches.length) { case 1: touches[0] .set(event.touches[0].pageX, event.touches[0].pageY, 0) .divideScalar(window.devicePixelRatio); touches[1] .set(event.touches[0].pageX, event.touches[0].pageY, 0) .divideScalar(window.devicePixelRatio); break; case 2: touches[0] .set(event.touches[0].pageX, event.touches[0].pageY, 0) .divideScalar(window.devicePixelRatio); touches[1] .set(event.touches[1].pageX, event.touches[1].pageY, 0) .divideScalar(window.devicePixelRatio); prevDistance = touches[0].distanceTo(touches[1]); break; } prevTouches[0].copy(touches[0]); prevTouches[1].copy(touches[1]); } function touchMove(event) { if (scope.enabled === false) return; event.preventDefault(); event.stopPropagation(); function getClosest(touch, touches) { let closest = touches[0]; for (const i in touches) { if (closest.distanceTo(touch) > touches[i].distanceTo(touch)) { closest = touches[i]; } } return closest; } switch (event.touches.length) { case 1: touches[0] .set(event.touches[0].pageX, event.touches[0].pageY, 0) .divideScalar(window.devicePixelRatio); touches[1] .set(event.touches[0].pageX, event.touches[0].pageY, 0) .divideScalar(window.devicePixelRatio); scope.rotate( touches[0] .sub(getClosest(touches[0], prevTouches)) .multiplyScalar(-1), ); break; case 2: touches[0] .set(event.touches[0].pageX, event.touches[0].pageY, 0) .divideScalar(window.devicePixelRatio); touches[1] .set(event.touches[1].pageX, event.touches[1].pageY, 0) .divideScalar(window.devicePixelRatio); let distance = touches[0].distanceTo(touches[1]); scope.zoom(delta.set(0, 0, prevDistance - distance)); prevDistance = distance; let offset0 = touches[0] .clone() .sub(getClosest(touches[0], prevTouches)); let offset1 = touches[1] .clone() .sub(getClosest(touches[1], prevTouches)); offset0.x = -offset0.x; offset1.x = -offset1.x; scope.pan(offset0.add(offset1)); break; } prevTouches[0].copy(touches[0]); prevTouches[1].copy(touches[1]); } domElement.addEventListener('touchstart', touchStart, false); domElement.addEventListener('touchmove', touchMove, false); }; EditorControls.prototype = Object.create(EventDispatcher.prototype); EditorControls.prototype.constructor = EditorControls; export { EditorControls };