(function (global, factory) { if (typeof define === "function" && define.amd) { define(["exports", "three"], factory); } else if (typeof exports !== "undefined") { factory(exports, require("three")); } else { var mod = { exports: {} }; factory(mod.exports, global.three); global.ArcballControls = mod.exports; } })(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _three) { "use strict"; Object.defineProperty(_exports, "__esModule", { value: true }); _exports.ArcballControls = void 0; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } Object.defineProperty(subClass, "prototype", { value: Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }), writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } //trackball state var STATE = { IDLE: Symbol(), ROTATE: Symbol(), PAN: Symbol(), SCALE: Symbol(), FOV: Symbol(), FOCUS: Symbol(), ZROTATE: Symbol(), TOUCH_MULTI: Symbol(), ANIMATION_FOCUS: Symbol(), ANIMATION_ROTATE: Symbol() }; var INPUT = { NONE: Symbol(), ONE_FINGER: Symbol(), ONE_FINGER_SWITCHED: Symbol(), TWO_FINGER: Symbol(), MULT_FINGER: Symbol(), CURSOR: Symbol() }; //cursor center coordinates var _center = { x: 0, y: 0 }; //transformation matrices for gizmos and camera var _transformation = { camera: new _three.Matrix4(), gizmos: new _three.Matrix4() }; //events var _changeEvent = { type: 'change' }; var _startEvent = { type: 'start' }; var _endEvent = { type: 'end' }; var _raycaster = new _three.Raycaster(); var _offset = new _three.Vector3(); /** * * @param {Camera} camera Virtual camera used in the scene * @param {HTMLElement} domElement Renderer's dom element * @param {Scene} scene The scene to be rendered */ var ArcballControls = /*#__PURE__*/function (_EventDispatcher) { _inherits(ArcballControls, _EventDispatcher); var _super = _createSuper(ArcballControls); function ArcballControls(_camera, domElement) { var _this; var scene = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; _classCallCheck(this, ArcballControls); _this = _super.call(this); _defineProperty(_assertThisInitialized(_this), "onWindowResize", function () { var scale = (_this._gizmos.scale.x + _this._gizmos.scale.y + _this._gizmos.scale.z) / 3; _this._tbRadius = _this.calculateTbRadius(_this.camera); var newRadius = _this._tbRadius / scale; var curve = new _three.EllipseCurve(0, 0, newRadius, newRadius); var points = curve.getPoints(_this._curvePts); var curveGeometry = new _three.BufferGeometry().setFromPoints(points); for (var gizmo in _this._gizmos.children) { _this._gizmos.children[gizmo].geometry = curveGeometry; } _this.dispatchEvent(_changeEvent); }); _defineProperty(_assertThisInitialized(_this), "onContextMenu", function (event) { if (!_this.enabled) { return; } for (var i = 0; i < _this.mouseActions.length; i++) { if (_this.mouseActions[i].mouse == 2) { //prevent only if button 2 is actually used event.preventDefault(); break; } } }); _defineProperty(_assertThisInitialized(_this), "onPointerCancel", function () { _this._touchStart.splice(0, _this._touchStart.length); _this._touchCurrent.splice(0, _this._touchCurrent.length); _this._input = INPUT.NONE; }); _defineProperty(_assertThisInitialized(_this), "onPointerDown", function (event) { if (event.button == 0 && event.isPrimary) { _this._downValid = true; _this._downEvents.push(event); _this._downStart = performance.now(); } else { _this._downValid = false; } if (event.pointerType == 'touch' && _this._input != INPUT.CURSOR) { _this._touchStart.push(event); _this._touchCurrent.push(event); switch (_this._input) { case INPUT.NONE: //singleStart _this._input = INPUT.ONE_FINGER; _this.onSinglePanStart(event, 'ROTATE'); window.addEventListener('pointermove', _this.onPointerMove); window.addEventListener('pointerup', _this.onPointerUp); break; case INPUT.ONE_FINGER: case INPUT.ONE_FINGER_SWITCHED: //doubleStart _this._input = INPUT.TWO_FINGER; _this.onRotateStart(); _this.onPinchStart(); _this.onDoublePanStart(); break; case INPUT.TWO_FINGER: //multipleStart _this._input = INPUT.MULT_FINGER; _this.onTriplePanStart(event); break; } } else if (event.pointerType != 'touch' && _this._input == INPUT.NONE) { var modifier = null; if (event.ctrlKey || event.metaKey) { modifier = 'CTRL'; } else if (event.shiftKey) { modifier = 'SHIFT'; } _this._mouseOp = _this.getOpFromAction(event.button, modifier); if (_this._mouseOp != null) { window.addEventListener('pointermove', _this.onPointerMove); window.addEventListener('pointerup', _this.onPointerUp); //singleStart _this._input = INPUT.CURSOR; _this._button = event.button; _this.onSinglePanStart(event, _this._mouseOp); } } }); _defineProperty(_assertThisInitialized(_this), "onPointerMove", function (event) { if (event.pointerType == 'touch' && _this._input != INPUT.CURSOR) { switch (_this._input) { case INPUT.ONE_FINGER: //singleMove _this.updateTouchEvent(event); _this.onSinglePanMove(event, STATE.ROTATE); break; case INPUT.ONE_FINGER_SWITCHED: var movement = _this.calculatePointersDistance(_this._touchCurrent[0], event) * _this._devPxRatio; if (movement >= _this._switchSensibility) { //singleMove _this._input = INPUT.ONE_FINGER; _this.updateTouchEvent(event); _this.onSinglePanStart(event, 'ROTATE'); break; } break; case INPUT.TWO_FINGER: //rotate/pan/pinchMove _this.updateTouchEvent(event); _this.onRotateMove(); _this.onPinchMove(); _this.onDoublePanMove(); break; case INPUT.MULT_FINGER: //multMove _this.updateTouchEvent(event); _this.onTriplePanMove(event); break; } } else if (event.pointerType != 'touch' && _this._input == INPUT.CURSOR) { var modifier = null; if (event.ctrlKey || event.metaKey) { modifier = 'CTRL'; } else if (event.shiftKey) { modifier = 'SHIFT'; } var mouseOpState = _this.getOpStateFromAction(_this._button, modifier); if (mouseOpState != null) { _this.onSinglePanMove(event, mouseOpState); } } //checkDistance if (_this._downValid) { var _movement = _this.calculatePointersDistance(_this._downEvents[_this._downEvents.length - 1], event) * _this._devPxRatio; if (_movement > _this._movementThreshold) { _this._downValid = false; } } }); _defineProperty(_assertThisInitialized(_this), "onPointerUp", function (event) { if (event.pointerType == 'touch' && _this._input != INPUT.CURSOR) { var nTouch = _this._touchCurrent.length; for (var i = 0; i < nTouch; i++) { if (_this._touchCurrent[i].pointerId == event.pointerId) { _this._touchCurrent.splice(i, 1); _this._touchStart.splice(i, 1); break; } } switch (_this._input) { case INPUT.ONE_FINGER: case INPUT.ONE_FINGER_SWITCHED: //singleEnd window.removeEventListener('pointermove', _this.onPointerMove); window.removeEventListener('pointerup', _this.onPointerUp); _this._input = INPUT.NONE; _this.onSinglePanEnd(); break; case INPUT.TWO_FINGER: //doubleEnd _this.onDoublePanEnd(event); _this.onPinchEnd(event); _this.onRotateEnd(event); //switching to singleStart _this._input = INPUT.ONE_FINGER_SWITCHED; break; case INPUT.MULT_FINGER: if (_this._touchCurrent.length == 0) { window.removeEventListener('pointermove', _this.onPointerMove); window.removeEventListener('pointerup', _this.onPointerUp); //multCancel _this._input = INPUT.NONE; _this.onTriplePanEnd(); } break; } } else if (event.pointerType != 'touch' && _this._input == INPUT.CURSOR) { window.removeEventListener('pointermove', _this.onPointerMove); window.removeEventListener('pointerup', _this.onPointerUp); _this._input = INPUT.NONE; _this.onSinglePanEnd(); _this._button = -1; } if (event.isPrimary) { if (_this._downValid) { var downTime = event.timeStamp - _this._downEvents[_this._downEvents.length - 1].timeStamp; if (downTime <= _this._maxDownTime) { if (_this._nclicks == 0) { //first valid click detected _this._nclicks = 1; _this._clickStart = performance.now(); } else { var clickInterval = event.timeStamp - _this._clickStart; var movement = _this.calculatePointersDistance(_this._downEvents[1], _this._downEvents[0]) * _this._devPxRatio; if (clickInterval <= _this._maxInterval && movement <= _this._posThreshold) { //second valid click detected //fire double tap and reset values _this._nclicks = 0; _this._downEvents.splice(0, _this._downEvents.length); _this.onDoubleTap(event); } else { //new 'first click' _this._nclicks = 1; _this._downEvents.shift(); _this._clickStart = performance.now(); } } } else { _this._downValid = false; _this._nclicks = 0; _this._downEvents.splice(0, _this._downEvents.length); } } else { _this._nclicks = 0; _this._downEvents.splice(0, _this._downEvents.length); } } }); _defineProperty(_assertThisInitialized(_this), "onWheel", function (event) { if (_this.enabled && _this.enableZoom) { var modifier = null; if (event.ctrlKey || event.metaKey) { modifier = 'CTRL'; } else if (event.shiftKey) { modifier = 'SHIFT'; } var mouseOp = _this.getOpFromAction('WHEEL', modifier); if (mouseOp != null) { event.preventDefault(); _this.dispatchEvent(_startEvent); var notchDeltaY = 125; //distance of one notch of mouse wheel var sgn = event.deltaY / notchDeltaY; var size = 1; if (sgn > 0) { size = 1 / _this.scaleFactor; } else if (sgn < 0) { size = _this.scaleFactor; } switch (mouseOp) { case 'ZOOM': _this.updateTbState(STATE.SCALE, true); if (sgn > 0) { size = 1 / Math.pow(_this.scaleFactor, sgn); } else if (sgn < 0) { size = Math.pow(_this.scaleFactor, -sgn); } if (_this.cursorZoom && _this.enablePan) { var scalePoint; if (_this.camera.isOrthographicCamera) { scalePoint = _this.unprojectOnTbPlane(_this.camera, event.clientX, event.clientY, _this.domElement).applyQuaternion(_this.camera.quaternion).multiplyScalar(1 / _this.camera.zoom).add(_this._gizmos.position); } else if (_this.camera.isPerspectiveCamera) { scalePoint = _this.unprojectOnTbPlane(_this.camera, event.clientX, event.clientY, _this.domElement).applyQuaternion(_this.camera.quaternion).add(_this._gizmos.position); } _this.applyTransformMatrix(_this.scale(size, scalePoint)); } else { _this.applyTransformMatrix(_this.scale(size, _this._gizmos.position)); } if (_this._grid != null) { _this.disposeGrid(); _this.drawGrid(); } _this.updateTbState(STATE.IDLE, false); _this.dispatchEvent(_changeEvent); _this.dispatchEvent(_endEvent); break; case 'FOV': if (_this.camera.isPerspectiveCamera) { _this.updateTbState(STATE.FOV, true); //Vertigo effect // fov / 2 // |\ // | \ // | \ // x | \ // | \ // | \ // | _ _ _\ // y //check for iOs shift shortcut if (event.deltaX != 0) { sgn = event.deltaX / notchDeltaY; size = 1; if (sgn > 0) { size = 1 / Math.pow(_this.scaleFactor, sgn); } else if (sgn < 0) { size = Math.pow(_this.scaleFactor, -sgn); } } _this._v3_1.setFromMatrixPosition(_this._cameraMatrixState); var x = _this._v3_1.distanceTo(_this._gizmos.position); var xNew = x / size; //distance between camera and gizmos if scale(size, scalepoint) would be performed //check min and max distance xNew = _three.MathUtils.clamp(xNew, _this.minDistance, _this.maxDistance); var y = x * Math.tan(_three.MathUtils.DEG2RAD * _this.camera.fov * 0.5); //calculate new fov var newFov = _three.MathUtils.RAD2DEG * (Math.atan(y / xNew) * 2); //check min and max fov if (newFov > _this.maxFov) { newFov = _this.maxFov; } else if (newFov < _this.minFov) { newFov = _this.minFov; } var newDistance = y / Math.tan(_three.MathUtils.DEG2RAD * (newFov / 2)); size = x / newDistance; _this.setFov(newFov); _this.applyTransformMatrix(_this.scale(size, _this._gizmos.position, false)); } if (_this._grid != null) { _this.disposeGrid(); _this.drawGrid(); } _this.updateTbState(STATE.IDLE, false); _this.dispatchEvent(_changeEvent); _this.dispatchEvent(_endEvent); break; } } } }); _defineProperty(_assertThisInitialized(_this), "onKeyDown", function (event) { if (event.key == 'c') { if (event.ctrlKey || event.metaKey) { _this.copyState(); } } else if (event.key == 'v') { if (event.ctrlKey || event.metaKey) { _this.pasteState(); } } }); _defineProperty(_assertThisInitialized(_this), "onSinglePanStart", function (event, operation) { if (_this.enabled) { _this.dispatchEvent(_startEvent); _this.setCenter(event.clientX, event.clientY); switch (operation) { case 'PAN': if (!_this.enablePan) { return; } if (_this._animationId != -1) { cancelAnimationFrame(_this._animationId); _this._animationId = -1; _this._timeStart = -1; _this.activateGizmos(false); _this.dispatchEvent(_changeEvent); } _this.updateTbState(STATE.PAN, true); _this._startCursorPosition.copy(_this.unprojectOnTbPlane(_this.camera, _center.x, _center.y, _this.domElement)); if (_this.enableGrid) { _this.drawGrid(); _this.dispatchEvent(_changeEvent); } break; case 'ROTATE': if (!_this.enableRotate) { return; } if (_this._animationId != -1) { cancelAnimationFrame(_this._animationId); _this._animationId = -1; _this._timeStart = -1; } _this.updateTbState(STATE.ROTATE, true); _this._startCursorPosition.copy(_this.unprojectOnTbSurface(_this.camera, _center.x, _center.y, _this.domElement, _this._tbRadius)); _this.activateGizmos(true); if (_this.enableAnimations) { _this._timePrev = _this._timeCurrent = performance.now(); _this._angleCurrent = _this._anglePrev = 0; _this._cursorPosPrev.copy(_this._startCursorPosition); _this._cursorPosCurr.copy(_this._cursorPosPrev); _this._wCurr = 0; _this._wPrev = _this._wCurr; } _this.dispatchEvent(_changeEvent); break; case 'FOV': if (!_this.camera.isPerspectiveCamera || !_this.enableZoom) { return; } if (_this._animationId != -1) { cancelAnimationFrame(_this._animationId); _this._animationId = -1; _this._timeStart = -1; _this.activateGizmos(false); _this.dispatchEvent(_changeEvent); } _this.updateTbState(STATE.FOV, true); _this._startCursorPosition.setY(_this.getCursorNDC(_center.x, _center.y, _this.domElement).y * 0.5); _this._currentCursorPosition.copy(_this._startCursorPosition); break; case 'ZOOM': if (!_this.enableZoom) { return; } if (_this._animationId != -1) { cancelAnimationFrame(_this._animationId); _this._animationId = -1; _this._timeStart = -1; _this.activateGizmos(false); _this.dispatchEvent(_changeEvent); } _this.updateTbState(STATE.SCALE, true); _this._startCursorPosition.setY(_this.getCursorNDC(_center.x, _center.y, _this.domElement).y * 0.5); _this._currentCursorPosition.copy(_this._startCursorPosition); break; } } }); _defineProperty(_assertThisInitialized(_this), "onSinglePanMove", function (event, opState) { if (_this.enabled) { var restart = opState != _this._state; _this.setCenter(event.clientX, event.clientY); switch (opState) { case STATE.PAN: if (_this.enablePan) { if (restart) { //switch to pan operation _this.dispatchEvent(_endEvent); _this.dispatchEvent(_startEvent); _this.updateTbState(opState, true); _this._startCursorPosition.copy(_this.unprojectOnTbPlane(_this.camera, _center.x, _center.y, _this.domElement)); if (_this.enableGrid) { _this.drawGrid(); } _this.activateGizmos(false); } else { //continue with pan operation _this._currentCursorPosition.copy(_this.unprojectOnTbPlane(_this.camera, _center.x, _center.y, _this.domElement)); _this.applyTransformMatrix(_this.pan(_this._startCursorPosition, _this._currentCursorPosition)); } } break; case STATE.ROTATE: if (_this.enableRotate) { if (restart) { //switch to rotate operation _this.dispatchEvent(_endEvent); _this.dispatchEvent(_startEvent); _this.updateTbState(opState, true); _this._startCursorPosition.copy(_this.unprojectOnTbSurface(_this.camera, _center.x, _center.y, _this.domElement, _this._tbRadius)); if (_this.enableGrid) { _this.disposeGrid(); } _this.activateGizmos(true); } else { //continue with rotate operation _this._currentCursorPosition.copy(_this.unprojectOnTbSurface(_this.camera, _center.x, _center.y, _this.domElement, _this._tbRadius)); var distance = _this._startCursorPosition.distanceTo(_this._currentCursorPosition); var angle = _this._startCursorPosition.angleTo(_this._currentCursorPosition); var amount = Math.max(distance / _this._tbRadius, angle); //effective rotation angle _this.applyTransformMatrix(_this.rotate(_this.calculateRotationAxis(_this._startCursorPosition, _this._currentCursorPosition), amount)); if (_this.enableAnimations) { _this._timePrev = _this._timeCurrent; _this._timeCurrent = performance.now(); _this._anglePrev = _this._angleCurrent; _this._angleCurrent = amount; _this._cursorPosPrev.copy(_this._cursorPosCurr); _this._cursorPosCurr.copy(_this._currentCursorPosition); _this._wPrev = _this._wCurr; _this._wCurr = _this.calculateAngularSpeed(_this._anglePrev, _this._angleCurrent, _this._timePrev, _this._timeCurrent); } } } break; case STATE.SCALE: if (_this.enableZoom) { if (restart) { //switch to zoom operation _this.dispatchEvent(_endEvent); _this.dispatchEvent(_startEvent); _this.updateTbState(opState, true); _this._startCursorPosition.setY(_this.getCursorNDC(_center.x, _center.y, _this.domElement).y * 0.5); _this._currentCursorPosition.copy(_this._startCursorPosition); if (_this.enableGrid) { _this.disposeGrid(); } _this.activateGizmos(false); } else { //continue with zoom operation var screenNotches = 8; //how many wheel notches corresponds to a full screen pan _this._currentCursorPosition.setY(_this.getCursorNDC(_center.x, _center.y, _this.domElement).y * 0.5); var movement = _this._currentCursorPosition.y - _this._startCursorPosition.y; var size = 1; if (movement < 0) { size = 1 / Math.pow(_this.scaleFactor, -movement * screenNotches); } else if (movement > 0) { size = Math.pow(_this.scaleFactor, movement * screenNotches); } _this.applyTransformMatrix(_this.scale(size, _this._gizmos.position)); } } break; case STATE.FOV: if (_this.enableZoom && _this.camera.isPerspectiveCamera) { if (restart) { //switch to fov operation _this.dispatchEvent(_endEvent); _this.dispatchEvent(_startEvent); _this.updateTbState(opState, true); _this._startCursorPosition.setY(_this.getCursorNDC(_center.x, _center.y, _this.domElement).y * 0.5); _this._currentCursorPosition.copy(_this._startCursorPosition); if (_this.enableGrid) { _this.disposeGrid(); } _this.activateGizmos(false); } else { //continue with fov operation var _screenNotches = 8; //how many wheel notches corresponds to a full screen pan _this._currentCursorPosition.setY(_this.getCursorNDC(_center.x, _center.y, _this.domElement).y * 0.5); var _movement2 = _this._currentCursorPosition.y - _this._startCursorPosition.y; var _size = 1; if (_movement2 < 0) { _size = 1 / Math.pow(_this.scaleFactor, -_movement2 * _screenNotches); } else if (_movement2 > 0) { _size = Math.pow(_this.scaleFactor, _movement2 * _screenNotches); } _this._v3_1.setFromMatrixPosition(_this._cameraMatrixState); var x = _this._v3_1.distanceTo(_this._gizmos.position); var xNew = x / _size; //distance between camera and gizmos if scale(size, scalepoint) would be performed //check min and max distance xNew = _three.MathUtils.clamp(xNew, _this.minDistance, _this.maxDistance); var y = x * Math.tan(_three.MathUtils.DEG2RAD * _this._fovState * 0.5); //calculate new fov var newFov = _three.MathUtils.RAD2DEG * (Math.atan(y / xNew) * 2); //check min and max fov newFov = _three.MathUtils.clamp(newFov, _this.minFov, _this.maxFov); var newDistance = y / Math.tan(_three.MathUtils.DEG2RAD * (newFov / 2)); _size = x / newDistance; _this._v3_2.setFromMatrixPosition(_this._gizmoMatrixState); _this.setFov(newFov); _this.applyTransformMatrix(_this.scale(_size, _this._v3_2, false)); //adjusting distance _offset.copy(_this._gizmos.position).sub(_this.camera.position).normalize().multiplyScalar(newDistance / x); _this._m4_1.makeTranslation(_offset.x, _offset.y, _offset.z); } } break; } _this.dispatchEvent(_changeEvent); } }); _defineProperty(_assertThisInitialized(_this), "onSinglePanEnd", function () { if (_this._state == STATE.ROTATE) { if (!_this.enableRotate) { return; } if (_this.enableAnimations) { //perform rotation animation var deltaTime = performance.now() - _this._timeCurrent; if (deltaTime < 120) { var w = Math.abs((_this._wPrev + _this._wCurr) / 2); var self = _assertThisInitialized(_this); _this._animationId = window.requestAnimationFrame(function (t) { self.updateTbState(STATE.ANIMATION_ROTATE, true); var rotationAxis = self.calculateRotationAxis(self._cursorPosPrev, self._cursorPosCurr); self.onRotationAnim(t, rotationAxis, Math.min(w, self.wMax)); }); } else { //cursor has been standing still for over 120 ms since last movement _this.updateTbState(STATE.IDLE, false); _this.activateGizmos(false); _this.dispatchEvent(_changeEvent); } } else { _this.updateTbState(STATE.IDLE, false); _this.activateGizmos(false); _this.dispatchEvent(_changeEvent); } } else if (_this._state == STATE.PAN || _this._state == STATE.IDLE) { _this.updateTbState(STATE.IDLE, false); if (_this.enableGrid) { _this.disposeGrid(); } _this.activateGizmos(false); _this.dispatchEvent(_changeEvent); } _this.dispatchEvent(_endEvent); }); _defineProperty(_assertThisInitialized(_this), "onDoubleTap", function (event) { if (_this.enabled && _this.enablePan && _this.scene != null) { _this.dispatchEvent(_startEvent); _this.setCenter(event.clientX, event.clientY); var hitP = _this.unprojectOnObj(_this.getCursorNDC(_center.x, _center.y, _this.domElement), _this.camera); if (hitP != null && _this.enableAnimations) { var self = _assertThisInitialized(_this); if (_this._animationId != -1) { window.cancelAnimationFrame(_this._animationId); } _this._timeStart = -1; _this._animationId = window.requestAnimationFrame(function (t) { self.updateTbState(STATE.ANIMATION_FOCUS, true); self.onFocusAnim(t, hitP, self._cameraMatrixState, self._gizmoMatrixState); }); } else if (hitP != null && !_this.enableAnimations) { _this.updateTbState(STATE.FOCUS, true); _this.focus(hitP, _this.scaleFactor); _this.updateTbState(STATE.IDLE, false); _this.dispatchEvent(_changeEvent); } } _this.dispatchEvent(_endEvent); }); _defineProperty(_assertThisInitialized(_this), "onDoublePanStart", function () { if (_this.enabled && _this.enablePan) { _this.dispatchEvent(_startEvent); _this.updateTbState(STATE.PAN, true); _this.setCenter((_this._touchCurrent[0].clientX + _this._touchCurrent[1].clientX) / 2, (_this._touchCurrent[0].clientY + _this._touchCurrent[1].clientY) / 2); _this._startCursorPosition.copy(_this.unprojectOnTbPlane(_this.camera, _center.x, _center.y, _this.domElement, true)); _this._currentCursorPosition.copy(_this._startCursorPosition); _this.activateGizmos(false); } }); _defineProperty(_assertThisInitialized(_this), "onDoublePanMove", function () { if (_this.enabled && _this.enablePan) { _this.setCenter((_this._touchCurrent[0].clientX + _this._touchCurrent[1].clientX) / 2, (_this._touchCurrent[0].clientY + _this._touchCurrent[1].clientY) / 2); if (_this._state != STATE.PAN) { _this.updateTbState(STATE.PAN, true); _this._startCursorPosition.copy(_this._currentCursorPosition); } _this._currentCursorPosition.copy(_this.unprojectOnTbPlane(_this.camera, _center.x, _center.y, _this.domElement, true)); _this.applyTransformMatrix(_this.pan(_this._startCursorPosition, _this._currentCursorPosition, true)); _this.dispatchEvent(_changeEvent); } }); _defineProperty(_assertThisInitialized(_this), "onDoublePanEnd", function () { _this.updateTbState(STATE.IDLE, false); _this.dispatchEvent(_endEvent); }); _defineProperty(_assertThisInitialized(_this), "onRotateStart", function () { if (_this.enabled && _this.enableRotate) { _this.dispatchEvent(_startEvent); _this.updateTbState(STATE.ZROTATE, true); //this._startFingerRotation = event.rotation; _this._startFingerRotation = _this.getAngle(_this._touchCurrent[1], _this._touchCurrent[0]) + _this.getAngle(_this._touchStart[1], _this._touchStart[0]); _this._currentFingerRotation = _this._startFingerRotation; _this.camera.getWorldDirection(_this._rotationAxis); //rotation axis if (!_this.enablePan && !_this.enableZoom) { _this.activateGizmos(true); } } }); _defineProperty(_assertThisInitialized(_this), "onRotateMove", function () { if (_this.enabled && _this.enableRotate) { _this.setCenter((_this._touchCurrent[0].clientX + _this._touchCurrent[1].clientX) / 2, (_this._touchCurrent[0].clientY + _this._touchCurrent[1].clientY) / 2); var rotationPoint; if (_this._state != STATE.ZROTATE) { _this.updateTbState(STATE.ZROTATE, true); _this._startFingerRotation = _this._currentFingerRotation; } //this._currentFingerRotation = event.rotation; _this._currentFingerRotation = _this.getAngle(_this._touchCurrent[1], _this._touchCurrent[0]) + _this.getAngle(_this._touchStart[1], _this._touchStart[0]); if (!_this.enablePan) { rotationPoint = new _three.Vector3().setFromMatrixPosition(_this._gizmoMatrixState); } else { _this._v3_2.setFromMatrixPosition(_this._gizmoMatrixState); rotationPoint = _this.unprojectOnTbPlane(_this.camera, _center.x, _center.y, _this.domElement).applyQuaternion(_this.camera.quaternion).multiplyScalar(1 / _this.camera.zoom).add(_this._v3_2); } var amount = _three.MathUtils.DEG2RAD * (_this._startFingerRotation - _this._currentFingerRotation); _this.applyTransformMatrix(_this.zRotate(rotationPoint, amount)); _this.dispatchEvent(_changeEvent); } }); _defineProperty(_assertThisInitialized(_this), "onRotateEnd", function () { _this.updateTbState(STATE.IDLE, false); _this.activateGizmos(false); _this.dispatchEvent(_endEvent); }); _defineProperty(_assertThisInitialized(_this), "onPinchStart", function () { if (_this.enabled && _this.enableZoom) { _this.dispatchEvent(_startEvent); _this.updateTbState(STATE.SCALE, true); _this._startFingerDistance = _this.calculatePointersDistance(_this._touchCurrent[0], _this._touchCurrent[1]); _this._currentFingerDistance = _this._startFingerDistance; _this.activateGizmos(false); } }); _defineProperty(_assertThisInitialized(_this), "onPinchMove", function () { if (_this.enabled && _this.enableZoom) { _this.setCenter((_this._touchCurrent[0].clientX + _this._touchCurrent[1].clientX) / 2, (_this._touchCurrent[0].clientY + _this._touchCurrent[1].clientY) / 2); var minDistance = 12; //minimum distance between fingers (in css pixels) if (_this._state != STATE.SCALE) { _this._startFingerDistance = _this._currentFingerDistance; _this.updateTbState(STATE.SCALE, true); } _this._currentFingerDistance = Math.max(_this.calculatePointersDistance(_this._touchCurrent[0], _this._touchCurrent[1]), minDistance * _this._devPxRatio); var amount = _this._currentFingerDistance / _this._startFingerDistance; var scalePoint; if (!_this.enablePan) { scalePoint = _this._gizmos.position; } else { if (_this.camera.isOrthographicCamera) { scalePoint = _this.unprojectOnTbPlane(_this.camera, _center.x, _center.y, _this.domElement).applyQuaternion(_this.camera.quaternion).multiplyScalar(1 / _this.camera.zoom).add(_this._gizmos.position); } else if (_this.camera.isPerspectiveCamera) { scalePoint = _this.unprojectOnTbPlane(_this.camera, _center.x, _center.y, _this.domElement).applyQuaternion(_this.camera.quaternion).add(_this._gizmos.position); } } _this.applyTransformMatrix(_this.scale(amount, scalePoint)); _this.dispatchEvent(_changeEvent); } }); _defineProperty(_assertThisInitialized(_this), "onPinchEnd", function () { _this.updateTbState(STATE.IDLE, false); _this.dispatchEvent(_endEvent); }); _defineProperty(_assertThisInitialized(_this), "onTriplePanStart", function () { if (_this.enabled && _this.enableZoom) { _this.dispatchEvent(_startEvent); _this.updateTbState(STATE.SCALE, true); //const center = event.center; var clientX = 0; var clientY = 0; var nFingers = _this._touchCurrent.length; for (var i = 0; i < nFingers; i++) { clientX += _this._touchCurrent[i].clientX; clientY += _this._touchCurrent[i].clientY; } _this.setCenter(clientX / nFingers, clientY / nFingers); _this._startCursorPosition.setY(_this.getCursorNDC(_center.x, _center.y, _this.domElement).y * 0.5); _this._currentCursorPosition.copy(_this._startCursorPosition); } }); _defineProperty(_assertThisInitialized(_this), "onTriplePanMove", function () { if (_this.enabled && _this.enableZoom) { // fov / 2 // |\ // | \ // | \ // x | \ // | \ // | \ // | _ _ _\ // y //const center = event.center; var clientX = 0; var clientY = 0; var nFingers = _this._touchCurrent.length; for (var i = 0; i < nFingers; i++) { clientX += _this._touchCurrent[i].clientX; clientY += _this._touchCurrent[i].clientY; } _this.setCenter(clientX / nFingers, clientY / nFingers); var screenNotches = 8; //how many wheel notches corresponds to a full screen pan _this._currentCursorPosition.setY(_this.getCursorNDC(_center.x, _center.y, _this.domElement).y * 0.5); var movement = _this._currentCursorPosition.y - _this._startCursorPosition.y; var size = 1; if (movement < 0) { size = 1 / Math.pow(_this.scaleFactor, -movement * screenNotches); } else if (movement > 0) { size = Math.pow(_this.scaleFactor, movement * screenNotches); } _this._v3_1.setFromMatrixPosition(_this._cameraMatrixState); var x = _this._v3_1.distanceTo(_this._gizmos.position); var xNew = x / size; //distance between camera and gizmos if scale(size, scalepoint) would be performed //check min and max distance xNew = _three.MathUtils.clamp(xNew, _this.minDistance, _this.maxDistance); var y = x * Math.tan(_three.MathUtils.DEG2RAD * _this._fovState * 0.5); //calculate new fov var newFov = _three.MathUtils.RAD2DEG * (Math.atan(y / xNew) * 2); //check min and max fov newFov = _three.MathUtils.clamp(newFov, _this.minFov, _this.maxFov); var newDistance = y / Math.tan(_three.MathUtils.DEG2RAD * (newFov / 2)); size = x / newDistance; _this._v3_2.setFromMatrixPosition(_this._gizmoMatrixState); _this.setFov(newFov); _this.applyTransformMatrix(_this.scale(size, _this._v3_2, false)); //adjusting distance _offset.copy(_this._gizmos.position).sub(_this.camera.position).normalize().multiplyScalar(newDistance / x); _this._m4_1.makeTranslation(_offset.x, _offset.y, _offset.z); _this.dispatchEvent(_changeEvent); } }); _defineProperty(_assertThisInitialized(_this), "onTriplePanEnd", function () { _this.updateTbState(STATE.IDLE, false); _this.dispatchEvent(_endEvent); //this.dispatchEvent( _changeEvent ); }); _defineProperty(_assertThisInitialized(_this), "setCenter", function (clientX, clientY) { _center.x = clientX; _center.y = clientY; }); _defineProperty(_assertThisInitialized(_this), "initializeMouseActions", function () { _this.setMouseAction('PAN', 0, 'CTRL'); _this.setMouseAction('PAN', 2); _this.setMouseAction('ROTATE', 0); _this.setMouseAction('ZOOM', 'WHEEL'); _this.setMouseAction('ZOOM', 1); _this.setMouseAction('FOV', 'WHEEL', 'SHIFT'); _this.setMouseAction('FOV', 1, 'SHIFT'); }); _defineProperty(_assertThisInitialized(_this), "compareMouseAction", function (action1, action2) { if (action1.operation == action2.operation) { if (action1.mouse == action2.mouse && action1.key == action2.key) { return true; } else { return false; } } else { return false; } }); _defineProperty(_assertThisInitialized(_this), "setMouseAction", function (operation, mouse) { var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var operationInput = ['PAN', 'ROTATE', 'ZOOM', 'FOV']; var mouseInput = [0, 1, 2, 'WHEEL']; var keyInput = ['CTRL', 'SHIFT', null]; var state; if (!operationInput.includes(operation) || !mouseInput.includes(mouse) || !keyInput.includes(key)) { //invalid parameters return false; } if (mouse == 'WHEEL') { if (operation != 'ZOOM' && operation != 'FOV') { //cannot associate 2D operation to 1D input return false; } } switch (operation) { case 'PAN': state = STATE.PAN; break; case 'ROTATE': state = STATE.ROTATE; break; case 'ZOOM': state = STATE.SCALE; break; case 'FOV': state = STATE.FOV; break; } var action = { operation: operation, mouse: mouse, key: key, state: state }; for (var i = 0; i < _this.mouseActions.length; i++) { if (_this.mouseActions[i].mouse == action.mouse && _this.mouseActions[i].key == action.key) { _this.mouseActions.splice(i, 1, action); return true; } } _this.mouseActions.push(action); return true; }); _defineProperty(_assertThisInitialized(_this), "unsetMouseAction", function (mouse) { var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; for (var i = 0; i < _this.mouseActions.length; i++) { if (_this.mouseActions[i].mouse == mouse && _this.mouseActions[i].key == key) { _this.mouseActions.splice(i, 1); return true; } } return false; }); _defineProperty(_assertThisInitialized(_this), "getOpFromAction", function (mouse, key) { var action; for (var i = 0; i < _this.mouseActions.length; i++) { action = _this.mouseActions[i]; if (action.mouse == mouse && action.key == key) { return action.operation; } } if (key != null) { for (var _i = 0; _i < _this.mouseActions.length; _i++) { action = _this.mouseActions[_i]; if (action.mouse == mouse && action.key == null) { return action.operation; } } } return null; }); _defineProperty(_assertThisInitialized(_this), "getOpStateFromAction", function (mouse, key) { var action; for (var i = 0; i < _this.mouseActions.length; i++) { action = _this.mouseActions[i]; if (action.mouse == mouse && action.key == key) { return action.state; } } if (key != null) { for (var _i2 = 0; _i2 < _this.mouseActions.length; _i2++) { action = _this.mouseActions[_i2]; if (action.mouse == mouse && action.key == null) { return action.state; } } } return null; }); _defineProperty(_assertThisInitialized(_this), "getAngle", function (p1, p2) { return Math.atan2(p2.clientY - p1.clientY, p2.clientX - p1.clientX) * 180 / Math.PI; }); _defineProperty(_assertThisInitialized(_this), "updateTouchEvent", function (event) { for (var i = 0; i < _this._touchCurrent.length; i++) { if (_this._touchCurrent[i].pointerId == event.pointerId) { _this._touchCurrent.splice(i, 1, event); break; } } }); _defineProperty(_assertThisInitialized(_this), "calculateAngularSpeed", function (p0, p1, t0, t1) { var s = p1 - p0; var t = (t1 - t0) / 1000; if (t == 0) { return 0; } return s / t; }); _defineProperty(_assertThisInitialized(_this), "calculatePointersDistance", function (p0, p1) { return Math.sqrt(Math.pow(p1.clientX - p0.clientX, 2) + Math.pow(p1.clientY - p0.clientY, 2)); }); _defineProperty(_assertThisInitialized(_this), "calculateRotationAxis", function (vec1, vec2) { _this._rotationMatrix.extractRotation(_this._cameraMatrixState); _this._quat.setFromRotationMatrix(_this._rotationMatrix); _this._rotationAxis.crossVectors(vec1, vec2).applyQuaternion(_this._quat); return _this._rotationAxis.normalize().clone(); }); _defineProperty(_assertThisInitialized(_this), "calculateTbRadius", function (camera) { var distance = camera.position.distanceTo(_this._gizmos.position); if (camera.type == 'PerspectiveCamera') { var halfFovV = _three.MathUtils.DEG2RAD * camera.fov * 0.5; //vertical fov/2 in radians var halfFovH = Math.atan(camera.aspect * Math.tan(halfFovV)); //horizontal fov/2 in radians return Math.tan(Math.min(halfFovV, halfFovH)) * distance * _this.radiusFactor; } else if (camera.type == 'OrthographicCamera') { return Math.min(camera.top, camera.right) * _this.radiusFactor; } }); _defineProperty(_assertThisInitialized(_this), "focus", function (point, size) { var amount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; //move center of camera (along with gizmos) towards point of interest _offset.copy(point).sub(_this._gizmos.position).multiplyScalar(amount); _this._translationMatrix.makeTranslation(_offset.x, _offset.y, _offset.z); var gizmoStateTemp = _this._gizmoMatrixState.clone(); _this._gizmoMatrixState.premultiply(_this._translationMatrix); _this._gizmoMatrixState.decompose(_this._gizmos.position, _this._gizmos.quaternion, _this._gizmos.scale); var cameraStateTemp = _this._cameraMatrixState.clone(); _this._cameraMatrixState.premultiply(_this._translationMatrix); _this._cameraMatrixState.decompose(_this.camera.position, _this.camera.quaternion, _this.camera.scale); //apply zoom if (_this.enableZoom) { _this.applyTransformMatrix(_this.scale(size, _this._gizmos.position)); } _this._gizmoMatrixState.copy(gizmoStateTemp); _this._cameraMatrixState.copy(cameraStateTemp); }); _defineProperty(_assertThisInitialized(_this), "drawGrid", function () { if (_this.scene != null) { var color = 0x888888; var multiplier = 3; var size, divisions, maxLength, tick; if (_this.camera.isOrthographicCamera) { var width = _this.camera.right - _this.camera.left; var height = _this.camera.bottom - _this.camera.top; maxLength = Math.max(width, height); tick = maxLength / 20; size = maxLength / _this.camera.zoom * multiplier; divisions = size / tick * _this.camera.zoom; } else if (_this.camera.isPerspectiveCamera) { var distance = _this.camera.position.distanceTo(_this._gizmos.position); var halfFovV = _three.MathUtils.DEG2RAD * _this.camera.fov * 0.5; var halfFovH = Math.atan(_this.camera.aspect * Math.tan(halfFovV)); maxLength = Math.tan(Math.max(halfFovV, halfFovH)) * distance * 2; tick = maxLength / 20; size = maxLength * multiplier; divisions = size / tick; } if (_this._grid == null) { _this._grid = new _three.GridHelper(size, divisions, color, color); _this._grid.position.copy(_this._gizmos.position); _this._gridPosition.copy(_this._grid.position); _this._grid.quaternion.copy(_this.camera.quaternion); _this._grid.rotateX(Math.PI * 0.5); _this.scene.add(_this._grid); } } }); _defineProperty(_assertThisInitialized(_this), "dispose", function () { if (_this._animationId != -1) { window.cancelAnimationFrame(_this._animationId); } _this.domElement.removeEventListener('pointerdown', _this.onPointerDown); _this.domElement.removeEventListener('pointercancel', _this.onPointerCancel); _this.domElement.removeEventListener('wheel', _this.onWheel); _this.domElement.removeEventListener('contextmenu', _this.onContextMenu); window.removeEventListener('pointermove', _this.onPointerMove); window.removeEventListener('pointerup', _this.onPointerUp); window.removeEventListener('resize', _this.onWindowResize); window.removeEventListener('keydown', _this.onKeyDown); if (_this.scene !== null) _this.scene.remove(_this._gizmos); _this.disposeGrid(); }); _defineProperty(_assertThisInitialized(_this), "disposeGrid", function () { if (_this._grid != null && _this.scene != null) { _this.scene.remove(_this._grid); _this._grid = null; } }); _defineProperty(_assertThisInitialized(_this), "easeOutCubic", function (t) { return 1 - Math.pow(1 - t, 3); }); _defineProperty(_assertThisInitialized(_this), "activateGizmos", function (isActive) { var gizmoX = _this._gizmos.children[0]; var gizmoY = _this._gizmos.children[1]; var gizmoZ = _this._gizmos.children[2]; if (isActive) { gizmoX.material.setValues({ opacity: 1 }); gizmoY.material.setValues({ opacity: 1 }); gizmoZ.material.setValues({ opacity: 1 }); } else { gizmoX.material.setValues({ opacity: 0.6 }); gizmoY.material.setValues({ opacity: 0.6 }); gizmoZ.material.setValues({ opacity: 0.6 }); } }); _defineProperty(_assertThisInitialized(_this), "getCursorNDC", function (cursorX, cursorY, canvas) { var canvasRect = canvas.getBoundingClientRect(); _this._v2_1.setX((cursorX - canvasRect.left) / canvasRect.width * 2 - 1); _this._v2_1.setY((canvasRect.bottom - cursorY) / canvasRect.height * 2 - 1); return _this._v2_1.clone(); }); _defineProperty(_assertThisInitialized(_this), "getCursorPosition", function (cursorX, cursorY, canvas) { _this._v2_1.copy(_this.getCursorNDC(cursorX, cursorY, canvas)); _this._v2_1.x *= (_this.camera.right - _this.camera.left) * 0.5; _this._v2_1.y *= (_this.camera.top - _this.camera.bottom) * 0.5; return _this._v2_1.clone(); }); _defineProperty(_assertThisInitialized(_this), "setCamera", function (camera) { camera.lookAt(_this.target); camera.updateMatrix(); //setting state if (camera.type == 'PerspectiveCamera') { _this._fov0 = camera.fov; _this._fovState = camera.fov; } _this._cameraMatrixState0.copy(camera.matrix); _this._cameraMatrixState.copy(_this._cameraMatrixState0); _this._cameraProjectionState.copy(camera.projectionMatrix); _this._zoom0 = camera.zoom; _this._zoomState = _this._zoom0; _this._initialNear = camera.near; _this._nearPos0 = camera.position.distanceTo(_this.target) - camera.near; _this._nearPos = _this._initialNear; _this._initialFar = camera.far; _this._farPos0 = camera.position.distanceTo(_this.target) - camera.far; _this._farPos = _this._initialFar; _this._up0.copy(camera.up); _this._upState.copy(camera.up); _this.camera = camera; _this.camera.updateProjectionMatrix(); //making gizmos _this._tbRadius = _this.calculateTbRadius(camera); _this.makeGizmos(_this.target, _this._tbRadius); }); _defineProperty(_assertThisInitialized(_this), "makeGizmos", function (tbCenter, tbRadius) { var curve = new _three.EllipseCurve(0, 0, tbRadius, tbRadius); var points = curve.getPoints(_this._curvePts); //geometry var curveGeometry = new _three.BufferGeometry().setFromPoints(points); //material var curveMaterialX = new _three.LineBasicMaterial({ color: 0xff8080, fog: false, transparent: true, opacity: 0.6 }); var curveMaterialY = new _three.LineBasicMaterial({ color: 0x80ff80, fog: false, transparent: true, opacity: 0.6 }); var curveMaterialZ = new _three.LineBasicMaterial({ color: 0x8080ff, fog: false, transparent: true, opacity: 0.6 }); //line var gizmoX = new _three.Line(curveGeometry, curveMaterialX); var gizmoY = new _three.Line(curveGeometry, curveMaterialY); var gizmoZ = new _three.Line(curveGeometry, curveMaterialZ); var rotation = Math.PI * 0.5; gizmoX.rotation.x = rotation; gizmoY.rotation.y = rotation; //setting state _this._gizmoMatrixState0.identity().setPosition(tbCenter); _this._gizmoMatrixState.copy(_this._gizmoMatrixState0); if (_this.camera.zoom != 1) { //adapt gizmos size to camera zoom var size = 1 / _this.camera.zoom; _this._scaleMatrix.makeScale(size, size, size); _this._translationMatrix.makeTranslation(-tbCenter.x, -tbCenter.y, -tbCenter.z); _this._gizmoMatrixState.premultiply(_this._translationMatrix).premultiply(_this._scaleMatrix); _this._translationMatrix.makeTranslation(tbCenter.x, tbCenter.y, tbCenter.z); _this._gizmoMatrixState.premultiply(_this._translationMatrix); } _this._gizmoMatrixState.decompose(_this._gizmos.position, _this._gizmos.quaternion, _this._gizmos.scale); _this._gizmos.clear(); _this._gizmos.add(gizmoX); _this._gizmos.add(gizmoY); _this._gizmos.add(gizmoZ); }); _defineProperty(_assertThisInitialized(_this), "onFocusAnim", function (time, point, cameraMatrix, gizmoMatrix) { if (_this._timeStart == -1) { //animation start _this._timeStart = time; } if (_this._state == STATE.ANIMATION_FOCUS) { var deltaTime = time - _this._timeStart; var animTime = deltaTime / _this.focusAnimationTime; _this._gizmoMatrixState.copy(gizmoMatrix); if (animTime >= 1) { //animation end _this._gizmoMatrixState.decompose(_this._gizmos.position, _this._gizmos.quaternion, _this._gizmos.scale); _this.focus(point, _this.scaleFactor); _this._timeStart = -1; _this.updateTbState(STATE.IDLE, false); _this.activateGizmos(false); _this.dispatchEvent(_changeEvent); } else { var amount = _this.easeOutCubic(animTime); var size = 1 - amount + _this.scaleFactor * amount; _this._gizmoMatrixState.decompose(_this._gizmos.position, _this._gizmos.quaternion, _this._gizmos.scale); _this.focus(point, size, amount); _this.dispatchEvent(_changeEvent); var self = _assertThisInitialized(_this); _this._animationId = window.requestAnimationFrame(function (t) { self.onFocusAnim(t, point, cameraMatrix, gizmoMatrix.clone()); }); } } else { //interrupt animation _this._animationId = -1; _this._timeStart = -1; } }); _defineProperty(_assertThisInitialized(_this), "onRotationAnim", function (time, rotationAxis, w0) { if (_this._timeStart == -1) { //animation start _this._anglePrev = 0; _this._angleCurrent = 0; _this._timeStart = time; } if (_this._state == STATE.ANIMATION_ROTATE) { //w = w0 + alpha * t var deltaTime = (time - _this._timeStart) / 1000; var w = w0 + -_this.dampingFactor * deltaTime; if (w > 0) { //tetha = 0.5 * alpha * t^2 + w0 * t + tetha0 _this._angleCurrent = 0.5 * -_this.dampingFactor * Math.pow(deltaTime, 2) + w0 * deltaTime + 0; _this.applyTransformMatrix(_this.rotate(rotationAxis, _this._angleCurrent)); _this.dispatchEvent(_changeEvent); var self = _assertThisInitialized(_this); _this._animationId = window.requestAnimationFrame(function (t) { self.onRotationAnim(t, rotationAxis, w0); }); } else { _this._animationId = -1; _this._timeStart = -1; _this.updateTbState(STATE.IDLE, false); _this.activateGizmos(false); _this.dispatchEvent(_changeEvent); } } else { //interrupt animation _this._animationId = -1; _this._timeStart = -1; if (_this._state != STATE.ROTATE) { _this.activateGizmos(false); _this.dispatchEvent(_changeEvent); } } }); _defineProperty(_assertThisInitialized(_this), "pan", function (p0, p1) { var adjust = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var movement = p0.clone().sub(p1); if (_this.camera.isOrthographicCamera) { //adjust movement amount movement.multiplyScalar(1 / _this.camera.zoom); } else if (_this.camera.isPerspectiveCamera && adjust) { //adjust movement amount _this._v3_1.setFromMatrixPosition(_this._cameraMatrixState0); //camera's initial position _this._v3_2.setFromMatrixPosition(_this._gizmoMatrixState0); //gizmo's initial position var distanceFactor = _this._v3_1.distanceTo(_this._v3_2) / _this.camera.position.distanceTo(_this._gizmos.position); movement.multiplyScalar(1 / distanceFactor); } _this._v3_1.set(movement.x, movement.y, 0).applyQuaternion(_this.camera.quaternion); _this._m4_1.makeTranslation(_this._v3_1.x, _this._v3_1.y, _this._v3_1.z); _this.setTransformationMatrices(_this._m4_1, _this._m4_1); return _transformation; }); _defineProperty(_assertThisInitialized(_this), "reset", function () { _this.camera.zoom = _this._zoom0; if (_this.camera.isPerspectiveCamera) { _this.camera.fov = _this._fov0; } _this.camera.near = _this._nearPos; _this.camera.far = _this._farPos; _this._cameraMatrixState.copy(_this._cameraMatrixState0); _this._cameraMatrixState.decompose(_this.camera.position, _this.camera.quaternion, _this.camera.scale); _this.camera.up.copy(_this._up0); _this.camera.updateMatrix(); _this.camera.updateProjectionMatrix(); _this._gizmoMatrixState.copy(_this._gizmoMatrixState0); _this._gizmoMatrixState0.decompose(_this._gizmos.position, _this._gizmos.quaternion, _this._gizmos.scale); _this._gizmos.updateMatrix(); _this._tbRadius = _this.calculateTbRadius(_this.camera); _this.makeGizmos(_this._gizmos.position, _this._tbRadius); _this.camera.lookAt(_this._gizmos.position); _this.updateTbState(STATE.IDLE, false); _this.dispatchEvent(_changeEvent); }); _defineProperty(_assertThisInitialized(_this), "rotate", function (axis, angle) { var point = _this._gizmos.position; //rotation center _this._translationMatrix.makeTranslation(-point.x, -point.y, -point.z); _this._rotationMatrix.makeRotationAxis(axis, -angle); //rotate camera _this._m4_1.makeTranslation(point.x, point.y, point.z); _this._m4_1.multiply(_this._rotationMatrix); _this._m4_1.multiply(_this._translationMatrix); _this.setTransformationMatrices(_this._m4_1); return _transformation; }); _defineProperty(_assertThisInitialized(_this), "copyState", function () { var state; if (_this.camera.isOrthographicCamera) { state = JSON.stringify({ arcballState: { cameraFar: _this.camera.far, cameraMatrix: _this.camera.matrix, cameraNear: _this.camera.near, cameraUp: _this.camera.up, cameraZoom: _this.camera.zoom, gizmoMatrix: _this._gizmos.matrix } }); } else if (_this.camera.isPerspectiveCamera) { state = JSON.stringify({ arcballState: { cameraFar: _this.camera.far, cameraFov: _this.camera.fov, cameraMatrix: _this.camera.matrix, cameraNear: _this.camera.near, cameraUp: _this.camera.up, cameraZoom: _this.camera.zoom, gizmoMatrix: _this._gizmos.matrix } }); } navigator.clipboard.writeText(state); }); _defineProperty(_assertThisInitialized(_this), "pasteState", function () { var self = _assertThisInitialized(_this); navigator.clipboard.readText().then(function resolved(value) { self.setStateFromJSON(value); }); }); _defineProperty(_assertThisInitialized(_this), "saveState", function () { _this._cameraMatrixState0.copy(_this.camera.matrix); _this._gizmoMatrixState0.copy(_this._gizmos.matrix); _this._nearPos = _this.camera.near; _this._farPos = _this.camera.far; _this._zoom0 = _this.camera.zoom; _this._up0.copy(_this.camera.up); if (_this.camera.isPerspectiveCamera) { _this._fov0 = _this.camera.fov; } }); _defineProperty(_assertThisInitialized(_this), "scale", function (size, point) { var scaleGizmos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var scalePoint = point.clone(); var sizeInverse = 1 / size; if (_this.camera.isOrthographicCamera) { //camera zoom _this.camera.zoom = _this._zoomState; _this.camera.zoom *= size; //check min and max zoom if (_this.camera.zoom > _this.maxZoom) { _this.camera.zoom = _this.maxZoom; sizeInverse = _this._zoomState / _this.maxZoom; } else if (_this.camera.zoom < _this.minZoom) { _this.camera.zoom = _this.minZoom; sizeInverse = _this._zoomState / _this.minZoom; } _this.camera.updateProjectionMatrix(); _this._v3_1.setFromMatrixPosition(_this._gizmoMatrixState); //gizmos position //scale gizmos so they appear in the same spot having the same dimension _this._scaleMatrix.makeScale(sizeInverse, sizeInverse, sizeInverse); _this._translationMatrix.makeTranslation(-_this._v3_1.x, -_this._v3_1.y, -_this._v3_1.z); _this._m4_2.makeTranslation(_this._v3_1.x, _this._v3_1.y, _this._v3_1.z).multiply(_this._scaleMatrix); _this._m4_2.multiply(_this._translationMatrix); //move camera and gizmos to obtain pinch effect scalePoint.sub(_this._v3_1); var amount = scalePoint.clone().multiplyScalar(sizeInverse); scalePoint.sub(amount); _this._m4_1.makeTranslation(scalePoint.x, scalePoint.y, scalePoint.z); _this._m4_2.premultiply(_this._m4_1); _this.setTransformationMatrices(_this._m4_1, _this._m4_2); return _transformation; } else if (_this.camera.isPerspectiveCamera) { _this._v3_1.setFromMatrixPosition(_this._cameraMatrixState); _this._v3_2.setFromMatrixPosition(_this._gizmoMatrixState); //move camera var distance = _this._v3_1.distanceTo(scalePoint); var _amount = distance - distance * sizeInverse; //check min and max distance var newDistance = distance - _amount; if (newDistance < _this.minDistance) { sizeInverse = _this.minDistance / distance; _amount = distance - distance * sizeInverse; } else if (newDistance > _this.maxDistance) { sizeInverse = _this.maxDistance / distance; _amount = distance - distance * sizeInverse; } _offset.copy(scalePoint).sub(_this._v3_1).normalize().multiplyScalar(_amount); _this._m4_1.makeTranslation(_offset.x, _offset.y, _offset.z); if (scaleGizmos) { //scale gizmos so they appear in the same spot having the same dimension var pos = _this._v3_2; distance = pos.distanceTo(scalePoint); _amount = distance - distance * sizeInverse; _offset.copy(scalePoint).sub(_this._v3_2).normalize().multiplyScalar(_amount); _this._translationMatrix.makeTranslation(pos.x, pos.y, pos.z); _this._scaleMatrix.makeScale(sizeInverse, sizeInverse, sizeInverse); _this._m4_2.makeTranslation(_offset.x, _offset.y, _offset.z).multiply(_this._translationMatrix); _this._m4_2.multiply(_this._scaleMatrix); _this._translationMatrix.makeTranslation(-pos.x, -pos.y, -pos.z); _this._m4_2.multiply(_this._translationMatrix); _this.setTransformationMatrices(_this._m4_1, _this._m4_2); } else { _this.setTransformationMatrices(_this._m4_1); } return _transformation; } }); _defineProperty(_assertThisInitialized(_this), "setFov", function (value) { if (_this.camera.isPerspectiveCamera) { _this.camera.fov = _three.MathUtils.clamp(value, _this.minFov, _this.maxFov); _this.camera.updateProjectionMatrix(); } }); _defineProperty(_assertThisInitialized(_this), "setTarget", function (x, y, z) { _this.target.set(x, y, z); _this._gizmos.position.set(x, y, z); //for correct radius calculation _this._tbRadius = _this.calculateTbRadius(_this.camera); _this.makeGizmos(_this.target, _this._tbRadius); _this.camera.lookAt(_this.target); }); _defineProperty(_assertThisInitialized(_this), "zRotate", function (point, angle) { _this._rotationMatrix.makeRotationAxis(_this._rotationAxis, angle); _this._translationMatrix.makeTranslation(-point.x, -point.y, -point.z); _this._m4_1.makeTranslation(point.x, point.y, point.z); _this._m4_1.multiply(_this._rotationMatrix); _this._m4_1.multiply(_this._translationMatrix); _this._v3_1.setFromMatrixPosition(_this._gizmoMatrixState).sub(point); //vector from rotation center to gizmos position _this._v3_2.copy(_this._v3_1).applyAxisAngle(_this._rotationAxis, angle); //apply rotation _this._v3_2.sub(_this._v3_1); _this._m4_2.makeTranslation(_this._v3_2.x, _this._v3_2.y, _this._v3_2.z); _this.setTransformationMatrices(_this._m4_1, _this._m4_2); return _transformation; }); _defineProperty(_assertThisInitialized(_this), "unprojectOnObj", function (cursor, camera) { var raycaster = _this.getRaycaster(); raycaster.near = camera.near; raycaster.far = camera.far; raycaster.setFromCamera(cursor, camera); var intersect = raycaster.intersectObjects(_this.scene.children, true); for (var i = 0; i < intersect.length; i++) { if (intersect[i].object.uuid != _this._gizmos.uuid && intersect[i].face != null) { return intersect[i].point.clone(); } } return null; }); _defineProperty(_assertThisInitialized(_this), "unprojectOnTbSurface", function (camera, cursorX, cursorY, canvas, tbRadius) { if (camera.type == 'OrthographicCamera') { _this._v2_1.copy(_this.getCursorPosition(cursorX, cursorY, canvas)); _this._v3_1.set(_this._v2_1.x, _this._v2_1.y, 0); var x2 = Math.pow(_this._v2_1.x, 2); var y2 = Math.pow(_this._v2_1.y, 2); var r2 = Math.pow(_this._tbRadius, 2); if (x2 + y2 <= r2 * 0.5) { //intersection with sphere _this._v3_1.setZ(Math.sqrt(r2 - (x2 + y2))); } else { //intersection with hyperboloid _this._v3_1.setZ(r2 * 0.5 / Math.sqrt(x2 + y2)); } return _this._v3_1; } else if (camera.type == 'PerspectiveCamera') { //unproject cursor on the near plane _this._v2_1.copy(_this.getCursorNDC(cursorX, cursorY, canvas)); _this._v3_1.set(_this._v2_1.x, _this._v2_1.y, -1); _this._v3_1.applyMatrix4(camera.projectionMatrixInverse); var rayDir = _this._v3_1.clone().normalize(); //unprojected ray direction var cameraGizmoDistance = camera.position.distanceTo(_this._gizmos.position); var radius2 = Math.pow(tbRadius, 2); // camera // |\ // | \ // | \ // h | \ // | \ // | \ // _ _ | _ _ _\ _ _ near plane // l var h = _this._v3_1.z; var l = Math.sqrt(Math.pow(_this._v3_1.x, 2) + Math.pow(_this._v3_1.y, 2)); if (l == 0) { //ray aligned with camera rayDir.set(_this._v3_1.x, _this._v3_1.y, tbRadius); return rayDir; } var m = h / l; var q = cameraGizmoDistance; /* * calculate intersection point between unprojected ray and trackball surface *|y = m * x + q *|x^2 + y^2 = r^2 * * (m^2 + 1) * x^2 + (2 * m * q) * x + q^2 - r^2 = 0 */ var a = Math.pow(m, 2) + 1; var b = 2 * m * q; var c = Math.pow(q, 2) - radius2; var delta = Math.pow(b, 2) - 4 * a * c; if (delta >= 0) { //intersection with sphere _this._v2_1.setX((-b - Math.sqrt(delta)) / (2 * a)); _this._v2_1.setY(m * _this._v2_1.x + q); var angle = _three.MathUtils.RAD2DEG * _this._v2_1.angle(); if (angle >= 45) { //if angle between intersection point and X' axis is >= 45°, return that point //otherwise, calculate intersection point with hyperboloid var _rayLength = Math.sqrt(Math.pow(_this._v2_1.x, 2) + Math.pow(cameraGizmoDistance - _this._v2_1.y, 2)); rayDir.multiplyScalar(_rayLength); rayDir.z += cameraGizmoDistance; return rayDir; } } //intersection with hyperboloid /* *|y = m * x + q *|y = (1 / x) * (r^2 / 2) * * m * x^2 + q * x - r^2 / 2 = 0 */ a = m; b = q; c = -radius2 * 0.5; delta = Math.pow(b, 2) - 4 * a * c; _this._v2_1.setX((-b - Math.sqrt(delta)) / (2 * a)); _this._v2_1.setY(m * _this._v2_1.x + q); var rayLength = Math.sqrt(Math.pow(_this._v2_1.x, 2) + Math.pow(cameraGizmoDistance - _this._v2_1.y, 2)); rayDir.multiplyScalar(rayLength); rayDir.z += cameraGizmoDistance; return rayDir; } }); _defineProperty(_assertThisInitialized(_this), "unprojectOnTbPlane", function (camera, cursorX, cursorY, canvas) { var initialDistance = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; if (camera.type == 'OrthographicCamera') { _this._v2_1.copy(_this.getCursorPosition(cursorX, cursorY, canvas)); _this._v3_1.set(_this._v2_1.x, _this._v2_1.y, 0); return _this._v3_1.clone(); } else if (camera.type == 'PerspectiveCamera') { _this._v2_1.copy(_this.getCursorNDC(cursorX, cursorY, canvas)); //unproject cursor on the near plane _this._v3_1.set(_this._v2_1.x, _this._v2_1.y, -1); _this._v3_1.applyMatrix4(camera.projectionMatrixInverse); var rayDir = _this._v3_1.clone().normalize(); //unprojected ray direction // camera // |\ // | \ // | \ // h | \ // | \ // | \ // _ _ | _ _ _\ _ _ near plane // l var h = _this._v3_1.z; var l = Math.sqrt(Math.pow(_this._v3_1.x, 2) + Math.pow(_this._v3_1.y, 2)); var cameraGizmoDistance; if (initialDistance) { cameraGizmoDistance = _this._v3_1.setFromMatrixPosition(_this._cameraMatrixState0).distanceTo(_this._v3_2.setFromMatrixPosition(_this._gizmoMatrixState0)); } else { cameraGizmoDistance = camera.position.distanceTo(_this._gizmos.position); } /* * calculate intersection point between unprojected ray and the plane *|y = mx + q *|y = 0 * * x = -q/m */ if (l == 0) { //ray aligned with camera rayDir.set(0, 0, 0); return rayDir; } var m = h / l; var q = cameraGizmoDistance; var x = -q / m; var rayLength = Math.sqrt(Math.pow(q, 2) + Math.pow(x, 2)); rayDir.multiplyScalar(rayLength); rayDir.z = 0; return rayDir; } }); _defineProperty(_assertThisInitialized(_this), "updateMatrixState", function () { //update camera and gizmos state _this._cameraMatrixState.copy(_this.camera.matrix); _this._gizmoMatrixState.copy(_this._gizmos.matrix); if (_this.camera.isOrthographicCamera) { _this._cameraProjectionState.copy(_this.camera.projectionMatrix); _this.camera.updateProjectionMatrix(); _this._zoomState = _this.camera.zoom; } else if (_this.camera.isPerspectiveCamera) { _this._fovState = _this.camera.fov; } }); _defineProperty(_assertThisInitialized(_this), "updateTbState", function (newState, updateMatrices) { _this._state = newState; if (updateMatrices) { _this.updateMatrixState(); } }); _defineProperty(_assertThisInitialized(_this), "update", function () { var EPS = 0.000001; //check min/max parameters if (_this.camera.isOrthographicCamera) { //check zoom if (_this.camera.zoom > _this.maxZoom || _this.camera.zoom < _this.minZoom) { var newZoom = _three.MathUtils.clamp(_this.camera.zoom, _this.minZoom, _this.maxZoom); _this.applyTransformMatrix(_this.scale(newZoom / _this.camera.zoom, _this._gizmos.position, true)); } } else if (_this.camera.isPerspectiveCamera) { //check distance var distance = _this.camera.position.distanceTo(_this._gizmos.position); if (distance > _this.maxDistance + EPS || distance < _this.minDistance - EPS) { var newDistance = _three.MathUtils.clamp(distance, _this.minDistance, _this.maxDistance); _this.applyTransformMatrix(_this.scale(newDistance / distance, _this._gizmos.position)); _this.updateMatrixState(); } //check fov if (_this.camera.fov < _this.minFov || _this.camera.fov > _this.maxFov) { _this.camera.fov = _three.MathUtils.clamp(_this.camera.fov, _this.minFov, _this.maxFov); _this.camera.updateProjectionMatrix(); } var oldRadius = _this._tbRadius; _this._tbRadius = _this.calculateTbRadius(_this.camera); if (oldRadius < _this._tbRadius - EPS || oldRadius > _this._tbRadius + EPS) { var scale = (_this._gizmos.scale.x + _this._gizmos.scale.y + _this._gizmos.scale.z) / 3; var newRadius = _this._tbRadius / scale; var curve = new _three.EllipseCurve(0, 0, newRadius, newRadius); var points = curve.getPoints(_this._curvePts); var curveGeometry = new _three.BufferGeometry().setFromPoints(points); for (var gizmo in _this._gizmos.children) { _this._gizmos.children[gizmo].geometry = curveGeometry; } } } _this.camera.lookAt(_this._gizmos.position); }); _defineProperty(_assertThisInitialized(_this), "setStateFromJSON", function (json) { var state = JSON.parse(json); if (state.arcballState != undefined) { _this._cameraMatrixState.fromArray(state.arcballState.cameraMatrix.elements); _this._cameraMatrixState.decompose(_this.camera.position, _this.camera.quaternion, _this.camera.scale); _this.camera.up.copy(state.arcballState.cameraUp); _this.camera.near = state.arcballState.cameraNear; _this.camera.far = state.arcballState.cameraFar; _this.camera.zoom = state.arcballState.cameraZoom; if (_this.camera.isPerspectiveCamera) { _this.camera.fov = state.arcballState.cameraFov; } _this._gizmoMatrixState.fromArray(state.arcballState.gizmoMatrix.elements); _this._gizmoMatrixState.decompose(_this._gizmos.position, _this._gizmos.quaternion, _this._gizmos.scale); _this.camera.updateMatrix(); _this.camera.updateProjectionMatrix(); _this._gizmos.updateMatrix(); _this._tbRadius = _this.calculateTbRadius(_this.camera); var gizmoTmp = new _three.Matrix4().copy(_this._gizmoMatrixState0); _this.makeGizmos(_this._gizmos.position, _this._tbRadius); _this._gizmoMatrixState0.copy(gizmoTmp); _this.camera.lookAt(_this._gizmos.position); _this.updateTbState(STATE.IDLE, false); _this.dispatchEvent(_changeEvent); } }); _this.camera = null; _this.domElement = domElement; _this.scene = scene; _this.target = new _three.Vector3(0, 0, 0); _this.radiusFactor = 0.67; _this.mouseActions = []; _this._mouseOp = null; //global vectors and matrices that are used in some operations to avoid creating new objects every time (e.g. every time cursor moves) _this._v2_1 = new _three.Vector2(); _this._v3_1 = new _three.Vector3(); _this._v3_2 = new _three.Vector3(); _this._m4_1 = new _three.Matrix4(); _this._m4_2 = new _three.Matrix4(); _this._quat = new _three.Quaternion(); //transformation matrices _this._translationMatrix = new _three.Matrix4(); //matrix for translation operation _this._rotationMatrix = new _three.Matrix4(); //matrix for rotation operation _this._scaleMatrix = new _three.Matrix4(); //matrix for scaling operation _this._rotationAxis = new _three.Vector3(); //axis for rotate operation //camera state _this._cameraMatrixState = new _three.Matrix4(); _this._cameraProjectionState = new _three.Matrix4(); _this._fovState = 1; _this._upState = new _three.Vector3(); _this._zoomState = 1; _this._nearPos = 0; _this._farPos = 0; _this._gizmoMatrixState = new _three.Matrix4(); //initial values _this._up0 = new _three.Vector3(); _this._zoom0 = 1; _this._fov0 = 0; _this._initialNear = 0; _this._nearPos0 = 0; _this._initialFar = 0; _this._farPos0 = 0; _this._cameraMatrixState0 = new _three.Matrix4(); _this._gizmoMatrixState0 = new _three.Matrix4(); //pointers array _this._button = -1; _this._touchStart = []; _this._touchCurrent = []; _this._input = INPUT.NONE; //two fingers touch interaction _this._switchSensibility = 32; //minimum movement to be performed to fire single pan start after the second finger has been released _this._startFingerDistance = 0; //distance between two fingers _this._currentFingerDistance = 0; _this._startFingerRotation = 0; //amount of rotation performed with two fingers _this._currentFingerRotation = 0; //double tap _this._devPxRatio = 0; _this._downValid = true; _this._nclicks = 0; _this._downEvents = []; _this._downStart = 0; //pointerDown time _this._clickStart = 0; //first click time _this._maxDownTime = 250; _this._maxInterval = 300; _this._posThreshold = 24; _this._movementThreshold = 24; //cursor positions _this._currentCursorPosition = new _three.Vector3(); _this._startCursorPosition = new _three.Vector3(); //grid _this._grid = null; //grid to be visualized during pan operation _this._gridPosition = new _three.Vector3(); //gizmos _this._gizmos = new _three.Group(); _this._curvePts = 128; //animations _this._timeStart = -1; //initial time _this._animationId = -1; //focus animation _this.focusAnimationTime = 500; //duration of focus animation in ms //rotate animation _this._timePrev = 0; //time at which previous rotate operation has been detected _this._timeCurrent = 0; //time at which current rotate operation has been detected _this._anglePrev = 0; //angle of previous rotation _this._angleCurrent = 0; //angle of current rotation _this._cursorPosPrev = new _three.Vector3(); //cursor position when previous rotate operation has been detected _this._cursorPosCurr = new _three.Vector3(); //cursor position when current rotate operation has been detected _this._wPrev = 0; //angular velocity of the previous rotate operation _this._wCurr = 0; //angular velocity of the current rotate operation //parameters _this.adjustNearFar = false; _this.scaleFactor = 1.1; //zoom/distance multiplier _this.dampingFactor = 25; _this.wMax = 20; //maximum angular velocity allowed _this.enableAnimations = true; //if animations should be performed _this.enableGrid = false; //if grid should be showed during pan operation _this.cursorZoom = false; //if wheel zoom should be cursor centered _this.minFov = 5; _this.maxFov = 90; _this.enabled = true; _this.enablePan = true; _this.enableRotate = true; _this.enableZoom = true; _this.enableGizmos = true; _this.minDistance = 0; _this.maxDistance = Infinity; _this.minZoom = 0; _this.maxZoom = Infinity; //trackball parameters _this._tbRadius = 1; //FSA _this._state = STATE.IDLE; _this.setCamera(_camera); if (_this.scene != null) { _this.scene.add(_this._gizmos); } _this.domElement.style.touchAction = 'none'; _this._devPxRatio = window.devicePixelRatio; _this.initializeMouseActions(); _this.domElement.addEventListener('contextmenu', _this.onContextMenu); _this.domElement.addEventListener('wheel', _this.onWheel); _this.domElement.addEventListener('pointerdown', _this.onPointerDown); _this.domElement.addEventListener('pointercancel', _this.onPointerCancel); window.addEventListener('keydown', _this.onKeyDown); window.addEventListener('resize', _this.onWindowResize); return _this; } //listeners _createClass(ArcballControls, [{ key: "applyTransformMatrix", value: /** * Apply a transformation matrix, to the camera and gizmos * @param {Object} transformation Object containing matrices to apply to camera and gizmos */ function applyTransformMatrix(transformation) { if (transformation.camera != null) { this._m4_1.copy(this._cameraMatrixState).premultiply(transformation.camera); this._m4_1.decompose(this.camera.position, this.camera.quaternion, this.camera.scale); this.camera.updateMatrix(); //update camera up vector if (this._state == STATE.ROTATE || this._state == STATE.ZROTATE || this._state == STATE.ANIMATION_ROTATE) { this.camera.up.copy(this._upState).applyQuaternion(this.camera.quaternion); } } if (transformation.gizmos != null) { this._m4_1.copy(this._gizmoMatrixState).premultiply(transformation.gizmos); this._m4_1.decompose(this._gizmos.position, this._gizmos.quaternion, this._gizmos.scale); this._gizmos.updateMatrix(); } if (this._state == STATE.SCALE || this._state == STATE.FOCUS || this._state == STATE.ANIMATION_FOCUS) { this._tbRadius = this.calculateTbRadius(this.camera); if (this.adjustNearFar) { var cameraDistance = this.camera.position.distanceTo(this._gizmos.position); var bb = new _three.Box3(); bb.setFromObject(this._gizmos); var sphere = new _three.Sphere(); bb.getBoundingSphere(sphere); var adjustedNearPosition = Math.max(this._nearPos0, sphere.radius + sphere.center.length()); var regularNearPosition = cameraDistance - this._initialNear; var minNearPos = Math.min(adjustedNearPosition, regularNearPosition); this.camera.near = cameraDistance - minNearPos; var adjustedFarPosition = Math.min(this._farPos0, -sphere.radius + sphere.center.length()); var regularFarPosition = cameraDistance - this._initialFar; var minFarPos = Math.min(adjustedFarPosition, regularFarPosition); this.camera.far = cameraDistance - minFarPos; this.camera.updateProjectionMatrix(); } else { var update = false; if (this.camera.near != this._initialNear) { this.camera.near = this._initialNear; update = true; } if (this.camera.far != this._initialFar) { this.camera.far = this._initialFar; update = true; } if (update) { this.camera.updateProjectionMatrix(); } } } } /** * Calculate the angular speed * @param {Number} p0 Position at t0 * @param {Number} p1 Position at t1 * @param {Number} t0 Initial time in milliseconds * @param {Number} t1 Ending time in milliseconds */ }, { key: "setGizmosVisible", value: /** * Set gizmos visibility * @param {Boolean} value Value of gizmos visibility */ function setGizmosVisible(value) { this._gizmos.visible = value; this.dispatchEvent(_changeEvent); } /** * Set gizmos radius factor and redraws gizmos * @param {Float} value Value of radius factor */ }, { key: "setTbRadius", value: function setTbRadius(value) { this.radiusFactor = value; this._tbRadius = this.calculateTbRadius(this.camera); var curve = new _three.EllipseCurve(0, 0, this._tbRadius, this._tbRadius); var points = curve.getPoints(this._curvePts); var curveGeometry = new _three.BufferGeometry().setFromPoints(points); for (var gizmo in this._gizmos.children) { this._gizmos.children[gizmo].geometry = curveGeometry; } this.dispatchEvent(_changeEvent); } /** * Creates the rotation gizmos matching trackball center and radius * @param {Vector3} tbCenter The trackball center * @param {number} tbRadius The trackball radius */ }, { key: "setTransformationMatrices", value: /** * Set values in transformation object * @param {Matrix4} camera Transformation to be applied to the camera * @param {Matrix4} gizmos Transformation to be applied to gizmos */ function setTransformationMatrices() { var camera = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var gizmos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; if (camera != null) { if (_transformation.camera != null) { _transformation.camera.copy(camera); } else { _transformation.camera = camera.clone(); } } else { _transformation.camera = null; } if (gizmos != null) { if (_transformation.gizmos != null) { _transformation.gizmos.copy(gizmos); } else { _transformation.gizmos = gizmos.clone(); } } else { _transformation.gizmos = null; } } /** * Rotate camera around its direction axis passing by a given point by a given angle * @param {Vector3} point The point where the rotation axis is passing trough * @param {Number} angle Angle in radians * @returns The computed transormation matix */ }, { key: "getRaycaster", value: function getRaycaster() { return _raycaster; } /** * Unproject the cursor on the 3D object surface * @param {Vector2} cursor Cursor coordinates in NDC * @param {Camera} camera Virtual camera * @returns {Vector3} The point of intersection with the model, if exist, null otherwise */ }]); return ArcballControls; }(_three.EventDispatcher); _exports.ArcballControls = ArcballControls; });